Main menu:

Site search

Categories

Archive

A Short Guide to Interviewing

I’ve been meaning for a while to write a post on how to interview software engineering candidates: here it is. In my opinion, there’s really no science to interviewing: it’s an intuitive, practice-based activity. So, as Barry Schwartz suggests in his book Practical Wisdom, I’m going to try to express what I know in just a few simple guidelines on each topic. First, a couple of general remarks:

  • Interviewing is important. Interviewing a candidate well is one of the most productive things you can do for your team in two hours as an engineer. So give interviewing the same attention and care as you do coding and debugging.
  • Interviewing takes practice. If interviewing feels awkward, or you get nervous, or you think you have no idea what you’re doing, that’s totally normal, and fine: you will get better with practice, and also more relaxed. It may take 3, 5, 10, or more interviews to hit your stride, but you will.

Basic Interview Template. Here is a basic 5-step interview plan, which you can use directly at first, and later adapt according to the specific interview and your own style:

  1. Greet the candidate and introduce yourself. The purpose is to make the candidate comfortable and mark the start of the interview. Example: “Nice to meet you. I’m Dave Mandelin. I work on JavaScript. Before we start, do you need a break or anything to drink?”
  2. Ask about experience listed on the resume. The key here is to follow your curiosity–look for things on the resume that intrigue you and try to have an interesting conversation. Examples: “What was the project? What was your role? What did you learn? What was hard about it? How would you handle this variation of the problem?”
  3. Ask about interests. This is to learn about fit and motivation. Examples: “Why do you want to work here? What roles are you interested in? What projects would you like to join?”
  4. Ask your technical questions. Ideally, ask questions that are similar to what comes up on the job, or even have the candidate write some code on a laptop. Problem-solving ability and communication skills are as important as getting the right answer. Experiment with different questions, but eventually you will want to have a standard set so you can calibrate the responses.
  5. Invite the candidate to ask you about anything. Like the greeting, this part is really for the candidate. They deserve a chance to interview you too, to see if they really want the job.

Before the interview, prep by scanning the resume for interesting things to ask about. Also, pick out what technical questions will be appropriate for this candidate. In general, don’t find out what others thought of the candidate–go in fresh and see for yourself.

After the interview, think about how it went. Did you learn everything you wanted to about the candidate? Were your technical questions too easy, too hard, or just right? Did you spend the amount of time you wanted to on each topic?

Writeups. After the interview, write up your findings promptly, while your memory is fresh. Doing a good writeup is a lot of work: it may take over an hour at first.

I use a template based on the interview template, with four sections: summary, experience, interests, and technical. The latter three are the detailed sections, and I write them first. The summary is for busy readers and for you at debrief.

For the detailed sections, I write down what I asked about, and what I found out. I usually include a few evaluative remarks: e.g., “simple project, but creative”, “communicated the answer very concisely”.

The summary section starts with a summary of the summary: a one-sentence take on the candidate. Then it gives highlights from the details, and strengths and weaknesses. Last come general discussion and evaluation.

Evaluation. The last step is to decide whether you want to hire the candidate. This goes in the writeup summary and of course you will say it in the debrief. Choose one of these four:

  • Champion, or strong recommend hire. This means you will strongly advocate and argue for the candidate at debrief. Say this if you think the candidate will become a leader or outstanding individual contributor, i.e., the candidate would be a peer to your senior team members.
  • Yes, or recommend hire. This means you want to hire the candidate. Say this if you think the candidate will become an above average member of your team, i.e., the candidate would fit in as a peer on your team.
  • Veto, or strong recommend no hire. This means you seriously don’t want to work with this person. Say this if the candidate is clearly unqualified or you see serious behavioral issues.
  • No, or recommend no hire. This is the default answer. If you are concerned about issues that are not serious enough for a veto, say no. If you think “maybe”, or “don’t know”, say no. It’s OK to say no: you are not making the final decision right now, and you might be persuaded to say yes at the debrief. Saying no is hard, and deciding not to hire a candidate is sad. There’s no getting around that. But remember that you have a responsibility to your co-workers to hire the right people, and to the candidate not to hire them to a job where they won’t thrive.

Final thought: try to have fun. Interviewing can be fun: you get to meet people, talk about their work, and reflect on the experience. If you enjoy interviewing, it won’t seem like a chore, and you’ll find it easier to give it the mindful effort needed to do a good job. Also, if you go into the interview expecting to have fun, the candidate can pick up on that, connect with you better, and show you more of what they’re all about.

