วิธีโหลดแอปพลิเคชันที่ทำงานอยู่ทั้งหมดจากพื้นที่สว็อปไปเป็น RAM ได้อย่างไร


20

หากเดสก์ท็อปของฉันมีหน่วยความจำไม่เพียงพอและทำการแลกเปลี่ยนเป็นจำนวนมากฉันจะปล่อยให้ฟรีหรือฆ่าแอปพลิเคชันที่เสีย RAM แต่หลังจากนั้นเดสก์ท็อป / แอปพลิเคชันทั้งหมดของฉันถูกเปลี่ยนและช้ามากคุณรู้วิธี "unswap" (โหลดจากพื้นที่สว็อปเป็น RAM) เดสก์ท็อป / แอปพลิเคชันของฉันหรือไม่


แทนที่จะปลดล็อกทั้งระบบโดยใช้swapon/ swapoff(ตามคำตอบที่ยอมรับในปัจจุบันแนะนำ) คุณอาจต้องการยกเลิกการสลับตัวจัดการการแสดงผลและลูก ๆ ทั้งหมดโดยการทิ้งความทรงจำในกระบวนการของพวกเขา (ซึ่งบังคับให้ยกเลิกการสลับ) โปรดดูเพิ่มเติมที่ “ วิธีการบังคับใช้กระบวนการ zsh ที่สับเปลี่ยนเพื่อแลกเปลี่ยนใน”บน stackoverflow
zrajm

คำตอบ:


16

ถ้าคุณมีแรมเพียงพอจริง ๆ อีกครั้งคุณสามารถใช้ลำดับนี้ (เป็น root):

$ swapoff -a
$ swapon -a

(เพื่อบังคับให้สลับอย่างชัดเจนในทุกแอปพลิเคชันของคุณ)

(สมมติว่าคุณใช้ linux)


แม้ว่าคุณจะไม่ทำ IIRC มันจะทำการย้ายข้อมูลให้ได้มากที่สุด ในขณะที่มันอาจสร้างความเสียหายแคช & co บางครั้งมันมีประโยชน์
Maciej Piechotka

18

สคริปต์ไพ ธ อนที่รวดเร็วและสกปรกต่อไปนี้จะทิ้งหน่วยความจำของกระบวนการเพื่อ stdout สิ่งนี้มีผลข้างเคียงของการโหลดเพจที่ถูกสลับหรือไฟล์ที่แม็พ เรียกว่าcat_proc_mem 123 456 789ตำแหน่งที่อาร์กิวเมนต์เป็น ID กระบวนการ

สคริปต์นี้ใช้เฉพาะกับ Linux อย่างสมบูรณ์ มันอาจจะปรับให้เข้ากับระบบอื่น ๆ ที่มี/procโครงสร้างคล้ายกัน(Solaris?) แต่ลืมเกี่ยวกับการทำงานบนเช่น * BSD แม้ใน Linux คุณอาจต้องเปลี่ยนนิยามของc_pid_tและค่านิยมของและPTRACE_ATTACH PTRACE_DETACHนี่เป็นบทพิสูจน์หลักฐานของสคริปต์ซึ่งไม่ได้หมายถึงเป็นตัวอย่างของวิธีปฏิบัติในการเขียนโปรแกรมที่ดี ใช้ความเสี่ยงของคุณเอง

/proc/$pid/memลินุกซ์ทำให้ความทรงจำของกระบวนการที่มีอยู่เป็น สามารถอ่านช่วงที่อยู่บางช่วงเท่านั้น /proc/$pid/mapsช่วงนี้สามารถพบได้โดยการอ่านข้อมูลการทำแผนที่หน่วยความจำจากแฟ้มข้อความ The-ไฟล์หลอก/proc/$pid/memไม่สามารถอ่านได้โดยกระบวนการทั้งหมดที่มีสิทธิ์ในการอ่าน: ptrace(PTRACE_ATTACH, $pid)กระบวนการผู้อ่านจะต้องมีการเรียกว่า

#!/usr/bin/env python
import ctypes, re, sys

## Partial interface to ptrace(2), only for PTRACE_ATTACH and PTRACE_DETACH.
c_ptrace = ctypes.CDLL("libc.so.6").ptrace
c_pid_t = ctypes.c_int32 # This assumes pid_t is int32_t
c_ptrace.argtypes = [ctypes.c_int, c_pid_t, ctypes.c_void_p, ctypes.c_void_p]
def ptrace(attach, pid):
    op = ctypes.c_int(16 if attach else 17) #PTRACE_ATTACH or PTRACE_DETACH
    c_pid = c_pid_t(pid)
    null = ctypes.c_void_p()
    err = c_ptrace(op, c_pid, null, null)
    if err != 0: raise SysError, 'ptrace', err

## Parse a line in /proc/$pid/maps. Return the boundaries of the chunk
## the read permission character.
def maps_line_range(line):
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    return [int(m.group(1), 16), int(m.group(2), 16), m.group(3)]

## Dump the readable chunks of memory mapped by a process
def cat_proc_mem(pid):
    ## Apparently we need to ptrace(PTRACE_ATTACH, $pid) to read /proc/$pid/mem
    ptrace(True, int(pid))
    ## Read the memory maps to see what address ranges are readable
    maps_file = open("/proc/" + pid + "/maps", 'r')
    ranges = map(maps_line_range, maps_file.readlines())
    maps_file.close()
    ## Read the readable mapped ranges
    mem_file = open("/proc/" + pid + "/mem", 'r', 0)
    for r in ranges:
        if r[2] == 'r':
            mem_file.seek(r[0])
            chunk = mem_file.read(r[1] - r[0])
            print chunk,
    mem_file.close()
    ## Cleanup
    ptrace(False, int(pid))

