Smörgåsbord

Ambachtelijk bereide beschouwingen.

The other day I compiled Firefox 3.5-beta4, and, apart from many improvements, I noticed that I am now affected by the infamous ‘hiccups’. Firefox will stall for seconds at a time on my poor netbook. Details on how this relates to the many fsync() calls made by the persistance layer (SQLite) can be found all over the net.
But I don’t want Firefox to stall and I don’t want to keep my harddisk awake with all these writes when I’m on battery power.
Luckily, both these problems go away if you put your Firefox profile on a ramdisk. There are numerous guides out there that save you from working out the details; I used this one from the Gentoo forums.
The guide uses cron to sync the (presumably) modified contents of the ramdisk – bookmarks, cookies, whatever – back to permanent storage (harddisk). You and I both know that while it’s often convenient to use cron, it’s not always the Right Way of Doing Things®. Why sync if nothing’s changed? I wrote a script that employs the inotify system to do the syncing only when necessary. You’ll find it in the forum thread I linked to earlier, but I post it here “ter lering ende vermaeck”. Depending on your browser there might be a vertical scrollbar at the bottom which lets you read up to the EOL’s ;-)
You can find the latest version at my public repo.

#!/bin/bash
 
# Packfox, a tool to facilitate running Firefox with its profile stored
# in RAM (tmpfs). Copyright 2008-2009 Wicher Minnaard, wicher@gavagai.eu .
# Distributed under the WTFPL, http://smormedia.gavagai.nl/dist/packfox/COPYING
# Latest version available at http://smormedia.gavagai.nl/dist/packfox/
 
 
# Change this to match your profile
PROFILE=$(hostname)
PFDIR="${HOME}/.mozilla/firefox"
# Tar every .. seconds (regardless of changes)
TMOUT="1800"
# But not more often than every .. seconds (regardless of changes)
TMMIN="60"
# Regex for which files not to act on when they're changed.
# Use inotifywait -m -e modify -e move -e create -e delete --exclude '(/Cache/)' -r your_profile_dir
# and watch the output while browsing to determine which regex will be right for YOU.
IEXCL="(.sqlite-journal$)|(\-log.txt$)|(cookies.sqlite$)|(sessionstore\-[0-9].js$)|(/weave/)|(/Cache/)"
# Have you read everything and have you made the necessary adjustments? Then remove the line below ;-)
echo "I should read the README and adjust the script variables before running this." && exit 2
 
 
# No user servicable parts below this line.
TGT="${PFDIR}/${PROFILE}"
 
# Global vars
INOTYPID=""
SLEEPPID=""
PACKLOCK=""
 
# Cleanup function
terminate(){
  # If we are the daemon and we get SIGINTed/SIGTERMed, kill our children
  # and if not already packing, do one last round of packing.
  if [ "$(basename ${0})" == "packfox-daemon" ]
  then
    if [ -n "${INOTYPID}" ]; then kill ${INOTYPID}; fi
    if [ -n "${SLEEPPID}" ]; then kill ${SLEEPPID}; fi
    if [ -z "${PACKLOCK}" ];then packup; fi
    exit
  fi
}
 
# For cleaning up 
trap terminate SIGINT SIGTERM
 
# Suicide with goodbye note. If gxmessage is installed, use that.
seppuku(){
  echo "${1}" 1>&2
  which gxmessage > /dev/null 2>&1 && gxmessage -nofocus -title "$(basename ${0})" "${1}" || xmessage "${1}"
  exit 2
}
 
# Checks and setup
test -d "${PFDIR}" || seppuku "Profile dir doesn't exist"
if [ -z "$(mount -t tmpfs | grep -F "${TGT}" )" ]
then
    mount "${PFDIR}/${PROFILE}" || seppuku "Mounting of profile's tmpfs failed. Check /etc/fstab and the output of 'dmesg'."
fi
test -f "${TGT}/.unpacked" || tar -xpf "${PFDIR}/${PROFILE}.packed.tar" -C "${PFDIR}" \
&& touch "${TGT}/.unpacked" || seppuku "Error unpacking the profile tarball. You might want to use the backup tarball located in ${PFDIR}."
 
# This tars up the profile
packup(){
  PACKLOCK="locked"  
  cd "${PFDIR}"
  tar --exclude '.unpacked' -cpf "${PFDIR}/${PROFILE}.packed.tmp.tar" "${PROFILE}"
  mv "${PFDIR}/${PROFILE}.packed.tar" "${PFDIR}/${PROFILE}.packed.tar.old"
  mv "${PFDIR}/${PROFILE}.packed.tmp.tar" "${PFDIR}/${PROFILE}.packed.tar"
  PACKLOCK=""
}
 
# No daemon, just packing
if [ "$(basename ${0})" == "packfox" ]; then packup; fi
 
# The daemon loop
if [ "$(basename ${0})" == "packfox-daemon" ]
then
  which inotifywait >/dev/null 2>&1 || seppuku " You'll need the 'inotify-tools' package for this script. Get it at http://inotify-tools.sourceforge.net or from your distro's repos".
  while true
    do inotifywait -q -q -t ${TMOUT} -e modify -e move -e create -e delete --exclude "${IEXCL}" \
    -r "${PFDIR}/${PROFILE}" &
    INOTYPID=${!}
    wait ${INOTYPID}; INOTIFYPID=""
 
    packup
 
    sleep ${TMMIN} &
    SLEEPPID=${!}
    wait ${SLEEPPID}; SLEEPPID=""
    done
  exit
fi

Tags: , , , ,

5 Responses to “how I fixed my Firefox hiccups”

  1. marius

    thanks for the script.
    here are a few problems I ran into:
    gxmessage needs to be installed (it is not installed by default on Debian).
    The title of the message could be set, like:
    gxmessage -nofocus -title “$(basename ${0})” -center “${1}”

    then I have huge (450M) google gears directory inside my profile.. this is my gmail for offline usage, and I cannot divert that path :(

  2. marius

    argh, fixed gears moving it and putting back a symbolic link to its new location.

    no hiccups anymore, yay!!!
    thanks

  3. Wicher

    Thanks for the tip on gxmessage, I’ll add that (soonish).
    You might consider to exclude your gears directory with tar’s and inotify’s exclude options. Or maybe you’ve already done so ;-)

  4. Marius

    yes, tar and inotify was the easy part, but gears did not want to fit into tmpfs mount of 128M ;-)

    btw, script also relies that the tar archive is there from the begining — this is not the case for the first time. The script would be more robust if it checked that instead of seppuku :)

  5. Wicher

    Thanks for the feedback, Marius!
    I’ve made a 0.2 (repo) in which I added some setup documentation so people don’t have to browse the topic in the Gentoo forums for clues.
    And I added xmessage as a fallback for those who do not have gxmessage installed. And there was a bug in 0.1 caused by a typo in a variable (that’s what you get for programming in Bash).

Leave a Reply

Got an account? This would be an excellent time to log in!

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">


© 2009-2010 Wicher Minnaard | electronic mail | theme: righteously modified "dark strict"