Know Your Engines at O’Reilly Velocity 2011

Yesterday I gave a talk at O’Reilly Velocity 2011, “Know Your Engines: How to make your JavaScript fast”. The concept came from the common idea that C++ programmers should know something about how the compiler works on their code in order to know how to get good performance. Why not for JS? So I basically offered what I know as a performance-focused engine developer: how the engine works in general, how it tries to make code fast, and what kind of code will defeat engine optimizations and make things slow. I figure it was pretty heavy technical stuff (including plenty of computer science) by the usual standards, but it seems to have gone over pretty well, judging by the tweets, and hopefully it will help developers make faster and more capable JavaScript apps.

I covered the full range of engines, from the interpreter-only designs of a few years ago (as background), to the function-by-function JITs currently in the latest version of every major browser (e.g., JägerMonkey), the current and possible future type-specializing JITs (Tracemonkey and Crankshaft, with brief mention of David Anderson‘s very exciting IonMonkey project), and a little bit on Brian Hackett’s type inference branch. (I heard afterward that Microsoft’s Chakra team is working on type inference as well, but a quick search didn’t turn up any real info–if anyone knows more, I’m curious.) The high bit is that if you write JavaScript that could have Java-oid type declarations applied to it, current and future engines will for the most part be able to magically figure out what those declarations would be, and make your code much faster. There’s a lot more in there about things like what a type really is in the engine, how property lookups are optimized, and what kinds of properties are fastest.

GC pauses are a major concern for interactive apps and games, so I had a section on how GCs work, what’s coming from engine developers to control pauses, and what can be done for now. I had to go kind of quickly through that section, so I want to add a few more notes here:

Bill McCloskey has a prototype of incremental GC for Firefox. It can slice the mark phase up finely enough to keep pause times below 1 ms. It doesn’t directly address sweeping, but we do most sweeping on a background thread, anyway (and sweeping can also be interleaved with allocations in order to keep pauses down). Currently the write barrier slows things down too much for production, so he’s still checking that out.

Recommendations for avoiding GC pauses depend on what kind of GC the browser has. For now, if you want to reduce pauses on all browsers, you have to assume a simple stop-the-world mark-sweep collector, in which case there are 2 key things to know. First, the length of pauses is roughly proportional to the total size of reachable heap objects (which include JS objects, arrays, strings, and functions), because the mark phase has to traverse them all. Second, the frequency of pauses depends on the allocation rate, that is, the number of bytes allocated per second, because using up memory is what triggers the GC to run.

A simple model of a program running under generational GC is that it starts up, allocates a bunch of objects, and then settles down into a steady state. In the steady state, there is a working set of W (bytes) allocated memory that stays allocated, and then a churn rate R (bytes/sec), where every second R bytes of temporary objects are allocated (e.g., short-term closures, strings being concatenated into results). R determines how often pauses occur, and W how long the pauses are. So, you could entirely avoid pauses in practice by having either W ≈ 0 (so pauses are unnoticeable) or R ≈ 0 (so pauses don’t happen in the steady state, only during startup).

I finished the talk with some gritty practical bits I discovered by running a whole bunch of microbenchmarks, based on educated guesses about what would turn up performance faults. Probably the most important is that eval, with, and throwing exceptions are not only generally slow operations, but they can deoptimize nearby code and cause much greater slowdowns than you might expect. Another big one is that dense arrays are much faster than sparse arrays–see the slides for details.

My slides are online at the O’Reilly page for my talk. I also have my own copy of the original Keynote version, and a pdf. Demis Bellot has also conveniently put them on SlideShare.

Thanks to everyone who tweeted praise for/interest in my talk (that I found in my mentions at least): piscisaureus, kamidphish, colinbdclark, rednaxelafx, djco, demisbellot, porteneuve, brendankenny, paulbiggar, slicknet, demisbellot, alex_gaynor, devongovett, juanpin, derek, SkipSauls, and of course Brendan. I truly appreciate your letting me know you enjoyed the talk (or expect to enjoy it!). And thanks again to Steve Souders and the Velocity conference chairs for hosting me and making it all possible!

Firefox 4 Release Parties in Indonesia

