Monday, 25 June 2007

Durban, Paris, Valencia, Mangere

Quite a weekend. The highlight was being naughty by heading over to my mate's place at 1am to watch the All Blacks play the Springboks. The game was brilliant, well worth staying up for --- there's nothing like a last-minute come-from-behind victory! More games like this and TV viewers will be wishing for their own rest-and-reconditioning program. The All Blacks looked good but they need to carry on from here and reduce the error rate under pressure.

It's interesting how important luck is in sports --- I think its impact is highly underrated. A lot of games are decided by the bounce of a ball, referee decision or other incidents over which players have little control. But after a game which could have gone either way, you hear a lot of comments which would not have been made if the result had been different --- often focusing on the virtues of the winner and the deficiencies of the loser. This seems illogical, although natural.

Consider luck in the design of sports tournaments. In the America's Cup, there's a round-robin series followed by one-on-one semifinals, challenger final, and the actual Cup match. The latter three rounds are each decided by the best of nine races. In the Rugby World Cup, there's pool play (largely meaningless), followed by quarter-final, semi-final, and final rounds, each of which is just a single match! I think it's safe to conclude that thanks to this design, luck plays a much greater role in the RWC. Consider a rugby team that beats any other team 80% of the time; it would clearly be the world's dominant team, but its chance of winning the RWC is actually just a fraction over 50%. On the other hand an America's Cup team with an 80% chance of winning any given race after the round-robin is almost certain to win the Cup (94% likely, in my very simple model). I think other long-suffering All Blacks supporters will agree that the RWC format is not ideal...

This weekend's weather was typical Auckland: sunshine and rain alternating at high frequency. We visited Mt St John again for a quick walk on Saturday; it's one of the smaller volcanic cones around here, but I like it because it's quiet, has good views, and thanks to its size and geography (the distraction of much larger Mt Eden and Mt Hobson nearby?) is hardly noticeable even though it's nestled in the heart of the city between Newmarket, Epsom and Remuera. I think that I commuted to school between Remuera and Newmarket for five years without actually realizing it was there.

Today we got our fix visiting Mangere Mountain for the first time ever. It's actually really impressive. The crater is enormous, with high steep walls and a cute little lava dome in the middle --- a feature I haven't seen anywhere else in the Auckland volcanic field. There's two separate explosion pits at the bottom. The view looking up and down Manukau Harbour is really great; it's neat seeing Auckland from a southern vantage point. Unfortunately I can't post a photo because our digital camera is stuffed. We'll definitely go back for a closer look.

Shame about Team New Zealand losing their first race. It'll be interesting to see if they can come back.



Friday, 22 June 2007

Webstock Press

Peter Griffin at the NZ Herald has blogged about my Webstock presentation. It's pretty good although it doesn't capture the smile on my face when I commented about Safari market share.

Thursday, 21 June 2007

Wellington

Quick update ... had a great trip to Wellington yesterday. Thanks very much to Natasha and the rest of the Webstock gang. My Webstock talk seemed to go down pretty well apart from a couple of issues ... the extraordinarily bright lighting (needed for video recording) made it impossible to see the audience --- questions just came out of the void! Also, during the talk I got a wee bit confused about which version of the talk I was giving and went into autopilot for a little while ... dunno if anyone noticed! I met a bunch of interesting people whose names I mostly forgot --- sorry everyone! My name-remembering neurons have been mostly cannibalized for other purposes.

Earlier in the day I gave a similar, more research-oriented version of the same talk at Victoria University. It was a lot of fun being there talking to academic types again about research, and Firefox of course.

I made recruiting a bit of a theme yesterday. Some people seemed interested although I haven't received a flood of emails (yet?). It breaks my heart to hear about terribly smart people doing IT backends or ex-browser-developers working on bank contracts! There's a better way to live!

Wellington turned on great weather yesterday, and looked lovely. The flight down was great too, with a fantastic view of Mt Taranaki ... truly an ur-mountain.

