Archive for the 'Mac OS X' Category

Adventures in Firefox – places.sqlite

I love Firefox. Don’t get me wrong here. It allows me to customize my browsing environment to exactly how I like it, has a ton of great extensions, and generally lets me feel like I have more ownership of my browser.

What I don’t like is that it had gotten slow lately. I’m not talking about just plain takes a few more seconds to launch slow, but more like launching Firefox required a good 3 minutes to fully finish whatever it was doing and become usable.

So I did a little digging and here’s what I found.

Firefox 3 now uses a local sqlite database to store many of it’s settings like bookmarks, browsing history, favicons, etc. This is a good thing in general, as the previous storage format for those things was ugly. Now we have a full-fledged database to poke with a sharp stick should we choose to.

Greatness of using sqlite aside, databases can become bloated when you do a lot of adds/updates/deletes (especially deletes) if they don’t get the proper maintenance. Sqlite databases use VACUUM for this basic maintenance, so that’s the first thing to try if Firefox is feeling sluggish. It’s a fairly easy operation, and it’s well documented on the net with regard to Firefox. In general, you use your command line access (in my case, Terminal.app) and navigate to your Firefox profile directory. Once there, you can issue the following command to VACUUM your places.sqlite database:

sqlite3 places.sqlite VACUUM;

That was easy.

You can perform this same VACUUM procedure on the other sqlite databases Firefox uses, one by one (do a ls *.sqlite in your profile directory to find them all) or you can take my little inline shell script and do them all in one fell swoop:

for z in `/bin/ls *.sqlite`; do sqlite3 $z VACUUM; done

This assumes 3 things: you’re using a bash as a shell, /bin/ls is where your system ls lives, and sqlite3 is in your PATH. If you’re on Mac OS X, you can copy/paste that once you’ve changed to your profile directory and it’ll work fine. Other operating systems, well, you’re on your own, but it’s a simple thing to track down those bits.

What that little inline script says, in a nutshell, is “find all files ending in sqlite in the current directory, then for each of them, call sqlite $filename with the VACUUM; argument to perform the maintenance”.

That’s the easiest thing you can do and many people have mentioned that it does indeed help in many situations. That said, it didn’t help mine much.

My places.sqlite database had grown to over 60Mb. I do a lot of browsing in my day-to-day job, but 60Mb worth of history is A LOT of entries, no matter how you dice it. After continuing to hear Firefox thrash my disk for a good 2-3 minutes every time I started it, I decided to dig in and see what it was doing.

Thank God for Mac OS X and DTrace.

One of my favorite things about UNIX in general, is that there are so many neat tools for observing what is going on in your computer. One of those tools is called iosnoop, and it comes courtesy of the inclusion of DTrace in Mac OS X Leopard. iosnoop is actually just a bash script wrapper for a DTrace script, albeit with quite a few knobs and buttons.
[rts-xeon:~] ryan$ iosnoop -h
USAGE: iosnoop [-a|-A|-DeghiNostv] [-d device] [-f filename]
[-m mount_point] [-n name] [-p PID]
iosnoop # default output
-a # print all data (mostly)
-A # dump all data, space delimited
-D # print time delta, us (elapsed)
-e # print device name
-g # print command arguments
-i # print device instance
-N # print major and minor numbers
-o # print disk delta time, us
-s # print start time, us
-t # print completion time, us
-v # print completion time, string
-d device # instance name to snoop
-f filename # snoop this file only
-m mount_point # this FS only
-n name # this process name only
-p PID # this PID only
eg,
iosnoop -v # human readable timestamps
iosnoop -N # print major and minor numbers
iosnoop -m / # snoop events on filesystem / only

Well, firing up iosnoop as root (which is required to access the DTrace probes) is as easy as issuing

sudo iosnoop

in Terminal.app.

When I did that while Firefox was grinding through it’s startup, I was still seeing TONS of reads and writes to it’s places.sqlite database. Doing a bit of Google research told me I wasn’t the only one.