Earlier this month, I got to fly to Indonesia to attend Firefox 4 release parties along with David Anderson and Josh Aas. (Gen Kenai, Luke Wagner, and Christian Legnitto also went to Indonesia, for “Leg 1″ just before we got there.) Sorry about blogging this so long after the fact–I’ve been recovering, catching up on duties here, and fixing up regular expressions. David already told the story on his blog, so instead of repeating that, I’ll offer up some personal reactions.

The highlight of the trip was certainly interacting with our hosts, Viking Karwur, Yofie Setiawan, Andi “Belutz”, and Irayani “Rara” Queencyputri (although I only got to talk to Rara for about 5 minutes–more below). I’m not a seasoned international traveler, but I felt like I had friends waiting for me, they always took care of us, we had many interesting conversations about daily life and other things in Indonesia and the United States (turns out Burger King and Starbucks are the same price), and of course they taught me how to say “thank you” in Indonesian: Terima Kasih!

The trip was physically demanding: we had to go through a +14 hour time change along with 22+ hours of travel, then 85°F+ temperatures every day (and I’m a pampered 72°F Bay Area person now), smoky megacity air, plane travel every day (except 6 hours in the car another day), and a public appearance scheduled for each day.

And then I got sick on day 3. In a taxi. Maybe that’s TMI already–anyway, it was pretty bad. I had 36 hours of misery. Fortunately, thanks to Yofie and the bartender at our Surabaya hotel, I had an Indonesian SIM card, so I could call Natalie and get some comforting. And thanks to an internet meme of a few years back, I knew Pocari Sweat was just what I needed to rehydrate myself. Finally, thanks to Josh Aas and his Cipro, I was able to recover enough to make the final event in Bali.

So, in some ways, the trip was rather an ordeal, but still a great experience. We had a wonderful dinner with Arry at Bandar Djakarta, and I tried Rawon in Surabaya, also delicious.

in Surabaya

I really liked answering questions at the events, and I really liked the way people were entirely willing to ask hard questions: are you releasing more often just to pump up version numbers? (absolutely not–hopefully by Firefox 26 people will be over version numbers anyway), why does Firefox use so much memory? (a: Fx4 caches a lot of things in order to be faster, b: we’re working on it), will Firefox ever run on Blackberry (doubtful). There were about a zillion photo ops, until the point my face got sore from smiling so much.

I loved seeing all the energy in Indonesia: huge new apartment buildings going up in Jakarta, motorcycles everywhere, electronics stores and ads for phones everywhere. According to the pamphlet in the Garuda Air seat pockets, the median age is about 29 and the economy is growing at 6% per year, so no wonder.

And yes, David did get called Justin Bieber a lot.

Mozilla JavaScript 2011

So, JägerMonkey is done (as of last fall, really), and Firefox 4 is out (yay! and whew!), so that means we can get back to the fun stuff: new coding projects. At the Platform Work Week, we firmed up plans for JavaScript for the next year or so. The main themes are debugging and performance:

New Debugging API. We are going to give the JS engine a new debugging API, called the Debug object. The new API will provide a cleaner interface and better isolate debuggers from the program they are debugging. This should make Firefox debugging tools stabler and easier to work on. The most exciting part is that the new debug API allows remote connections, so in the future we should be able to do things like debug a web page running on a mobile device using a debugger running on a laptop.

Jim Blandy designed the API last year, so now we just need to implement it. Jim and Jason Orendorff are starting that now.

Incremental and Generational GC. GC (garbage collection) pauses are probably the biggest practical performance issue right now in Firefox. (Note that there are other sources of pauses as well, such as the cycle collector and perhaps IO that happens on the main thread.)

(Background on what GC is if you are not familiar: As a JavaScript program runs, it creates objects, arrays, strings, and functions, which take up memory. In order to not use up all your memory and crash, the JS engine must be able to automatically discover which objects are not in use anymore (so they are now “garbage”) and free them up. This “automatic memory reclamation” subsystem is called the garbage collector, or GC.)

The reason for the pauses is that SpiderMonkey uses an old-school stop-the-world mark-and-sweep collector. Briefly, it works like this:

  1. Based on some heuristics, the JS engine decides it is time to collect some garbage.
  2. The GC finds all the GC roots, which are the immediately accessible objects: JS local variables, the JS global object, JS objects stored on the C++ stack, and a few other things.
  3. The GC marks all objects that can be reached from the roots, by following all the pointers stored in the roots, then all the pointers stored in the objects reached from the roots, and so on.
  4. The GC sweeps over all allocated objects. If an object is not marked, there is no way for the program to access it, so it can never be used again, and the GC frees it.