In Mozilla news, Vlad and I sorted out the new-textframe crasher that caused problems when we tried to turn on new-textframe last week. Hopefully we'll get it turned on for real tomorrow. I'm feeling rather swamped right now with 90+ bugs worth of bugmail to read. Hopefully I can dig out soon. Chris is making great progress on <video>, now he can play at least 640x480 without dropping frames or losing AV sync. His code also has the nice feature that decoding happens on its own thread so it benefits from multicore. Still lots to do...



Saturday, 16 June 2007

15 Minutes With A Tucked-In T-Shirt

Being picked on by bullies at school is one thing, but to achieve supreme nerd credentials, try being ridiculed in the press for the way you dress. (BTW Juha, Chris was wearing jeans and a sweatshirt... stay alert mate!) Perhaps I should get an extreme makeover and expense it to Mozilla.

The Auckland Web meetup was a lot of fun. The talk seemed to go down well. After a slow start the audience warmed up and asked some good questions, although none of the tricky ones I was expecting. I hope I didn't seem rude to the person (Cindy?) who asked about CSS styling of scrollbars! ("No, because we have taste!"*) Thanks also to Nigel for being a good sport when I had to make a few remarks about the dominant browser vendor.

The demos went well, although in the run-up before the talk we discovered some interesting issues with Chris' video patch. We really need someone to maintain a set of Firefox/Gecko demos that we can share ... it's quite a bit of work and no doubt there's cool stuff I could have shown that I just didn't know about or have time to pull together.

The other talks were interesting. Electrocity is a lot of fun; really cool project. Nigel's WPF/Silverlight talk was really good. The lead-in slides were a bit wooly to be honest, but the meat of the talk and the demos were awesome even though I'd seen or heard about most of them already. The C# vs Javascript chess match demo was a bit annoying just because it's portrayed as a contest between languages when it's more about implementation techniques. Yes, untyped Javascript is harder to write a good compiler for than a statically typed language, or even other dynamic languages, thanks to dynamic properties and the prototype chain, but there's no reason to believe it can't be done.

One thing that was a concern was that it appears Silverlight allows any (untrusted) app to create a full-screen window. This makes a good demo but is very bad news for security: we work hard to ensure that untrusted content is always enclosed in browser chrome, to give a visual clue to the reduced trust level and reduce the chance of spoofing. I think Nigel said Flash 9 allows untrusted full-screen too; if so, this is something we need to look at. Another problem is that there is no visible way to get out of full-screen mode; a "Press Esc to exit full screen mode" cue is displayed briefly during the transition to full-screen, but it would be easy for users to miss or forget that.

I'm afraid in the rush to create "compelling experiences" and offer more to application developers, people are glossing over important issues of trust. People keep talking about blurring the boundaries between the desktop and the Web, but a key difference is that generally desktop apps are highly trusted and Web apps have little to no trust. (This is a good thing for Web apps, because a trust decision is a major barrier to use ... although often not high enough!)

One way to look at things is that traditionally desktop apps have had a set of capabilities that Web apps have lacked: rich graphics, offline capability, native-looking user interface, media support. Now we can bring those features to Web apps, that's cool. Likewise there's features that Web apps have had and desktop apps lacked, like zero installed footprint and trivial auto-update, and they're travelling in the other direction. But there's another set of capabilities that desktop apps have, like access to your local file system, your address book, your webcam, and your intranet, that we will never want to give to random Web apps. And although policies for granting some kind of limited access to some Web apps are worth talking about, I suspect that a simple "trusted/not trusted" binary model is about as complex as most people can handle, and maybe too complex already.

* That was a lie actually. Well, we do have taste, but the real reason we've never supported IE-style scrollbar coloring is that a) it was never high enough priority and b) you can't really do that and get the correct platform look using the theme APIs we have access to. As far as I know.

PS, sorry Ulrika, but the Computerworld article A Kiwi sits 'on the edge of tomorrow' at Google infuriates me! This person is naive and condescending ... fortunately unlike the Googlers I know.



Bad Steve

John Lilly has a great post about the scary Steve slides from Apple's WWDC. Jobs' vision of the Web as a cozy duopoly is unsettling for all sorts of reasons, but it also makes little sense for Apple. Ongoing IE dominance would mean ongoing Web stagnation, and that would risk Apple losing platform control to Flash and Silverlight.

It's also an interesting message to people outside Apple who are building on Webkit...

