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.
Complete solution:
1. Open Terminal and make a backup copy of Apple's default dynamic_pager.plist:
$ cd /System/Library/LaunchDaemons
$ sudo cp com.apple.dynamic_pager.plist{,_bak}
2. Convert the plist from binary to plain XML:
$ sudo plutil -convert xml1 com.apple.dynamic_pager.plist
3. Open the converted plist with your text editor of choice. (I use pico, see dblu's answer for an example using vim):
$ sudo pico -w com.apple.dynamic_pager.plist
It should look as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs$
<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>
4. Change the ProgramArguments array (lines 13 through 18) so that it launches an intermediate shell script instead of launching dynamic_pager directly. See note #1 for details on why this is necessary.
<key>ProgramArguments</key>
<array>
<string>/sbin/dynamic_pager_init</string>
</array>
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. Create the intermediate shell script:
$ cd /sbin
$ sudo pico -w dynamic_pager_init
The script should look as follows (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):
Update: This version of the script makes use of wait4path as suggested by ZILjr:
#!/bin/bash
#launch Apple's dynamic_pager only when the swap volume is mounted
echo "Waiting for Swap volume to mount";
wait4path /Volumes/Swap;
echo "Launching dynamic pager on volume Swap";
/sbin/dynamic_pager -F /Volumes/Swap/.vm/swapfile;
8. Save and close dynamic_pager_init (same commands as step 5)
9. Modify permissions and ownership for dynamic_pager_init:
$ sudo chmod a+x-w /sbin/dynamic_pager_init
$ sudo chown root:wheel /sbin/dynamic_pager_init
10. Verify the permissions on dynamic_pager_init:
$ ls -l dynamic_pager_init
-r-xr-xr-x 1 root wheel 6 18 Sep 15:11 dynamic_pager_init
11. 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.
12. 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
13. Delete the old swapfiles:
$ cd /private/var/vm
$ sudo rm swapfile*
14. Profit!
Note 1
Simply modifying the arguments to dynamic_pager in the plist 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:
$ cd /Volumes
$ ls -l
You will see something like this:
drwxrwxrwx 11 yourUser staff 442 16 Sep 12:13 Swap -> private/var/vm
drwxrwxrwx 14 yourUser staff 5 16 Sep 12:13 Swap 1
lrwxr-xr-x 1 root admin 1 17 Sep 12:01 System -> /
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.
com.apple.launchd[1] (com.apple.dynamic_pager[176]) Exited with exit code: 1
com.apple.launchd[1] (com.apple.dynamic_pager) Throttling respawn: Will start in 10 seconds
When everything is working properly, you may see the above message a couple of times, but you should also see the following message, and then no more of the "Throttling respawn" messages afterwards.
com.apple.dynamic_pager[???] Launching dynamic pager on volume Swap
This means that the script did have to wait for the partition to load, but in the end it was successful.