Mac OS X SSD tweaks

January 22, 2010

NOTE: Due to the fact that the RamDisk script part breaks on 10.6.5 – this post has been revised on Mac OS SSD tweaks (revised for 10.6.5 – thanks to Pierre)

Ok, I have an Intel X-25M 160 GB SSD coming and I’m on a VERY GEEKY mood… so I decided to poke around a little on what could be done to tweak Mac OS X in order to, at least minimize the write amplification problem and also optimize the space used – yes you know the €/MB ratio is high on SSDs. Most of these tweaks, besides providing for a longer lifespan for SSD disks, should improve overall system performance even on an non SSD disk. Of course you will use them at your own risk…

Oh no… ‘noatime’

Let’s start with an obvious one, inherited from other unixes – disabling enabling ‘noatime’. On a short introduction – it is usual for unix filesystems to record the ‘last access’ time of every file. This means that every time a file is read, a write is made on the filesystem to record this action. No point and not necessary, and disabling it poses no secondary effects that I am aware of, so… to disable it, just create a file named for example “com.nullvision.noatime.plist” in the directory /Library/LaunchDaemons with the following content:

<?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>Label</key>
        <string>com.nullvision.noatime</string>
        <key>ProgramArguments</key>
        <array>
            <string>mount</string>
            <string>-vuwo</string>
            <string>noatime</string>
            <string>/</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>

It seems that I missed this, which is required (thanks to Miles Wolbe).

sudo chown root:wheel /Library/LaunchDaemons/com.nullvision.noatime.plist

…and of course a reboot to activate it. You can check that it is active (ok, this is a little paranoid) with:

$ mount | grep " / "
/dev/disk0s2 on / (hfs, local, journaled, noatime)

And off we go for the next tweak.

Zzzzz… sleeping for Gigabytes

Another easy and straightforward thing to do is tweak Mac OS X sleep mode. By default Mac OS X sleeps after a predefined period, and if, while it sleeping the battery rans out, the whole contents of the system’s memory will be copied to disk (to a file named “/var/vm/sleepimage“) and reloaded on the next power on. This file is as big as the amount of RAM you have on your system. I usually don’t leave my MacBook to sleep for so long that the battery rans out, and even if I do, I usually save all my work, so… I will assume the risk of not awaking from sleep (and a couple of HFS log replays) to save 8 GB on my SSD. On the shell just execute the following couple of commands:

$ sudo pmset -a hibernatemode 0
$ sudo rm /var/vm/sleepimage

…and your done with this one, no reboot needed.

Remember DOS RAMDISK? Well still here – baptized RAM FS

Ok, if you have been reading the news you probably know that SSDs don’t handle writes that well. This is related to the way SSDs work internally – meaning that each cell on an SSD disk as a life-cycle of around 10.000 writes. If you ask me, 10.000 writes is more than enough, even more because most if not all SSDs do write rebalancing in order not to completely wear out a part of the disk while the other part is brand new. Anyway my Mac (and yours too if you have one) spends the day writing transient data to temporary (and other) directories. The idea is to create a temporary filesystem in RAM and move all that writing into that filesystem. Cool huh? Start by creating a script to create and mount the ram filesystem. On the “/var/root” directory, create a file named “ramfs.sh” with the following content:

#!/bin/bash
ramfs_size_mb=256
mount_point=/private/tmp

ramfs_size_sectors=$((${ramfs_size_mb}*1024*1024/512))
ramdisk_dev=`hdid -nomount ram://${ramfs_size_sectors}`
newfs_hfs -v 'Volatile HD' ${ramdisk_dev}
mkdir -p ${mount_point}
mount -o noatime -t hfs ${ramdisk_dev} ${mount_point}
chown root:wheel ${mount_point}
chmod 1777 ${mount_point}

In the above script, you can change the variable “ramfs_size_mb” to fit your needs. The next step is running it at boot… This can be accomplished using “launchd“, so just create a new “com.nullvision.ramfs.plist” in the “/Library/LaunchDaemons” directory, containing:

<?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>Label</key>
        <string>com.nullvision.ramfs</string>
        <key>ProgramArguments</key>
        <array>
            <string>/var/root/ramfs.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>

Almost ready… Noticed that “/tmp” points to “/private/tmp“, cool that’s we wanted, right? What about “/private/var/tmp“? It doesn’t…