Apple's Webkit developers have been good community citizens for a long time and I have tons of respect for them. I hope that continues, Steve Jobs notwithstanding. (Actually what I really hope is that those slides represent some marketing idiot's brain explosion and not Steve Jobs at all, in which case we can all calm down.)



Tuesday, 12 June 2007

This Week's Madness

I'm working flat out to get new-textframe ready for turning on by Tuesday (PDT, which means really Wednesday here). The main issues left are performance and word selection/caret movement. The former is more difficult and interesting than the latter. I've identified and addressed a few issues:


  • On very large blocks, we could burn a lot of time scanning from the start of the block to find a place to start (re)building textruns for text that has changed. I changed this to scan backwards from the changed text, which is more complex but more efficient.
  • On Mac we were hurting badly in some situations where new-textframe was computing slightly larger font heights than other parts of the code; we'd end up adding overflow rects everywhere which turned out to be quite expensive. I fixed that by making font height float-to-int conversion consistently more conservative.
  • We were spending a lot more time in the platform text engine (e.g. ATSUI) with new textframe in some cases, for two reasons. We were failing to cache textruns when the textrun was relying on the DOM text node for text storage to save memory. This was easily fixed by disabling that "optimization". Also, the old textframe effectively caches textruns for individual words, which can save a lot of time in text that uses the same words repeatedly. I replicated this optimization for the new textframe. In fact the new textframe is even smarter; given a new string to build a textrun for, it looks up each word in the cache and makes a new string containing all the words that were not found in the cache, passing that to the platform text engine. This gives us the best of both worlds: avoids measuring any word more than once, but still passes reasonably long strings to the platform text engine (the engines have considerable overhead and passing words down one at a time is not recommended!).

I need to reprofile, especially on Windows, to see how we're doing now.

All this activity is why I've been a little slow on reviews lately. Things should lighten up by the end of this week...

... Except that I also have to prepare for a talk I'm giving at the Auckland Web "Meet-Up" this Thursday night. It sounds like there'll be over 100 people there and it should be a lot of fun. This will probably be the first ever public demo of Chris' <video> tag support, which is starting to look (and sound) really good! The office grooves to the sweet sound of ukuleles...

Also next week on Tuesday I'm going to be in Wellington giving a similar talk to the mini-Webstock that evening. And I'm taking the chance to visit Victoria University, give a talk there, meet some of the staff and students in the CS department, and hopefully do a little recruiting. Phew!

Still working on a good name for the Chronicle debugger. Current candidate: Chronologer.



Tuesday, 5 June 2007

Shrike

On my last trip to the USA I met up with Steve Fink again who I used to work with at IBM Research. He mentioned that the Shrike bytecode manipulation toolkit that I wrote several years ago is still being used and maintained at IBM and in fact has just be released (again!) as open source as part of the T.J. Watson Libraries for Analysis (WALA). This is cool...

I wrote Shrike because I was doing a lot of bytecode instrumentation of large projects and I was dissatisfied with the convenience and performance of available bytecode manipulation libraries; at the time, BCEL was the main contender, although IBM had an internal library called JikesBT. I'd written a bytecode reader for my thesis work at CMU and I thought I had some ideas that would let me write a library that was smaller, faster, and much more convenient to use than the existing options. In my humble opinion, I succeeded :-).

