PowerSearch: Only in Bowtie
---------------------------

![Bowtie PowerSearch](/bt-search.png)

Bowtie's search feature has only been demonstrated via video thus far -- few people have actually had the opportunity to use it. But just about everyone who's seen it has had one question: how is it so fast?

Every major iTunes controller on the market does searching essentially the same way, and they're all bloated, buggy, and most importantly, SLOW. In fact, this was one of the reasons I originally decided to omit searching from Bowtie entirely. Then I came up with an idea, based on what I'd done for fast searching over the network with TuneConnect. It's called PowerSearch: it's fast, powerful, and it blows everyone else's search out of the water. And here's why.

### How Everyone Else Does It ###

iTunes has a great built-in search feature -- it's fast and easy-to-use, much like Bowtie's. ;) It's no surprise that most other iTunes controllers rely on iTunes to do the searching for them. It makes sense. But there's a problem.

Apple Event objects are chunky little buggers, and they take a lot of work to decode. If you start searching for something in an iTunes controller, and it attempts to do live updating, you very well may end up in a scenario where you're getting 2,000 tracks back from iTunes after typing your first letter. If these were native objects, it wouldn't be a huge problem for an app to process, but since we've already established that Apple Event objects are relatively heavy lifting...

A few applications take an alternate, though similar, route, and pull all of the tracks from iTunes beforehand, and then do their own searching. Slightly more effective at increasing search speed? Sure. Increases memory consumption and bloat? Oh hell yeah.

### How Bowtie Does It ###

Bowtie PowerSearch is truly unique: not only is it lightning fast, but it's also more powerful. You can easily filter by different types of content using quick modifier keystrokes. For instance, if I type "U2" into my search field, I'll get every track that has a title, album, or artist that contains "U2". But if I type "@U2" into my search field, I'll only get tracks with an artist that contains "U2". Not too shabby, eh?

The secret behind PowerSearch's power are two technologies that are deeply ingrained in Mac OS X, and therefore, very fast: **plists** and **predicates**.

**Plists** are something with which many of us are already familiar: they're the canonical, mostly-human-readable way of storing data on Mac OS X. Every Mac application uses one to describe its metadata, and many system-wide configuration files are stored in this format. As such, the code that OS X uses to read and write these files is very fast, as it has to happen quite frequently.

It just so happens that iTunes likes to keep a copy of your music library around stored in plist format in a file called, cryptically, "iTunes Music Library.xml". The first step in making searching faster is harnessing the power of this file. When Bowtie launches, and every time you go to search and it notices this file has been changed, it opens it, and creates an internal representation of every track in the file. Granted, my library isn't very large (about 1,400 tracks), but on my MacBook Pro this process completes in less than half a second (compared to about 10 seconds using the latter Apple Events method). Step 1: accomplished.

Here's where **predicates** come in. Predicates in Mac OS X are a convenient way of storing search specifiers based on multiple parameters. For instance, a predicate string for the search criteria shown in the graphic at the top might look like this: `(artist contains[cd] "u2") AND (name contains[cd] "where the stre")`. Easy enough to understand.

The beauty of this, though, is the internal predicate compiler that turns this human-readable string into something small and lightweight that the computer understands. From here, it's a single line of code to apply whatever predicate I've created to an array or a dictionary. Like an array of tracks, for instance. And did I mention it's lightning fast?

### From the top... ###

When Bowtie launches, or whenever it notices your music library has changed, Bowtie pulls your library and creates an internal representation of all of your tracks (yes I already said that, I'm reiterating). Next, the instant you start typing in the Bowtie search box, Bowtie goes to work creating predicates out of what you type, based on how you type it and what modifiers you add to it. Every step along the way, it applies the most recent predicate to the master list of tracks, and displays the result. Because this is all happening using native, internal objects built upon a very fast filtering platform, the result is what appears to be instantaneous (and very powerful!) search.

And that's how we do it. :) So be on the lookout for Bowtie beta 2, coming out very soon.

Oh and by the way, you'll notice that there are two different search interfaces at the top of this post. When I first started implementing the search, I opted to design a HUD-style interface (the one pictured on the right). When it was done, I showed it to Laurent, who decided he wasn't a big fan and promptly commenced designing the sexylicious aqua-and-metal interface pictured to the left. Ultimately, we both decided that the aqua interface looked better, so it's what Bowtie uses. We did, however, leave the HUD interace in for sentimental reasons. If you want to use it, just run this command in Terminal, and relaunch Bowtie:

	defaults write net.mattpat.Bowtie searchMode HUD
	
To change it back, just use this:

	defaults write net.mattpat.Bowtie searchMode Aqua

Enjoy! ;)