So I quit Firefox (it locks the sqlite database) and fired up my old friend sqlite3 to take a look at the database and found that moz_places had over 175,000 rows. 155,000 of those rows were marked as hidden (hidden = 1) which means that they were never visited in the browser, and “are commonly embedded pages, i-frames, RSS bookmarks and javascript calls” (via firefoxforensics).

Well, I’ve never once used a Live Bookmark and don’t need to keep the history of those other items, so I decided to just delete them all. You can do that using sqlite3 very easily with a quick

[rts-xeon:~/Library/Application Support/Firefox/Profiles/rts] ryan$ sqlite3 places.sqlite
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> delete from moz_places where hidden=1 and url like 'http%';
sqlite> .quit

That SQL statement tells sqlite to delete all the hidden items that have a url beginning with http. It’s important not to just delete all the hidden items, as some of them are required for Firefox to operate. I found that out the hard way, and am glad I made a copy of my places.sqlite before deleting all the hidden items and breaking my Firefox history/bookmark manager entirely.

Once you’ve deleted those hidden items, your places.sqlite database should decrease significantly in size. Mine dropped from 61Mb or so down to around 9Mb. There are still 10,000 items in my history, but those are all places I’ve explicitly visited so I’m fine with that.

Launching Firefox is no longer a 3 minute endeavour – it comes up about as fast as Safari does and I get to have my cake and eat it too.

Hope this article helps someone, and feel free to leave your comments/experience below.

gem update libxml-ruby on Leopard

So I’m updating my laptop to reflect the same environment as my servers – which means getting rid of macports. Part of the process was to update all the rubygems we’ve got installed. I tried to ‘gem up libxml-ruby’ and was disappointed to see

[rts-mbp:~] ryan$ sudo gem up libxml-ruby
Updating installed gems
Updating libxml-ruby
Building native extensions.  This could take a while...
ERROR:  While executing gem ... (Gem::Installer::ExtensionBuildError)
    ERROR: Failed to build gem native extension.

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb up
checking for socket() in -lsocket... no
checking for gethostbyname() in -lnsl... no
checking for atan() in -lm... no
checking for atan() in -lm... yes
checking for inflate() in -lz... yes
checking for iconv_open() in -liconv... yes
checking for xmlParseDoc() in -lxml2... yes
checking for libxml/xmlversion.h... yes
checking for xmlDocFormatDump()... yes
checking for docbCreateFileParserCtxt()... yes
creating extconf.h
creating Makefile

make
gcc -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0 \
-I. -DRUBY_EXTCONF_H=\"extconf.h\"  -fno-common -arch ppc -arch i386 -Os -pipe -fno-common -I. \
 -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0 -I.  -c cbg.c
cbg.c:2:26: error: libxml/xmlIO.h: No such file or directory
cbg.c:2:26: error: libxml/xmlIO.h: No such file or directory
cbg.c: In function ‘deb_Match’:
cbg.c:28: error: ‘BAD_CAST’ undeclared (first use in this function)
cbg.c:28: error: (Each undeclared identifier is reported only once
cbg.c:28: error: for each function it appears in.)
cbg.c:28: error: syntax error before ‘filename’
cbg.c: In function ‘deb_Match’:
cbg.c:28: error: ‘BAD_CAST’ undeclared (first use in this function)
cbg.c:28: error: (Each undeclared identifier is reported only once
cbg.c:28: error: for each function it appears in.)
cbg.c:28: error: syntax error before ‘filename’
lipo: can't open input file: /var/tmp//ccpl6OUz.out (No such file or directory)
make: *** [cbg.o] Error 1

Gem files will remain installed in /Library/Ruby/Gems/1.8/gems/libxml-ruby-0.5.4 for inspection.
Results logged to /Library/Ruby/Gems/1.8/gems/libxml-ruby-0.5.4/ext/libxml/gem_make.out
[rts-mbp:~] ryan$