The main problem with stop-the-world mark-and-sweep GC is that if there are a lot of live objects, it can take a long time to mark all those objects. “A long time” typically means 100 milliseconds, which is not that long, but is disruptive to animation and is noticeably jerky.

Our first step in fixing GC pauses will be incremental GC. Incremental GC means that instead of stopping the program to mark everything, the GC periodically pauses the program to do a little bit of marking, say 3 milliseconds worth. There is an overhead to starting and stopping a mark phase, so the shorter the pause time, the slower the actual program runs. But we think we can make the pause time unnoticeable without having too much impact on throughput.

Note that the sweep phase can also take a long time, so we’ll need to do some work there also, such as sweeping incrementally or in concurrently on a different thread.

The longer-term goal is to move to generational GC. It’s more complicated than incremental GC, so I won’t go into details now, but the key benefits of generational GC are that (a) it is very fast at collecting short-lived objects (technically, it actually manages to collect them without looking at them or doing anything to them at all), and (b) it helps make creating objects faster.

Bill McCloskey and Chris Leary are working on the new GCs. Gregor Wagner has also been working independently on specific improvements, like doing more sweeping off the main thread.

Type Inference. Currently, TraceMonkey and Crankshaft generate really fast native code for JavaScript by observing types of values dynamically as a program runs, then compiling native code specialized for those types. The idea of type inference is to try to go one better by inferring types using static analysis, then compiling specialized native code. A key potential advantage of type inference is that (depending on the program) it can say for certain that a given value has a given type, so the type doesn’t need to be checked in the native code, as it does in the dynamic systems. Fewer runtime checks means faster code.

There are two things that need to be done to make this work. First, you need a type inference algorithm that runs on JavaScript. Second, you need to adapt a JIT compiler to use the inferred types to generate better code.

Brian Hackett started this work early last year as a research project, and has had the type inference algorithm working for a while now. He is now working with volunteer contributors to adapt the existing JägerMonkey compiler to use the results. As of today, they’re running the major benchmarks in the JS shell just a bit faster overall than trunk, but expect that to improve. I tried an integer array microbenchmark the other day, and the TI branch was 40% faster than either TraceMonkey or Crankshaft, both of which are very good at that sort of thing.

IonMonkey IonMonkey is the name of our next JIT compiler. Like Crankshaft, it will feature SSA compiler IRs (intermediate representations), which will facilitate advanced optimizations (for untyped-language JITs–Java compiler writers might not consider these advanced) such as type specialization, function inlining, linear-scan register allocation, dead-code elimination, and loop-invariant code motion.

This should mesh nicely with type inference, by making it a lot easier to do the optimizations better that type inference enables. For example, type inference is potentially particularly good at inlining. One of the key benefits of inlining is that it allows optimization across the call boundaries. But the existing JägerMonkey compiler doesn’t know how to combine functions, so the type inference branch compiles the inlined function separately and drops in the resulting machine code. IonMonkey will be able to patch the inline function into the other function’s IR and then optimize both together.

IonMonkey is currently in the design stages–David Anderson and I are studying the compiler literature and the competition and doing experiments to find out just what features IonMonkey needs. Coding is about to start.

Wrapup. Debugging, GC, type inference, and IonMonkey are the E-ticket items–we’ll do other things too, like small optimizations, ES5 improvements, bugfixes, and hopefully a JavaScript sampling profiler. And I haven’t covered any of the research stuff, like ES6–that’s Andreas’s department.

Console for hacking Mozilla on Windows

This post is just a little tip for hacking Mozilla on Windows. It’s well known that the basic Windows console program is, uh, not good, compared to a Unix console. But it turns out there’s a really nice project on SourceForge named Console that provides multiple tabs, good fonts and scrollback, keyboard shortcuts, and a few other goodies.

Chris Leary asked me to write this up so that other people know about it (and people have been asking lately). Justin Dolske was the person who pointed me to the project in the first place.