Shrike was based on a number of ideas:


  • BCEL parses .class file into one large mutable data structure representing a class and its methods. You can then modify the structure, e.g. by inserting instructions into a method, and then BCEL will compile that structure back into a .class file. This is slow, because a lot of data has to be parsed and then recompiled even if it's not modified. It's also a clumsy interface to use, because inserting instructions into a method requires manual adjustment of things like branch targets, exception handler ranges and the like. It's *especially* clumsy when you want to compose multiple independent instrumentation passes applied to the same original code --- you run head on into the problem of one pass instrumenting the code belonging to previous passes. Shrike avoids these problems by offering a patch-based API for code instrumentation. This means you specify your desired changes as fragments of code that should be inserted at specific points. You can add a number of patches, but none of the underlying code is changed until you request those patches be committed. Then Shrike makes one pass over the code, applying all patches and updating all branch targets, exception handlers etc for you. It's very convenient and very fast.
  • Similarly, Shrike doesn't actually give you any mutable object representing a class. There are class reader objects, which give you access to immutable class data, and class writer objects, which essentially are sinks you can use to compile a class. There are utilities for copying a class from a reader to a writer, of course with the option to modify things along the way. Methods and other class data which is not being modified can be copied directly without being parsed or recompiled! This is a huge performance win.
  • Shrike's code representation is better than BCEL's. BCEL uses a linked list of instruction objects; instruction objects are mutable and therefore created fresh for each instruction of each method. In Shrike instruction objects are immutable and the code for a method is simply an array of instruction objects. Inserting or deleting from an array would be slow but thanks to the patch API we don't have to do that. Because instruction objects are immutable, they can be shared within and between methods. This makes bytecode parsing very fast; for the Java bytecode instructions that take no operands, parsing just requires looking up the instruction object in a table and then storing a reference to that object in the code array.
  • Shrike also handles the exception handler ranges in a nice way. In the class file, each exception handler specifies a range of instructions it covers. This is a real pain to manipulate directly if you're moving instructions around or if you want to add or remove handling from a range of instructions. In Shrike there's just an array of exception handler lists, one list for each instruction. These lists are immutable so they can be shared by all instructions which have the same exception handlers covering them. This is very easy to manipulate and it turns out that converting handler ranges to these lists and back again is very efficient.
  • The Java bytecode format has an incredibly nasty feature called JSR --- little subroutines that you could use inside the code for a single method. This was an ill-advised attempt to avoid code explosion in the compilation of "try ... finally" blocks. Several people, including me, scored rather meaningless publications by discussing how to handle this quirk in type systems. Shrike hides it completely by converting all incoming JSR usage to inlined bytecodes; Shrike users never see JSRs.
  • The Java class file format restricts methods to 64K bytecodes. Some of the instrumentation I was doing was blowing this limit in a few methods (primarily static class initializers for certain library classes). Shrike deals with this problem by auto-magically breaking up oversized methods into one method calling helpers. It uses heuristics and may fail, but never actually does. It's a rather esoteric feature but invaluable when you need it...
  • Shrike provides simple dataflow analysis of its code representation. You can use this to figure out the type of any local variable or expression stack location at any instruction, which is very useful for instrumentation. Shrike also provides a bytecode verifier based on that, which is very useful for finding bugs in your instrumentation...

Despite all those features, Shrike is still a pretty small library. The emphasis on using immutable objects and arrays keeps the number of classes small. Using one class for instructions of the same kind (e.g., binary operators) also helps. It's also factored into one component "ShrikeCT" for reading and writing class files, and another component "ShrikeBT" for manipulating method bytecode; you can easily pick and choose components.

Looking back, I'm quite proud of Shrike. It was a real pleasure to do a small, focused project from scratch and get a lot of things right.

BCEL seems to have been eclipsed by ASM for manipulating Java bytecode. ASM seems to use the same "copy reader to writer" paradigm that Shrike does, so it's definitely going in the right direction. It would be interesting to compare ASM with Shrike in more detail, but unfortunately I don't have the time.

Zooming further out, I think it would be a fascinating intellectual and educational exercise to study situations where we have multiple libraries that export basically the same underlying functionality through different APIs --- bytecode instrumentation engines, traditional operating system kernels, traditional GUI toolkits, string libraries, bignum libraries, and so on. It seems likely one could make very concrete and defensible judgements that certain API design decisions were made better in one library than another. This could lead to some reliable and teachable "do's and don'ts" of module interface design, backed by interesting examples, that I think could be incredibly valuable to students of software development. This is important because genuinely teachable facts are heartbreakingly rare in software design. There's a great book here that someone needs to write!



Waikowhai

This long weekend the weather was variable, frequent showers but also some nice sunny periods. We tried to make the most of it. On Saturday we took some lunch out and visited Waikowhai Park for the first time. It was great --- wonderful view over the Manukau harbour, lovely green lawns, a nice playground, all surrounded by a large tract of amazing bush. The bush actually covers the entire hillside from the top of the ridge down to the water, so you can't see houses and you can barely hear any traffic --- it's very easy to forget that you're actually still near the heart of Auckland. My only disappointment was that the flying fox has been disabled.

