I have been able to move Apple's virtual memory swapfiles to a dedicated partition on my hard drive up until now. The technique I have been using is described in a thread on forums.macosxhints.com.

However, with the developer preview of Snow Leopard, this method no longer works. Does anyone know how it could be done with the new OS?

Update: I have marked dblu's answer as accepted even though it didn't quite work because he gave excellent, detailed instructions and because his suggestion to use plutil ultimately pointed me in the right direction. The complete, working solution is posted here in the question because I don't have enough reputation to edit the accepted answer.

Update #2: Changed the procedure to illustrate ekl's technique, which greatly simplifies the whole thing by eliminating the need for an intermediate shell script:

Complete solution:

1. Open Terminal and make a backup copy of Apple's default dynamic_pager.plist:

4. Modify the ProgramArguments array (lines 13 through 18) to use the wait4path shell command (as suggested by ZILjr) prior to launching dynamic_pager. See note #1 for details on why this is necessary. In the following example, my partition is called 'Swap', and I chose to put the swapfiles in a hidden directory on that partition, called '.vm' be sure that the directory you specify actually exists. The XML should look as follows:

5. Save the plist, and return to the terminal prompt. Using pico, the commands would be:

<ctrl+o> to save the file
<enter> to accept the same filename (com.apple.dynamic_pager.plist)
<ctrl+x> to exit

6. Convert the modified plist back to binary:

$ sudo plutil -convert binary1 com.apple.dynamic_pager.plist

7. Restart your Mac. If you run into trouble, switch to verbose startup mode by holding down Command-v immediately after the startup chime. This will let you see all of the startup messages that appear during startup. If you run into even worse trouble (i.e. you never see the login screen), hold down Command-s instead. This will boot the computer in single-user mode (no graphical UI, just a command prompt) and allow you to restore the backup copy of com.apple.dynamic_pager.plist that you made in step 1.

8. Once the computer boots, fire up Terminal and verify that the swap files have actually been moved:

$ cd /Volumes/Swap/.vm
$ ls -l

You should see something like this:

-rw------- 1 someUser staff 67108864 18 Sep 12:02 swapfile0

9. Delete the old swapfiles:

$ cd /private/var/vm
$ sudo rm swapfile*

10. Profit!

Note 1

Modifying the arguments to dynamic_pager in the plist without using wait4path does not always work, and when it fails, it does so in a spectacularly silent way. The problem stems from the fact that dynamic_pager is launched very early in the startup process. If your swap partition has not yet been mounted when dynamic_pager is first loaded (in my experience, this happens 99% of the time), then the system will fake its way through. It will create a symbolic link in your /Volumes directory which has the same name as your swap partition, but points back to the default swapfile location (/private/var/vm). Then, when your actual swap partition mounts, it will be given the name Swap 1 (or YourDriveName 1). You can see the problem by opening up Terminal and listing the contents of your /Volumes directory:

Note that this failure can be very hard to spot. If you were to check for the swapfiles as I show in step 12, you would still see them! The symbolic link would make it seem as though your swapfiles had been moved, even though they were actually being stored in the default location.

Note 2

I was originally unable to get this to work in Snow Leopard because com.apple.dynamic_pager.plist was stored in binary format. I made a copy of the original file and opened it with Apple's Property List Editor (available with Xcode) in order to make changes, but this process added some extended attributes to the plist file which caused the system to ignore it and just use the defaults. As dblu pointed out, using plutil to convert the file to plain XML works like a charm.

Note 3

You can check the Console application to see any messages that dynamic_pager_init echos to the screen. If you see the following lines repeated over and over again, there is a problem with the setup. I ran into these messages because I forgot to create the '.vm' directory that I specified in dynamic_pager_init.

When everything is working properly, you may see the above message a couple of times only, and then no more of the "Throttling respawn" messages. This means that the system did have to wait for the partition to load, but in the end it was successful.

I am truly curious as to why you would want to do this?
–
DiagoAug 23 '09 at 22:10