Anyway, a few tips for using Console for Mozilla hacking:

  1. It’s just a zip file containing a program. There’s no install, you just run it.
  2. For mozilla-build, you want to create a new “Tab” in the settings. For example, I have one called “Mozilla ia32″, with Shell set to “C:\mozilla-build\start-msvc9.bat” and Startup dir set to “C:\mozilla-build”.
  3. With the latest version of mozilla-build, it doesn’t work right if you just do that. What will happen is that the tab will start up, then shut down as a standard Windows console opens. (Very annoying, because if it’s the only tab, it’ll even close down Console, so you can’t easily fix it.)

What you need to do is find your startup batch file (e.g., start-msvc8.bat) and change the last line from:

    start /d "%USERPROFILE%" "" "%MOZILLABUILD%"\msys\bin\bash --login -i

to

    "%MOZILLABUILD%"\msys\bin\bash --login -i

Console project on SourceForge

Grill Engineering

Time for a weekend-themed blog post.

Background: I always found getting steak done right to be one of the hardest cooking feats. My typical result was to cook the steak for a while, until the outside is kind of burned and it looks done, then serve it up to find the center is cold and red. And there seems to be a lot of contradictory, context-free, unvalidated advice out there, so it’s hard to learn better by reading. Recently I took an engineering approach to grilling and I think I’ve got it figured out. I used lessons from the JägerMonkey project: start by reading up on different designs, analyze their differences, try to figure out who’s got it right, and do some experiments to clear up unanswered questions. I ended up learning 4 big things:

1. Let the steak thaw before cooking. I’ve found it much easier to get the inside done right without charring the outside if the steak is near room temperature. I leave the steaks in the refrigerator overnight or during the day, and then on a cutting board for about 30 minutes before cooking.

2. Season liberally. I used to season steak lightly or not at all, but I’ve found it’s much better if I use plenty of salt and pepper. Natalie swears by sea salt, and I insist on freshly ground pepper. Watching restaurant chefs seems to be the best way to get a baseline for how much to add, and then you can add more or less as you like it.

Adding a little bit of oil before cooking also seems to be standard restaurant practice. I use a little bit of macadamia oil because it does well with high heat and some chef told me to in a YouTube video I can’t find right now. I think it’s mostly to just help the steak not stick to the grill.

Some sources say that putting salt on meat before cooking dries it out, but that is completely wrong.

3. Cook by temperature. This is the most important point: With an accurate thermometer, you can repeatably cook steak to the exact doneness that you like. Some people say poking steaks with a thermometer makes the juices run out, and instead recommend prodding it with a finger to test firmness, or various other things. But I’ve found that I can stick the steaks with a thermometer as many times as I want without harming them, and the thermometer is much more precise than any other method. Maybe if you are a restaurant chef and have cooked 3000 steaks you can do it better with a finger-squeeze, but I sure can’t.

As with everything else, the web disagrees on what temperature is medium rare, medium, and so on. Part of the problem is that the temperature at the center will continue to increase for a few minutes after taking the steak off the grill, so when a temperature is quoted, it’s not clear whether a quoted value is the temperature you cook to on the grill, or the final temperature.

The critical decision is when to take the steak off the grill, so that’s the temperature you need to figure out. I’ve found that stopping cooking at 125 °F yields a good medium rare steak for me, and 133 °F a medium steak for Natalie. It probably goes up by 5-10 °F afterward, but I haven’t done that experiment yet.

For a one-inch-thick steak, it takes my grill about 8 minutes to cook to 125 °F, so I set the heat on high, cook for 2 minutes, rotate 45° (to create a nice cross-hatched grill mark pattern) and cook for 2 minutes, flip and cook for 2 minutes, rotate 45° again. After another minute or so, I start taking temperature readings with an “instant-read” meat thermometer. Once it’s close to done, I hold the thermometer in and remove the steak from the grill immediately once it reaches the desired temperature.

The keys are: (a) experiment to find out at what temperature it’s done the way you like it, (b) experiment to find out about how long it takes to get to that temperature, (c) monitor the temperature continuously once it is almost done, and (d) use a high-quality thermometer. I use this one, because as an engineer I like fancy instruments and I enjoy taking the temperature of random objects using the infrared function.

