I have an idea.
So, I’ve run into some issues with OS X where it will start swapping, even though there is more than enough physical RAM available. I’m assuming this has to do with the OS deciding certain processes have been idle for long enough; it will pre-emptively swap them out with the assumption of a need for new, soon-to-be “things” requiring memory. This would give the user the perception that their machine loads up things faster when said “things” need to be loaded. That could be total BS on my part, but until I have a full technical explanation of it, that’s the story I’m going to stick to.
Now, I’m used to Linux, where you can set /proc/sys/vm/swappiness=0 and effectively stop swapping altogether. As long as there’s enough physical memory available, it will keep using it. If you run out, then OOM kill (assuming you haven’t disabled it via /proc/sys/vm/oom-kill) will come and start playing whack-a-mole with your processes. Sweet. This is good.
Since OS X doesn’t have this, what *does* it have? Well, it has a process called dynamic_pager, which oversees the management of swap (and swap files). There are two files we’re interested in here:
/sbin/dynamic_pager
/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist
The binary is obvious, but the LaunchDaemon plist is what we’re really interested in here. This is what tells dynamic_pager to kick off at launch. Now, the plist is in binary format, so to really get a look (from Terminal, unless you use the plist Editor), you can convert it to XML:
plutil -convert xml1 com.apple.dynamic_pager.plist
From there, the contents of the file will be something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnableTransactions</key>
<true/>
<key>HopefullyExitsLast</key>
<true/>
<key>Label</key>
<string>com.apple.dynamic_pager</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/sbin/dynamic_pager</string>
<string>-F</string>
<string>/private/var/vm/swapfile</string>
</array>
</dict>
</plist>
Fantastic! By the way, to convert back to binary when you’re done, you can do this:
plutil -convert binary com.apple.dynamic_pager.plist
Now that we’re looking at our plist, you’ll notice the config setting for -F /private/var/vm/swapfile. This is the base name used by dynamic_pager for when it needs to create a new swapfile. If you do a ps, you’ll notice it running:
[chet@cilantro ~]$ ps ax | grep dynamic_pager
39 ?? Ss 0:00.02 /sbin/dynamic_pager -F /private/var/vm/swapfile
And if you check out /private/var/vm:
[chet@cilantro ~]$ ls -lh /private/var/vm/
-rw------- 1 root wheel 64M Jul 19 22:02 swapfile0
-rw------- 1 root wheel 64M Jul 23 21:38 swapfile1
-rw------- 1 root wheel 128M Jul 23 21:38 swapfile2
As you can see, dynamic_pager is alive and well, managing a set of swap files on my local disk. Side note about the listing above: as the need for swap increases (or decreases) with activity, dynamic_pager will take the liberty of dynamically changing the swapfile size for you. You can also specify the -S flag in your plist to specify a static file size.
In any case, here’s where the fun starts: I don’t know about you, but the disk in my MacBook Pro isn’t anything super-amazing. Maybe it’s on a 3Gb/sec SATA channel, but it’s a 5400rpm drive, and random writes usually yield somewhere around 12MB/sec. Sequential writes will hit about 60MB/sec at times, but lets be honest, random is what we should be caring about; they’re nothing spectacular.
So, when I’m in the middle of working on something, have a few Flash widgets running, doing who knows what, and I start to experience the lovely effects of swapping, it’s not always the best experience. On top of slowing things down, it’s also adding a lot of extra physical load to the disk. Poopy. I wish there was a way to decouple swap from my physical root disk, and possibly put it somewhere that might help out swap performance a bit. Oh wait, I have a thought!
Thanks to the designers at Apple, who graciously added an SD card slot to the latest line of MacBook Pro’s, we now have an option for swap: offload it to an SD card! Now, a plain old SD card might not be the best (even a class 10 would only give you 10MB/sec max, and under real world conditions it’s obviously going to be worse.. about 2MB/sec), but with the latest SDXC technology, Kingston, Toshiba (and others) have developed cards hitting between 50-60MB/sec on writes, which is very similar to the sequential writes on our local disk. Again, under real-world, random usage, it’s going to be less, but should be relatively similar to the random writes of our local disk. To try it out, just slide in your SDXC card, and update your plist to something like the following:
<string>/sbin/dynamic_pager</string>
<string>-F</string>
<string>/Volumes/sdxc_swap/swapfile</string>
After that, restart your dynamic_pager process, and you should be good to go, enjoying an offloaded swap, and totally burn out your SDXC card
That being said, I’d like to mention a couple of things. First, I don’t have a high performance SDXC card of my own for testing, so performance mileage may vary depending on the card. I know Toshiba is targeting their SDXC cards for use in Netbooks, which is great; it gives us an glimmer of hope that their cards are built for some relatively heavy duty lifting- more than your standard camera SD card; maybe you won’t burn it out as quickly after all!
Another thing to point out is that the high performance cards we’re discussing are all relatively larger.. 32GB or greater in size. Chances are you’ll [hopefully] never hit this in swap. However, dynamic_pager will also take care of dumping out a sleepimage file to the swap space, which will be up to however many GB of RAM you may have; take that into consideration when picking a card. You’ll probably still have leftover space, but just a word of advice.
That being said, putting your sleepimage on an SDXC card is actually nice in the sense of security. Put your machine to sleep, pop your SDXC card out, and you basically have locked your laptop down in terms of a thief being able to try and yank whatever you were working on. There are threads out there about people dumping sleep/hibernate images and stealing sensitive data, so this is a nice little side effect of offloading swap to a little card.
In any case, that’s all for now. It was a thought I had the other day, so I figured I would share the idea with others. Maybe some people will think it sucks, but I think it’s kind of fun. If you have a card and would like to dump back some performance data to me, that would be awesome (ie: test via Xbench or the like). And, if I ever get my own card worth testing, I’ll post an update on how it went! If you’d also like to tell me how dumb I am, that’s okay too; I’m used to it. Enjoy!