Turns out after a bit of digging around in the Makefile that the INCPATH doesn’t include the correct path to xmlIO.h, which is /usr/include/libxml2/libxml/xmlIO.h.

ln to the rescue. Just do

sudo ln -s /usr/include/libxml2/libxml /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0/libxml

and libxml-ruby will build fine!

[rts-mbp:~] ryan$ sudo gem up libxml-ruby
Updating installed gems
Updating libxml-ruby
Building native extensions.  This could take a while...
Successfully installed libxml-ruby-0.5.4
Gems updated: libxml-ruby
[rts-mbp:~] ryan$

Win an iMac? Yes please!

So my daughter Emma is 4 now, and her ruby iMac is on its last legs. It’s been up on blocks for a couple months now, and I just can’t seem to get it to boot off anything but the internal drive so I can upgrade the OS to something past 10.2.8.

What a pleasure that I just happened to run across the Stay At Home Dad iMac Give-Away contest being run by Mike over at his blog Stay At Home Dad, Geek Style, in concert with Sittercity, which I’d never heard of before, but looks quite interesting, given the need for babysitters with a 4 year old in the house.

What’s on the line? One of these babies:

iMac

A brand new, unopened 20″ Apple iMac. It has a 2.0 GHz Intel Core 2 Duo processor, 1 GB of memory, a 250 GB hard drive, an 8x SuperDrive, and an awesome 20″ glossy display. It ships with an Apple Mighty Mouse, a sexy new Apple keyboard, an Apple Remote for controlling the included Front Row software (which turns your computer into a full-on media center), and as dutifully noted on Apple’s iMac page, a power cord (duh!).

If you’d like to enter Mike’s Stay At Home Dad iMac Give-Away contest, visit his site for the rules and enter. It’s a rather interesting contest, as he’s giving out “tickets” based on doing certain things, like writing an initial post like this one is worth one ticket and is required to enter. There are other opportunities to earn a ticket.

* make extra posts about the contest for 1 ticket each
* put a Sittercity banner on your sidebar and get 5 tickets
* bid on DevDad’s ads and get 1 ticket per $1 bid
* chip in for DevDad’s dream set-up and get 2 tickets per $1 chipped in
* like the contest page on stumble upon and get 1 ticket

You’re also encouraged to use this graphic:

SitterCity

Which I am so doing as to appease the contest gremlins.

All in all, it’s an interesting way to run a contest, and I’m all for a little link love for chances to win Apple hardware, which is the pinnacle of industrial design, which runs, in my opinion, the best consumer OS on the planet. (Server OS would have to be Solaris.)

Wish me luck, and I might just have to put up a little extra chrome to help out my odds and get some more of those golden tickets!

Enforce your Breaks

AntiRSI is a program for Mac OS X that helps prevent RSI (repetitive strain injury) and other computer related stress.

AntiRSI – TECH.inhelsinki.nl

Untitled

To make it all happen in one shot, follow the same procedure (type “.”, type your message, tab, type “large type”) but then hit CTRL+ENTER and it will save the “large type” command. Then you get a new list, from which you can select “run after delay”. Slick huh?

Set quick timed reminders with Quicksilver – Lifehacker

Kitten’s Project Blog

Kitten’s Project Blog has lots of nice WordPress plugins

Radmind Wizardry

How to add support for new hardware to an existing base load

These directions describe how to add support for new hardware into an
existing base load

cat a binary and screw up your terminal?

via unixtips.org
When your term can’t display the correct char after you cat a binary file try the following command to reset it:
echo CTRL-V ESC c

Check this one out…

La Chose Interactive

auxpropfunc error -1

After searching through my archives, I finally found this message from Joel Rennich of afp548.com fame.

Since Googling for that error found pretty much nothing else on the net, I thought I’d throw it here so that someone else wondering about all the
auxpropfunc error -1
entries in your syslog and console logs were could have a clear, consise answer to the issue. Continue reading ‘auxpropfunc error -1′