4. Rest the steaks. This one isn’t controversial, but not everyone has heard about it. In general, meat should be left to “rest” for a few minutes after cooking. I haven’t figured out exactly how long it should be, but 10 minutes seems a little too long, and I recently saw a random web page that recommended half of cooking time. That would be 4 minutes for my one-inch-thick steaks, so I might try that, but usually it just ends up being however long it takes to finish setting the table and serve the other dishes.

That’s it. That’s all I know, and it’s enough to cook steaks just how we like them. The same basic idea works for pork, chicken, and fish–the main difference is the target temperature.

Crankshaft

The V8 team has dropped Crankshaft, a new JIT system for JavaScript, into their bleeding-edge repo. According to their blog entry, it doubles their speed on 3 of 8 V8 benchmarks, and improves page load time by 12% on JS-heavy pages.

First off: Congratulations to the V8 team. It looks like great work, pushing forward what kinds of things JS can do in the browser. I look forward to checking out the code.

Analysis. I haven’t looked into the details yet, but their blog post has a good summary and I can make some guesses based on my own knowledge of the subject. I think the key features are:

  • Dynamic recompilation. Crankshaft introduces an optimizing compiler that does complex optimizations, such as register allocation and loop-invariant code motion. These optimizations take time, so they would make startup slow if that was the only compiler. But Crankshaft also has a base compiler that starts fast but doesn’t optimize very much: probably less than the V8 compiler, in fact. Only if the code is predicted to run many times will it be compiled with full optimization.
  • Profile-driven type specialization. That means Crankshaft records the types of variables and the targets of function calls at runtime, and then recompiles methods specialized to those types and targets.

I have to point out that runtime type specialization for JavaScript was pioneered by Mozilla’s Tracemonkey project. It looks to me like Crankshaft adds three new things to the type specialization mix: (1) instead of recording a trace once and then doing type specialization, they profile over multiple iterations so they can gather more information, (2) compiling whole methods instead of linear traces, introducing a bit larger scope to the optimizations and reducing code size, and (3) using ICs along with type specialization.

Another indication that Crankshaft and Tracemonkey are fundamentally related: Crankshaft gets a big boost over V8 on the benchmarks deltablue, richards, and crypto. Tracemonkey gets a big boost over JaegerMonkey on deltablue, richards, and splay.

(Historical note: Most of the fundamentals of JIT optimization were established in the research language Self in the 80s and 90s. Subsequent work has typically focused on porting those techniques to new languages, adapting them to modern processors, and making various incremental improvements. In the 90s and 00s that was done with Java, which gave us our modern high-performance Java JITs. It looks like the 00s and 10s will see it done for JavaScript. It’ll be interesting to see how close JS perf gets to Java.)

Response. The Mozilla JavaScript team and developer community definitely have the skills and resources to enhance our dynamic type specialization system with ICs, more profiling data, wider compilation scope, and whatever else we can think of. So we won’t get left behind.

Also, we’ve already been working on static-analysis-driven type specialization. This means using static analysis to discover the types and targets ahead of time and then compiling with type specialization. The Self researchers found static and dynamic analysis to be about equally effective for optimization, but we won’t know whether that’s true for JS until we’ve tried it.

Brian Hackett created and implemented the type inference project, which is documented in bug 557407 and bug 608741. The code is in the JaegerMonkey repository. Brian is currently fixing bugs and integrating his work into the JaegerMonkey engine, and he already has some very promising performance results.

So, plenty to do after Firefox 4 comes out. In the words of David Anderson, “The game’s back on.”

Kraken Benchmark Update

colinpj tweeted me “Can you post kraken results using the same browser versions + setup?” Here you go:

Browser Sunspider update

IEBlog recently showed some Sunspider results that show them currently ahead of us. I just want to correct that a little bit. :-)

The latest Firefox shown on their graph is Firefox 4.0 beta 6, which is well behind our nightly releases at this point, including in performance. Their graph shows the Chrome 8 nightly, but nightlies for no other browsers. So I decided to do a comparison test using Sunspider 0.9.1 on the latest version I could get for each of the big 5 browsers. Results:

So, not terribly different from their results, except that it shows we’re a hair faster as of now, at least on this machine. We are currently finishing up a last few perf projects before we turn to focus on getting it ready for release. I’m expecting us to get 3-10% faster by then, but that’s just a guess. I’m sure IE is still working on perf as well.