For the small performance gains. I like to keep my hard drive(s) partitioned according to usage. I have one partition for the OS and applications, one for the users folder, one for documents, one for media (music, movies, etc.) and one for swapfiles. In my experience, keeping the swap files separate from the rest of the system keeps disk fragmentation low. My preference would be to have swap on a dedicated drive, but another partition will usually suffice.
–
e.JamesAug 23 '09 at 22:20

4

Fair enough - However partitions on the same drive actually causes more work for the drive itself, however partitions on different drives provide a performance gain. The hard drive has to do more work when jumping across partitions on a single drive. I only ask because I have yet to have fragmentation and performance issues on my Mac after almost 2 years of usage out of the box, and when I see these posts they interest me.
–
DiagoAug 23 '09 at 22:28

1

I'm not sure why I can't post an answer (101 rep, which — if I can remember my maths — is more than the 10 which the protected state requires), but I found an non-wait4path solution, thanks to what Applicorn's Xupport modified for me. I'll post a full answer once I figure out how to, but the short of it is to change the last program argument to just the new path (e.g. <string>/Volumes/swap/.vm/swapfile</string>), change the OnDemand key to <true/>, and add a StartOnMount key to the end with a value of <true/>. P.S. This solution works fine in Lion (for me, at least).
–
Slipp D. ThompsonApr 22 '12 at 2:20

Are you certain that the swapfile is actually being moved to the partition with this setup? When I tried this approach originally, dynamic_pager would load before the secondary partitions had been mounted. The system would fake its way through by creating a symbolic link to partition2 in the /Volumes directory which simply pointed back to /private/var/vm. You could identify the failure by doing ls -al in the /Volumes directory, where you would see both "partition2" (the symbolic link) and "partition2 1" (your actual partition).
–
e.JamesSep 18 '09 at 14:34

Either way, +1 for the technique to convert plist files to & from binary format. com.apple.dynamic_pager.plist was in plain text format in 10.5.x, but in binary format as of 10.6. Which is part of my problem. I've been modifying plist files using the Property List Editor app that comes with Xcode, and maybe that's why things didn't work. I'll give plutil a try and see if it gets me any further.
–
e.JamesSep 18 '09 at 14:55

I can't test it with another partition at the moment, however during my tests I made dynamic_pager creating swapfiles on a thumbdrive by using the above technique.
–
dbluSep 18 '09 at 19:43

I was able to make the original technique work, thanks to your suggestion to use plutil for the conversions. I posted the complete solution in the question (since I don't have enough rep to add it to your answer). See my note #1 for a detailed description of the problems I ran into with just modifying the plist.
–
e.JamesSep 18 '09 at 20:45

Anyway, thank you for the answer. You put together an excellent set of instructions, and you pointed me in the right direction so I have marked it as accepted. Cheers! :)
–
e.JamesSep 18 '09 at 20:49

just a question: why not just editing the .plist file adding wait4path, instead of using the intermediate dynamic_pager_init ?

something like this:

EDIT: as explained in the comment by e.James and my following comment, the immediately following XML block is not good, both because there's an error (missing &&) and because only the first argument of the arrayProgramArgumentsit's parsed as the program to run!

please keep in mind that i still had not enough time to safely try this setting, but i tried to run various other shell commands launched in the same way, and everything should work as expected

How it works:

base: executing wait4path /path && command means that command is run only if wait4path ends and exits without errors, and this happens only when /path is an available path, so we can safely tell dynamic_pager to use that volume for swapfiles

1) as written in launchd.plist manpage, the keys Program and ProgramArguments are mapped to an execvp call, that means that everything but the first string in the array is treated as an argument for the first string in the array, the program to run;

2) as written in bash manpage, there is a bash -c <string> option to run the string passed as commands

/bin/bash is the program to run, -c is the first argument and the double quoted string is the second argument

I guess it should work exactly as your solution, without the intermediate script: launchd will start the service, that will wait for the given path and then launch dynamic_pager..

Please note that:
* the string that you want to execute should be double quoted if you run bash -c in Terminal, but it's not double quoted in the plist file! (i guess because it's already declared as a string with the proper tag)
* the two & in the string must be changed to &amp; in the plist file

