If my desktop run out of memory and swaps a lot then I free or kill the application wasting my RAM. But, after that, all my desktop/applications have been swapped and are horribly slow, do you know a way to "unswap" (reload from swap space into RAM) my desktop/applications?
4 Answers
The following quick-and-dirty python script dumps the memory of a process to stdout. This has the side effect of loading any swapped out page or mapped file. Call it as cat_proc_mem 123 456 789
where the arguments are process IDs.
This script is completely specific to Linux. It may be adaptable to other systems with a similar /proc
structure (Solaris?), but forget about running it on e.g. *BSD. Even on Linux, you may need to change the definition of c_pid_t
and the values of PTRACE_ATTACH
and PTRACE_DETACH
. This is a proof-of-principle script, not meant as an example of good programming practices. Use at your own risk.
Linux makes the memory of a process available as /proc/$pid/mem
. Only certain address ranges are readable. These ranges can be found by reading the memory mapping information from the text file /proc/$pid/maps
. The pseudo-file /proc/$pid/mem
cannot be read by all processes that have the permission to read it: the reader process must have called 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)
See also more information on /proc/$pid/mem
.
unswap () {
cat_proc_mem "$@" >/dev/null
}

- 635

- 829,060
-
3This is seriously one of the coolest things I've ever seen on stack exchange. Kudos for posting this! There are so many good nuggets to pull from this. – Dan Nov 08 '15 at 04:40
-
Unformatunately I wasn't able to get this script working. With python 2 it shows error that the value r[0] is too big. On python 3 (after fixing a few minor issues) I get OSError: [Errno 5] Input/output error at chunk = mem_file.read(r[1] - r[0]) and the program I used it on hangs in both cases. – barteks2x Mar 21 '17 at 13:35
-
@Barteks2x I'm sorry, I don't have the time right now to make this script error-proof. It does work for me, at least on machines that don't have too many security restrictions (the technique uses some debugging interfaces that are disabled on hardened setups). The program is suspended while it's being traced, send it a SIGCONT (
kill -CONT 1234
where 1234 is the PID) to resume it. – Gilles 'SO- stop being evil' Mar 21 '17 at 14:47 -
@Barteks2x: I've added some error checking here. This makes the script work even on IOErrors from /dev/dri/card0 and OverflowErrors from [vsyscall]. (It also prints out what the problem area was). – hackerb9 Jul 24 '17 at 17:57
-
If you don't want to write Python to read all the process memory and force it to swap in, you can use a short
gdb
script to do the same thing. See the script I posted under “How to force a swapped-out zsh process to swap in?” on stackoverflow. – Ian D. Allen Nov 02 '21 at 07:30
If you really have enough RAM available again you can use this sequence (as root):
$ swapoff -a
$ swapon -a
(to force the explicit swap-in of all your applications)
(assuming that you are using linux)

- 57,532
-
Even if you don't IIRC it will move as much data as possible. While it may damage cache & co. it is sometimes useful. – Maja Piechotka Jan 21 '11 at 22:32
Just for completeness, GDB can dump process image. I didn't check that it unswaps it, but it has to---there's no other way to read the whole process memory:
gdb -p $mypid
followed by
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core

- 71
-
4
-
1gcore has no way to write to /dev/null, which is what you'd want if you were trying to force a process back into memory. However, you can do it in a single command like so:
gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
– hackerb9 Jul 24 '17 at 18:11
swapon/swapoff will completely clear your swap space, but you can free some of it via the /proc file system too. You want the first one:
# 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

- 15,393
-
3Swap memory is, by definition, not cache. Dropping the caches is very unlikely to change anything in the swap. Also, it is preferable to use sysctl instead of directly writing over files in the proc filesystem.
sysctl vm.drop_caches=X
. Also, sysctl is easier to sudo. – Juliano Jan 21 '11 at 23:59 -
@julian virtual memory = ram + swap iirc. Both applications and caches use virtual memory. However I think that the op needs to clear everything but caches from swap, as I doubt those are really what's effecting him. – xenoterracide Jan 22 '11 at 08:17
-
@xenoterracide: caches only make sense in real, RAM memory. It is pointless to store cache in the swap, they are complete opposites. Swap is slow memory used when the system is short on physical RAM; cache is fast memory used when the system has plenty of unused physical RAM. – Juliano Jan 22 '11 at 12:49
-
1@juliano yes I know, but I believe they are both stored using virtual memory, though it's possible that caches only get stored in RAM. honestly dropping the caches makes no sense here, imo. – xenoterracide Jan 22 '11 at 13:58
swapon
/swapoff
(as the currently accepted answer suggests), you might want to unswap your display manager and all its children by dumping their process memories (which force unswapping). See also “How to force a swapped-out zsh process to swap in?” on stackoverflow. – zrajm Dec 13 '13 at 10:30