A final point is that the graph shows pretty clearly that Sunspider scores are converging: the days when one browser would be 2x or 6x as fast as another are gone. Now it’s more like 1.1x or 1.2x. I know there are a few more tricks we can play that are too complicated to do before Firefox 4.0, but they would make only a small dent in Sunspider scores. By next year, either we’ll all be fast and basically done with JS perf work, or else it will be time to update the benchmark to help drive the next round of perf improvments.

Update: sdwilsh pointed out to me that the IEBlog post shows a date of “10/25″ for Firefox, which isn’t the build date of beta 6. So it might actually be a nightly build from a week or two ago. Not clear.

Jägermonkey: it’s in ur browser!!!

At the beginning of this year, the Mozilla JavaScript team started a new project, code-named JägerMonkey, with a simple goal: make us fast.

Our previous major engine upgrade, TraceMonkey, gave Firefox 3.5 a big speed boost. But while the technology inside TraceMonkey makes it faster than any other engine on certain programs (then and now), it doesn’t help other programs as much. And the web has grown more complex, with more and more JavaScript-intensive demos, apps, and games. And the competition has been getting a lot tougher, with engines that could run fast on bigger and prettier web apps. We knew we needed another major upgrade for Firefox 4.0, to make us fast all around.

So, we went off for 8 months of studying the classic research, reverse engineering the competition, measuring, experimenting, designing, prototyping, analyzing performance, scrutinizing assembly code, redesigning, coding, and lots and lots of debugging. David Anderson and I intend to blog more about the techniques and technologies we used in our copious free time in the weeks between now and release.

As part of the project, we revamped the JavaScript engine’s fundamental value type, touching about 20,000 lines of code, which I compared to a vascular system transplant in an earlier post. We imported a couple of basic components, the assembler and the regular expression compiler, from WebKit’s JavaScriptCore. We created a new cross-platform whole-method JIT compiler in about 23,000 lines of code. It supports x86, x86-64, and ARM in an almost entirely shared compiler code base, the only JS engine that does so (to our knowledge). And it all works together with the existing TraceMonkey trace JIT compiler.

You can try the new JavaScript engine now in Firefox 4 beta 7. If you try them, you should see:

  • Big improvements in benchmark scores. Those aren’t the main goal–but they are a really convenient target for us to aim at.
  • Things just feel faster, especially big JavaScript-heavy things like Gmail and Facebook. That’s subjective, so as an engineer I feel a bit funny touting it, but that’s what early users are saying, anyway. :-]
  • Cool demos and games work great now. You can play a good game of Super Mario Bros in JavaScript now. Or play some Gameboy. Or try a fluid simulator.

Keep in mind that these are only preview builds, and we are not done yet, which means:

  • We should be a little bit faster yet by the time Firefox 4 is released. In particular, we’re still working on making function calls faster, which should speed up pretty much every non-tiny JavaScript program.
  • If you come across something where our speed is not up to scratch, let us know! (For that matter, if you come across something that Jägermonkey works great on, we’d feel good hearing about that too!) We still have time to fix performance issues or add a key optimization or two. Filing a bug is the most convenient way for us (and this link should save you from any need to dig through Bugzilla). But the important thing for us is to find out, so always feel free to just send us an email.

For me, one of the most satisfying parts of this project has been working together as a team. You can just feel it when a team really comes together, each person knowing what their teammates are up to and naturally supporting and depending on each other. Both the Jägermonkey team and the larger JavaScript team really came together this year–it’s been great.

Another cool thing is that we dared to give key pieces of the project to our interns this summer, and they all came through!

The rest of the JavaScript team made our project possible: they kept the lights on in the rest of the JS world, and put together some critical components Jägermonkey needs to work correctly. We got some nice help integrating with the rest of the browser from mrbkap and peterv. The community helped us out, especially with testing, finding performance problems, and, most of all, cheerleading and moral support. I’d especially like to acknowledge the people outside the core JM team who contributed code: platform engineer Brian Hackett, who created many excellent optimizations; Julian Seward, who needs no introduction, and did us a big favor in porting over WebKit’s assembler; Bill McCloskey, who just started but already wrote a JM patch and is optimizing integration with the tracer; and contributor Jan de Mooij, who wrote several optimization patches.

Finally, here’s the Jägermonkey team: from left to right, Andrew Drake, Alan Pierce, Sean Stangl, David Anderson, Luke Wagner, Chris Leary, and Dave Mandelin.