PS: as always, proceed at your own risk, i take no responsibility for problems you may have using this setting !

That is an interesting idea. I'm not sure if it is "legal" to put more than one program into the ProgramArguments array, but it is certainly worth a shot. Have you tried it out?
–
e.JamesJul 13 '10 at 14:57

Sorry, there's an error in my previous post, my idea was to run the following command line (note the && that was missing): wait4path /Volumes/Swap/ && /sbin/dynamic_pager -F /Volumes/Swap/.vm/swapfile if someone finds a way to "format" that line so that launchd will like it, i guess it should work (i'm thinking about it, maybe calling /bin/bash an passing the rest as arguments ?); more explanations about the Program and ProgramArguments fields are available in the launchd.plist manpage, and that will lead to execvp(3) manpage. I'm reading & thinking, if someone is faster please post :)
–
eklJul 13 '10 at 16:07

i edited the previous post with a solution that should work, please comment if you see any kind of error or whatever may not work properly, thanks!
–
eklJul 13 '10 at 23:52

I tried it out on my laptop, and it seems to work. I'll keep an eye on it for a couple of days to be sure, but it looks like you've simplified the whole process immensely! Nice work :)
–
e.JamesJul 14 '10 at 8:03

Your simplified method is working like a charm on my laptop. Thank you! I will update the main question to incorporate your solution.
–
e.JamesJul 29 '10 at 11:09

I know it has been a while since this article was written but I thought I would add my own little item down here for for those who want to do this as well…

I have used the above trick to move my swap files off to another internal drive (my boot drive is SSD with MLC chips, so moving vm off can save the life expectancy). Anyway, after creating the new volume I had a Swap volume in Finder that I am never going to use in Finder itself, so I decided to make the volume invisible to Finder. You need Apple's Developer Toolkit installed. Then type:

/Developer/Tools/SetFile -a V /Volumes/Swap/

…and replace /Volumes/Swap with whatever you named your volume. Restart Finder and presto, no more Swap volume in Finder!

Change the swap files location
In Mac OS X the virtual memory information are stored in the so called "Swapfiles". Because the swapfiles are the most interactive system files, it makes sense to put them on a separate partition. It is recommended to store the swap files on the first partition of your fastest internal hard disk. The recommended minimum partition size should be about 3 or 4 times lager than the physical built-in memory size (e.g 1 GB physical memory = 4 GB swap partition).
Recommendations and instructions for an optimal system performance:

2.
Restore your system data or install new system on the system partition.

3.
Boot from the system partition.

4.
If you want your swap volume to be invisible to the Finder:
• Launch Xupport and choose "Settings"
• Enable "Show hidden files and folders" and restart the Finder
• Rename the swap volume from "swap" to ".swap" (The dot makes it invisible to the Finder)
• Disable "Show hidden files and folders" and restart the Finder again

This is most likely an unwanted answer (since I can't comment after Diago), but why really do you insist this will give small performance gains? I've went through a discussion on apple forums and conclusion was that this is not a good idea at all. And I was very resistant on abandoning it. Could you come up with data proving that at least for yourself, or is it just a "feeling"?

From every time I used swap even on linux, back 10 years ago, and nowadays on ubuntu, I could never see improvements on performance. My reason for wanting it was to prevent issues with free space on OSX and, on linux, for being able to hibernate. That's all swap is to me.

But I've never really did deeper research either on my own or in the interwebs.

This isn't an answer, but perhaps a very useful follow-up supplement. Apple provides a free plist editor here PlistEdit Pro. It allows you to edit these files safely. Looks as if you could just change the argument with the value /private/var/vm/swapfile to something like /Volumes/OtherDrive/vm/myswapfilename to move the swap files somewhere else...

It's a good thought, and the first thing I started with when I went down this route. The problem is that the swap partition is not always mounted at the point in time when dynamic pager launches. See note #1 in the question itself for details about what I mean.
–
e.JamesOct 30 '10 at 2:37