Archive for the Category Programming

 
 

YUI CSS Kicks Ass

I was looking for a color picker widget over at Yahoos YUI site. I have been there before mostly to watch the videos on Javascript. Douglas Crockford is obviously the man when it comes to Javascript.

Anyway, I saw a link for a video on YUI’s CSS component and I was just a little bit interested. I though it was probably just another CSS reset. There was some vague promise of Grids and I couldn’t imagine how they could make that easy so I still didn’t think it looked promising.

Wow was I wrong. If you haven’t seen this then you need to go check it out. Nate Koechley and crew have done a seminal piece of CSS work here. Here are the highlights:

  • They provide a reset for all styles and fonts in all major browsers, including IE6. You are leveraging all the cross browser testing done by Yahoo
  • Everything (fonts, boxes etc) is sized with em’s or percentages of em’s so the entire page will scale gracefully for 508C
  • The Grids can be nested. You can do 2, 3 or 4 columns in a variety of width ratios (e.g. 2 columns: 1/4, 3/4 )
  • Its really simple to use

At work we have struggled with CSS. We don’t have a full time web designer to work for us. So the devs do all the html & css. I’m fairly handy with this sort of thing but have no where near enough time to produce the level of product that you can get with YUI. Other devs have even less patience for this sort of thing. For us this make a whole lot of sense.

We are really sensitive to the semantic markup of the page and the use of em’s for 508C support. We want it to be nice to use not just live up to the letter of some spec. I started using em’s when we first did the style sheet but I was about to give up because it was getting so difficult to use. Now its going to be easy to provide the kind of experience and cross browser compatibility that I have wanted all along.

Just go to Yahoo’s home page and increase the font size. Look at how smoothly that works and realize how hard that is to set up. Now realize you can do that to your site and still get work done faster than before. Your developers can pick this up in an hour or two and start building better stuff.

Indrio Performance Enhancements

Indrio development took a back seat to some other more important real world stuff for a while. I’ll get into that at a later time but right now I’m gonna focus on Indrio.

Some parts of the iTunes API are shamefully slow. The Enumerator for ITrackCollection operates in n ² time. So the time it takes to walk the list grows quadratically with the length of the list. Iterating over the list with python and calling Item is actually faster that the enumerator. That was a bit of a shock. Item() is definitely n ², access at the end of the list is much slower than at the start of the list.

Even if Apple were to fix this we are talking about 5 seconds here which would give a max speedup of 2.2 seconds. Thats still too slow for search as you type. Besides, have you ever seen what happens when you drop a 5k rows worth of table into a web page? It won’t render correctly on anything.

The real solution is to page the results. This way access to the results is fast even in the worst case scenario at the end of a large list. This is what you would do in a real GUI application anyway. Never show the user more information that then can digest and Never do processing for anything you didn’t show the user.

The search for answers to Inrdio’s speed problems lead me down a path of optimizations that tightly coupled the iTunes stuff to the web server. Some of the optimizations were good but I’m not going to pay for them with bad architecture. So I took a step back and completely abstracted everything behind three classes: AudioPlayerInterface, TrackList, & Track.

The AudioPlayerInterface supports searching, queuing, and provides information about what songs will play/are playing. The TrackList supports the paged access to tracks, either from search results or from the playlist. Tracks are, of course, tracks with information like Artist, Title and so on.

In the iTunes implementation of TrackList is extremely fast. You construct a TrackList without having to iterate through the tracks. Then the web application module can get a page of tracks and compose them with the templating engine.

Access to Track data is done as its requested. The absolute minimum number of COM calls are made to render each template. The Track interface uses the wrapper pattern so its thin and fast. This way the tracks can support a large set of properties without having to copy each one into a temporary variable. The extra fields can be used by other templates, like the one that will render what playing now.

Expect a release (with code) as soon as I get the obvious bugs out.

Indrio Development: Fun with DOM

DOM is a swell gal, she treats me all right, just so long as I take her out to her favourite restaurant; Firefox. When I get cheap and go for fast food at Internet Explorer, she’s not happy.

innerHTML is a read only property in IE for the table and tbody elements. Trying to set it causes a very nondescript error with a code of 0. Firefox isn’t totally off the hook either. With large sets of rows there are rendering errors at the bottom of the table if you don’t define a background color. I’m using prototype.js to insert the rows returned from an AJAX call. I kluged a fix for IE by inserting the entire table every time.

Performance building that table was very bad for large result sets (1k+ rows). Python had a built in profiler & CherryPy has profiler support. I totally love this, this rocks 1000% more than Java. Reading and building the data set from iTunes was about 1/10th the total execution time so something else was not very fast. Turns out it was a module for the template engine that only worked with 2.4. I upgraded everything to 2.4 and performance got drastically better.

Now the major bottleneck is with fetching values from iTunes via COM. Thats about 80% of the time is spent in __getattr__ and _ApplyTypes_. Thats the COM stuff translating returned values into Python types and the majority of that time is probably spent in iTunes. The stop gap to give reasonable performance is to limit the number of rendered results.  I picked a ‘magic’ number, 300, which renders in under 2 seconds on my system. This will suck if your trying to search for music by genre and there are 1K+ results for ‘Trance’ in your library. Some sort of paging solution may have to be used to get through a result set like that. I don’t really see that as a major usage pattern in my experience. People generally ask for music by title or artist and this turns out to be very specific and returns a limited number of results.

Indrio Development Continues Apace: HTTP Server

For this particular application I don’t care where the user interface is displayed. In fact it would be cooler if the UI could go somewhere other than where iTunes is. In fact it would also be cool if a couple of people on different computers could access the thing at the same time, bonus. So I decided to send the UI out over an HTTP server to a browser and use a bit of AJAX to make this snappy. This brought development to an impasse, where do you get an HTTP server for python. Apache was out of the question, I’m not having users install that thing just to run this little app, way overkill. In fact what I wanted was fairly specific:

  • Small; as in not large, as in less than 1 MB compiled
  • Embedded; must run from inside the app, no external servers please
  • Must not stop me from talking to COM
  • Must be nice to Unicode strings
  • Must be nice to AJAX
  • Must serve some static files
  • Must server some dynamic content probably composed with a template system

Turns out there was only one system that I could locate that fit the bill, CherryPy. Getting the demo up and running was easy. Getting it to talk to COM was trickier. Its got something to do with threads and CoInitialize-ing them. The docs there almost have the magic formula, you have to hook on to whatever COM object you are calling after you call CoInitialize(). This means you can’t start up COM in the built in __init__ function of your root class in CherryPy, you have to call it from in the InitializeCOM()function, after the call to CoInitialize(). With that sorted I got the HTTP server to stop giving 501 errors and spit out the version of iTunes; “6.0.1.3 “. So far so good.

Now I am a big believer in the MVC pattern, code should stay in the code, and the view should be just the view. So next I wanted a template language to put together with CherryPy to complete my tool set. There seem to be a lot of these out there, mainly that want to mess with the HTML your writing to make sure your doing it right. Now, writing XHTML strict isn’t a problem and there is the posibility that I might generate some JavaScript code. The template engine has to be general, small size is a plus, easy to learn is a plus. Cheetah looks almost exactly like Velocity to me, and I’ve worked with Velocity before so its a good fit for a rapid prototype.