if __name__ == "__main__":
    for pid in sys.argv[1:]:
        cat_proc_mem(pid)

ดูเพิ่มเติมข้อมูลเพิ่มเติมเกี่ยวกับ/proc/$pid/mem

unswap () {
  cat_proc_mem "$@" >/dev/null
}

2
นี่เป็นหนึ่งในสิ่งที่ยอดเยี่ยมที่สุดที่ฉันเคยเห็นจากการแลกเปลี่ยนสแต็ค ความรุ่งโรจน์สำหรับการโพสต์นี้! มีนักเก็ตที่ดีมากมายที่จะดึงออกมาจากสิ่งนี้
ด่าน

Unformatunately ฉันไม่สามารถทำให้สคริปต์นี้ทำงานได้ ด้วย python 2 จะแสดงข้อผิดพลาดว่าค่า r [0] ใหญ่เกินไป ใน python 3 (หลังจากแก้ไขปัญหาเล็กน้อย) ฉันได้รับ OSError: [Errno 5] ข้อผิดพลาดอินพุต / เอาท์พุตที่ chunk = mem_file.read (r [1] - r [0]) และโปรแกรมที่ฉันใช้กับแฮงค์ทั้งสอง กรณี
barteks2x

@ Barteks2x ฉันขอโทษฉันยังไม่มีเวลาทำข้อผิดพลาดสคริปต์นี้ มันใช้งานได้สำหรับฉันอย่างน้อยในเครื่องที่ไม่มีข้อ จำกัด ด้านความปลอดภัยมากเกินไป (เทคนิคใช้อินเทอร์เฟซการตรวจแก้จุดบกพร่องบางอย่างที่ปิดใช้งานในการตั้งค่าที่แข็งตัว) โปรแกรมถูกระงับในขณะที่กำลังติดตามส่ง SIGCONT ( kill -CONT 1234ที่ 1234 เป็น PID) เพื่อดำเนินการต่อ
Gilles 'หยุดความชั่วร้าย'

@ Barteks2x: ฉันได้เพิ่มการตรวจสอบข้อผิดพลาดบางอย่างที่นี่ สิ่งนี้ทำให้สคริปต์ทำงานได้แม้บน IOErrors จาก / dev / dri / card0 และ OverflowErrors จาก [vsyscall] (นอกจากนี้ยังพิมพ์สิ่งที่เป็นปัญหาพื้นที่)
hackerb9

6

เพื่อความสมบูรณ์ GDB สามารถดัมพ์อิมเมจกระบวนการ ฉันไม่ได้ตรวจสอบว่ามันยกเลิกการสลับ แต่ต้อง --- ไม่มีวิธีอื่นในการอ่านหน่วยความจำกระบวนการทั้งหมด:
gdb -p $mypid
ตามด้วย
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core


3
gcore $pidนอกจากนี้ยังพร้อมใช้งานนอก gdb (ตามสคริปต์กระดาษห่อเล็ก)
Tobu

gcore ไม่มีวิธีเขียนไปยัง / dev / null ซึ่งเป็นสิ่งที่คุณต้องการหากคุณพยายามบังคับให้กระบวนการกลับเข้าสู่หน่วยความจำ อย่างไรก็ตามคุณสามารถทำได้ด้วยคำสั่งเดียวเช่น: gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
hackerb9

0

swapon / swapoff จะล้างพื้นที่สวอปของคุณอย่างสมบูรณ์ แต่คุณสามารถปล่อยบางส่วนผ่านระบบไฟล์ / proc ได้เช่นกัน คุณต้องการแรก:

# To free pagecache
echo 1 > /proc/sys/vm/drop_caches

# To free dentries and inodes
echo 2 > /proc/sys/vm/drop_caches

# To free pagecache, dentries and inodes
echo 3 > /proc/sys/vm/drop_caches

ผ่านhttp://linux-mm.org/Drop_Caches


3
หน่วยความจำสลับคือตามนิยามไม่ใช่แคช การทิ้งแคชนั้นไม่น่าจะเปลี่ยนแปลงอะไรในการแลกเปลี่ยน นอกจากนี้ควรใช้ sysctl แทนการเขียนทับไฟล์ในระบบไฟล์ proc โดยตรง sysctl vm.drop_caches=X. นอกจากนี้ sysctl ยังง่ายกว่า sudo
Juliano

@julian หน่วยความจำเสมือน = ram + swap iirc ทั้งแอปพลิเคชันและแคชใช้หน่วยความจำเสมือน อย่างไรก็ตามฉันคิดว่า op ต้องการล้างทุกอย่างแต่แคชจากการแลกเปลี่ยนเนื่องจากฉันสงสัยว่าสิ่งเหล่านั้นมีผลกระทบต่อเขาจริงๆ
xenoterracide

@xenoterracide: แคชใช้งานได้จริงในหน่วยความจำ RAM เท่านั้น มันไม่มีประโยชน์ที่จะเก็บแคชในการสลับมันเป็นสิ่งที่ตรงกันข้าม Swap เป็นหน่วยความจำช้าที่ใช้เมื่อระบบสั้นบนแรมจริง แคชรวดเร็วใช้หน่วยความจำเมื่อระบบมีความอุดมสมบูรณ์ของ RAM
Juliano

@ Juliano ใช่ฉันรู้ แต่ฉันเชื่อว่าพวกเขาทั้งสองถูกเก็บไว้โดยใช้หน่วยความจำเสมือนแม้ว่าเป็นไปได้ว่าแคชจะถูกเก็บไว้ใน RAM เท่านั้น การปล่อยแคชอย่างตรงไปตรงมาไม่สมเหตุสมผลเลย
xenoterracide
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.