Well let’s change it (please note, I’m really not sure on the real impact of this, because “launchd” needs this directory and I’m mounting it using “launched” so really, use it at your risk. Still if you are brave enough just to:

$ sudo -i
# cd /private/var
# mv tmp tmp.old
# ln -s ../tmp

On a short note, I noticed that my MacBook now takes a couple of seconds longer to shutdown, I’ll investigate this if it starts bothering me. …oh, yeah and a reboot is required for this one.

Things I moved into the the RAM filesystem:

  • Xcode build directory (if you’re using it, you ought to know how to change it)
  • MacPorts download and build directories
    • /opt/local/var/macports/build
    • /opt/local/var/macports/software
    • /opt/local/var/macports/distfiles
  • ~/Library/Caches (testing this one to check how it works out)

tags:
posted in Mac OS by Ricardo Gameiro

Follow comments via the RSS Feed | Leave a comment | Trackback URL

16 Comments to "Mac OS X SSD tweaks"

  1. idczar wrote:

    so how did these settings work for you?

  2. Ricardo Gameiro wrote:

    I’ve kept all of them except the ~/Library/Caches move to ramfs. Safari not being able to reuse it’s cache was getting to be a pain because the ‘top sites’ feature caches the thumbnails in that directory. Otherwise – GREAT!

  3. edaldu wrote:

    How about reading ~/Library/Caches from disk at boot and writing it back to disk on shutdown? Is there a hook available for this? Of course this would also increase shutdown-time, but with a SSD this would be only a few seconds

    Sorry for reviving this old post :)

  4. Pierre wrote:

    Hello :)

    i’m following this article (Especially the part about the RamDISK for tmp) with great interest. However, i don’t understand something: After setting up my tmp folder to the ram partition, the shutdown of the machine is very slow… It says something about diskarbitrationd not being welcome anymore…

    Any direction on how to solve this, and get my shutdown times back to normal?

    Thanks! Pierre.

  5. Pierre wrote:

    Hello again,

    i’ve been investigating a bit on what’s happening for the bad shutdown times. In fact, those 3 processes can’t properly shutdown: - securityd - diskarbitrationd - launchd i believe it’s because they are started before the /private/tmp is substituted by the RAMFS… And therefore, when trying to shutdown, they can’t find their pid / data file in the new tmp.

    i’ve been trying to make a small mod of the script:

    !/bin/bash

    ramfs_size_mb=512 mount_point=/private/tmp trans_dir=/private/trans

    case “$1″ in start) ramfs_size_sectors=$((${ramfs_size_mb}10241024/512)) ramdisk_dev=hdid -nomount ram://${ramfs_size_sectors} newfs_hfs -v ‘Temporary’ ${ramdisk_dev} mkdir -p ${mount_point} mkdir -p ${trans_dir} cp -R ${mount_point}/* ${trans_dir}/ mount -o noatime -t hfs ${ramdisk_dev} ${mount_point} chown root:wheel ${mount_point} mv ${trans_dir}/* ${mount_point}/ chmod 1777 ${mount_point} ;; *) umount ${mount_point} hdiutil detach ${mount_point} ;; esac

    As you can see, i’m copying every file in tmp before creating the ramfs, and then put those files in the ramfs so the processes can find their eggs later…

    But it doesn’t seem to change much of the problem.

    If anyone has a good solution (The best would probably be to be able to mount the ramfs prior to any other operation or daemon launch), i’m really interested.

    Kind regards, Pierre.

  6. Ricardo Gameiro wrote:

    Hi, I did run into this – but ended up never looking in to it and for the time being, I’m sorry, but I’m to busy to go into this in detail – in the mean time – If you find a solution, please report back.

  7. Mike Subelsky wrote:

    this was super helpful to me. I implemented all of this and it’s working great! One thing I had to do that’s not in here is make /var/root/ramfs.sh executable (chmod 755)

  8. Pierre wrote:

    Hi,

    As you might have noticed, updating to 10.6.5 breaks this tweak… Some binaries are not available in the PATH at the time the script gets executed. i have found a very elegant solution now, using StartupItems in /System/Library.

    If you’d like to create a new post about it, i’ll be glad to explain how i did it (No shutdown issue anymore…). But not on comment, i can’t seem to have nice line endings here.

    Bye :) Pierre.

  9. Pierre wrote:

    Basically: - Create a StartupItem in /System/Library (A folder named “RamFS”). - Inside this folder, create a script named “RamFS”, the name is very important (See the content of the script at the end of this post). - Then, create a plist in this RamFS folder, named “StartupParameters.plist” (Contents also at the end of this post.

    Now, the rights of all those files are very important. From a terminal, cd to /System/Library/StartupItems and type: sudo chown -R root:admin RamFS sudo chmod -R u+rwX,g+rX,o+rX RamFS sudo chmod u+x,g+x,o+x RamFS/RamFS

    And you’re done.

    Now the scripts contents for RamFS:

    !/bin/sh

    Create a RAM disk with same perms as mountpoint

    RAMDisk() { mntpt=$1 rdsize=$(($210241024/512)) echo “Creating RamFS for $mntpt” # Create the RAM disk. dev=hdik -drivekey system-image=yes -nomount ram://$rdsize # Successfull creation… if [ $? -eq 0 ] ; then # Create HFS on the RAM volume. newfs_hfs $dev # Store permissions from old mount point. eval /usr/bin/stat -s $mntpt # Mount the RAM disk to the target mount point. mount -t hfs -o union -o nobrowse $dev $mntpt # Restore permissions like they were on old volume. chown $st_uid:$st_gid $mntpt chmod $st_mode $mntpt fi }

    Test for arguments.

    if [ -z $1 ] ; then echo “Usage: $0 [start|stop|restart] ” exit 1 fi

    Source the common setup functions for startup scripts

    test -r /etc/rc.common || exit 1 . /etc/rc.common

    StartService () { ConsoleMessage “Starting RamFS disks…” RAMDisk /private/tmp 256 RAMDisk /var/run 64 RAMDisk /var/db 1024 #mkdir -m 1777 /var/db/mds }

    StopService () { ConsoleMessage “Stopping RamFS disks, nothing will be done here…” #diskutil unmount /private/tmp /private/var/run #diskutil unmount /private/var/run }

    RestartService () { ConsoleMessage “Restarting RamFS disks, nothing will be done here…” }

    RunService “$1″

    And the contents of the StartupParameters.plist:

    Description RamFS Disks Manager OrderPreference Early Provides RamFS Uses Disks

  10. Pierre wrote:

    OOps sorry, in fact the chown should be root:wheel of course, not root:admin…

  11. Pierre wrote:

    Now i’m very very sorry for clutturing your nice blog… But i forgot another thing, which is the shutdown time explaination: Using union for mounting the RamFS makes it use both the old tmp folder AND the new RamFS mount… So daemons which have been started before RamFS still can find their data.

    Additionnaly, you might want to remove the “nobrowse” flag, i have put it to avoid seeing those disks on my finder :)

    Bye :) Pierre.

  12. Ricardo Gameiro wrote:

    Hello Pierre, compiled your comments in Mac OS X SSD tweaks (revised for 10.6.5)

    Thanks!

  13. Smultie wrote:

    When a try activating noatime, it seems to not be working. I’ve followed all the steps on the guide, but after rebooting, I get the following message when using “mount” on terminal:

    /dev/disk0s2 on / (hfs, local, journaled) <—geen “noatime” :( devfs on /dev (devfs, local, nobrowse) map -hosts on /net (autofs, nosuid, automounted, nobrowse) map auto_home on /home (autofs, automounted, nobrowse) /dev/disk1s2 on /Volumes/Backup (hfs, local, nodev, nosuid, journaled) /dev/disk1s3 on /Volumes/Data (exfat, local, nodev, nosuid, noowners)

    Anyone that can help me?

  14. John wrote:

    I recently received a new hard drive, so i did a fresh install of the OS. As soon as I had a working desktop, I did the 10.6.5 combo update. I attempted to enable noatime, but it is not showing up when i type mount in terminal. It has been working fine for me for almost 8 months, and all of the sudden it does not work anymore. I even navigated to /Library/LaunchDaemons in finder, and my noatime file is indeed in there. It is just not working for some reason though. Any advice?

  15. Miles Wolbe wrote:

    Smultie & John: In order for the noatime tip to work, you’ll need to run:

    sudo chown root:wheel /Library/LaunchDaemons/com.nullvision.noatime.plist

    Ricardo: you may want to update your directions to mention this.

  16. John wrote:

    Thanks for the reply. Like I said, I had it working previously for almost 8 months. Once I switched from an OWC 50 GB extreme ssd to a OWC 128 GB pro ssd it no longer worked. I tried owning it as root before I move it to /Library/LaunchDaemons and after as well. For some reason it is just not working. Do you have it working in 10.6.5 or 10.6.6? I just updated to 10.6.6 hoping it was something related to 10.6.5 but it still wont show up when i type mount in terminal?

Leave Your Comment


 

© Copyright nullVision.com.