Today we went back with some friends to check out some of the walking tracks in that area. Due to the rain they were a bit slippery, and there's a lot of up-and-down as you descend to beaches and climb back up hills, but we had a really good time. The forest there is the major stand of original old-growth forest left on the main isthmus, and it shows; tree ferns there were as big as any I've seen anywhere (some must have been six metres high or more).

The view out to Puketutu Island in the Manukau harbour reminded me that the island is going to become a park. It's going to be wonderful, the view from the end of the island out to the Manukau Heads should be awesome.

It's almost embarrassing that in two years we'd never been to this great park about ten minutes drive away. But Auckland has so many good parks, even dedicated explorers like us will take years to do them all justice ... and they keep adding new ones to make it harder. (Today we were thinking of going out to the Hunua Falls ... that's another area full of places to explore, just an hour away, and as far as I can recall I've never been there!)



Saturday, 2 June 2007

Status Update

Vlad and Stuart took off for the long weekend today after which they head back to Mountain View. It was fun hosting you guys! The office will be quiet again.

We did some Tp2 performance benchmarks with text in various configurations. On my Mac and the office Linux box, new-textframe seems to either have negligible impact or be a slight win. On Vlad's Vista laptop, it's a 5-10% slowdown. This is bad. I plan to look into this next week. Unfortunately when I tried to install Windows XP on the office box to get started on performance analysis, I realized that that box (an HP Proliant ML350) doesn't actually support Windows XP. That sucks. I'm going to have borrow Chris' laptop for a few days... (Ubuntu 7 had installed on it just fine, and it never crossed my mind Windows XP would have a problem with it. What a nightmare Windows installation/licensing/activation is...)

Earlier in the week I did some testing with my glyph bounds work-in-progress and found that on my Mac, performance impact was negligible using ATSUGetGlyphScreenBounds and my specialized glyph extents cache. That's probably another area where I'll need to do further performance analysis for Windows. Something to do after the new textframe is turned on.

In the meantime I've been fixing other random bugs, mostly various regressions from the new textframe.

We had an interesting discussion about text rasterization on Windows. There are basically three different high-quality rasterization schemes available, in increasing order of quality:


  • Cleartype with "compatible widths". This is what GDI apps get by default on XP and Vista. "Compatible widths" means that Cleartype hinting isn't allowed to change glyph advances, so layouts are identical to what you'd get with Cleartype off. This is what we currently get.
  • Cleartype with "natural widths". GDI apps can get this on Vista (but not XP, AFAIK) by setting some undocumented flag. This allows hinting to change glyph advances. We should definitely use this when available since Web apps don't get pixel-accurate layout compatibility anyway.
  • WPF. This adds subpixel positioning and vertical subpixel antialiasing, and maybe other things. This doesn't seem to be available to GDI apps at all via published interfaces. We would like to use it but it's not clear how. We tossed around some crazy ideas, none of them appealing. Definitely not happening for 1.9.

On the bright side, on Mac we're getting subpixel positioning and antialiasing in all directions, so our cross-platform code is being tested for that already. If/when better rasterization becomes available we should be able to plug it right in.

In other news, Michael Ventnor has stepped up with a patch to fix some issues with GTK2 themes for HTML form controls and turn them on. We're going to try turning them on early in alpha6. We may revert the patch if there are major blocking issues that no-one steps up to fix. Now that Aqua form controls are on (nice work guys!), it would be nice to bring Linux/X up to speed too.

I finally landed the patch for getClientRects/getBoundingClientRect. This is a nice pair of DOM APIs that are mostly IE compatible, in the sense that elem.getBoundingClientRect().x/.y - document.body.getBoundingClientRect().x/.y should give you consistent results on IE and Firefox for elements that are descendants of the body (assuming the layouts are the same). The compatibility is limited in this way because we refuse to emulate some insane IE quirks regarding the body's reported position.

There's a bug about implementing document.elementFromPoint(x, y). This would be really easy to do if I wasn't swamped. It would be a good feature for someone new to come in and implement. It just needs to be added to the DOM IDL and implemented using the same display list machinery we use for event handling.