Conclusion

By Jeff Cogswell |
Posted 2008-09-17

Google Chrome JavaScript Is Powered with a V8 Engine

When JavaScript was first invented, I don't think anybody imagined just what
we would be doing with it today. In fact, a lot of people today might not
realize how much it's being used behind the scenes of all the modern Web 2.0
applications.

Right now, JavaScript is virtually the only language that can be used in a
client-side browser-based application. Sure, there's always VBScript if you
want to limit which browsers can run your application. And there are many other
languages if you want to require visitors of your Web site to download an
add-on to provide support for that language. But if you want to write an
application for the most browsers with the least amount of headache for your
users, you're pretty much stuck with JavaScript on the client end. (The server
end is wide open in terms of language and platform choices, of course.)

Originally, JavaScript was just used to add fancy little animations
(like graphics falling down the screen like rain) and other such annoyances to
Web pages. But today JavaScript is being used for serious work. For example, on
Facebook you can send an e-mail message within a single DIV element that opens
up, allowing you to type in the message, send it and update the thread of
messages on the page, all without leaving the page. And that's all done through
JavaScript.

But the problem Web developers are hitting is that JavaScript is a slow,
interpreted language. While today's computers are able to move along pretty
quickly and the sites do function reasonably well, we are nevertheless limited
as to how our sites can perform. And soon we're going to hit a brick wall if
something isn't done to help make JavaScript run better.

There are several solutions to this problem. One approach that has worked
well with scripting languages in the past is JIT (Just-in-Time) compilation.
Here, code is compiled to native machine code as needed. This approach only
works well with routines that are called over and over. If you're calling a
routine just once-one that doesn't have many for loops-it's often faster to
just interpret it rather than first compile it and then run it. The compilation
can take longer than just running the interpreted form. But if you have a
routine that's called over and over, compiling it the first time and then
running the compiled form can make a big difference.

Language developers have taken the JIT concept and mixed it with other
concepts such as various types of optimization to significantly speed up
languages. The newest Firefox version that is still in development, for
example, includes a JIT and optimization compiler for JavaScript, allowing it
to run much more quickly. That is certainly good news. (And, interestingly, the
original designer of JavaScript, Brendan Eich, is the CTO
of Mozilla, which makes Firefox. So, needless to say, I suspect we will see
some serious advances from Firefox in the JavaScript world.)

Google, however, has taken a slightly different approach to making
JavaScript run faster. Google does indeed compile it, but the approach is
different from a typical JIT solution. Let's see what Google is doing.

The Problem with Compiling JavaScript

The Problem with Compiling JavaScript and Other Dynamic Languages

If you've programmed in C++, you're well aware that before you can access a
class, you need to have the class fully defined. Typically you'll put your
class definition in a header file. This definition includes the word "class," the name of the class,
and a list of all the member variables and member functions. Later in your code
you can create objects that are instances of the class.

The class is much like
a cookie cutter for objects. Once the program is running and you create an
object, the object has the members it will have until it is destroyed. You can
change the value of the members (such as changing the height member of a Rectangle object from 10 to 20 or changing the balance member of the
CheckingAccount object from 100 to 100,000,000) but you can't add or remove
members. While your program is running, you can't add a depth member to your
Rectangle class. The only way you can make changes is by changing the code and
recompiling. But then when you run the program, all your Rectangle objects will
have the new member.

JavaScript, however, is a dynamic language, and the whole concept of classes
changes drastically. You can add and remove members of an object while the
program is running. Thus, you can have two Rectangle objects, for example, and
then add a depth member to just one of those objects.

In fact, although it's not necessarily the best programming practice, you
can even provide the user of your program with a text box where he or she can
type in a name, and then you can add a member to an object by that name. Thus,
your user could suggest the name eWEEK for a member, and you could add that
member to the object and give it a value.

And further, that value can be any type you want-again something totally
different from C++. In C++, if you have a Rectangle class with members Height
and Width and you specify that they are to hold integers, then you can't store
a string in one of these members while the program is running. In fact, the
compiler will catch it and stop you while you're compiling before you're even
able to run the program.

But not so with JavaScript: You can store the number 10 in your eWEEK
member, or you can store the string "Awesome Publication" in the
member.

As you can probably imagine, this makes for some serious problems with
compilation. Microsoft, for example, hit these snags when trying to add dynamic
languages to the list of languages that can be compiled under the .NET
run-time. Microsoft's CLR (Common Language Runtime) is strongly typed and not
dynamic, making languages such as JavaScript and Python difficult to compile.
Microsoft now has support (primarily in its Silverlight product) for dynamic
languages, but to do so it had to add an entire dynamic language layer on top
of the run-time.

(And incidentally, just to make life even more interesting, almost anything
in JavaScript can be treated as an object and have members assigned to it at
run-time, including even functions.)

Google has taken a unique approach to compiling JavaScript. It's implemented
something known as hidden classes.

Googles Solution: Hidden Classes

Hidden Classes in V8

Google drew on its team members' expertise with earlier compiled, dynamic
languages, such as an experimental language called Self (created when the team
members worked at Sun Microsystems). To a programmer like myself, the concept
at first sounds horrible. When I first read about it I was shocked that they
would do something so seemingly inefficient. But in fact, it works beautifully.

Here's how it works. In JavaScript, objects are initially created with no
members. You could create two new objects and neither will have any members.
Then your code can add members. You might have a line of code that creates an
object; then the next line adds on a new member called Width; then the next
line adds a member called Height.

During this time, your object went through three stages: First it had no
members, then it had only one member, then it had two members.

Now, typically such member-adding code will take place in a constructor
function. This is a special named function in JavaScript that runs when you
create a new object. The function gets a name, and that name is in turn used
for the class of the object. Thus, you might have a function called Rectangle.
Its code will have a line to add a Width member, and then a line to add a
Height member. And this is where the V8 smarts of Google Chrome come in.

While compiling the code, V8 will create in the background a compiled class
(just like you have in C++ at run-time) that contains no members. Then as the
compiler discovers the line of code that adds a Width member, the compiler will
create a second class, this one with the Width member. Then as the
compiler encounters the next line, it will create a third class, this
one with the Width and Height members.

That's right, it creates three classes. But the compiler is smart, because
later on in your code, when you create several instances of your Rectangle
class, the compiler will know to use the third class.

Of course, that's sort of a simple example. In fact, you might add the eWEEK
member to one of your objects outside of the constructor. In that case, the
compiler will create a fourth class, this one including the eWEEK member.

In other words, you might have multiple instances of Rectangle, and behind
the scenes several of them may share the third class, while others might have
their own separate class. These are called hidden classes.

And, of course, the rest of your code is compiled to machine code; the
compiler doesn't just make a bunch of classes. That's where the efficiency
actually comes in. The idea of generating all these classes is only a minor
tradeoff in the long run, because ultimately your code is running as native
machine code and is far, far faster than traditional, interpreted JavaScript.

Taking Out the Garbage

Collecting the Garbage

One of the huge problems with languages like JavaScript is garbage
collection. Garbage collection just refers to the problem of using memory and
being done with the memory but the computer not being able to reuse the memory
because it doesn't know if you still need it. Got that?

If not, here's how it works: Suppose I create a Rectangle object. I use that
in a calculation. Then I'm done with the object. In a language like C++, you
write a line of code that tells the run-time library that you're done with the
object. The run-time library will then delete the object and allow the part of
memory where the object was stored to be used again for other objects.

But in languages like JavaScript, you don't explicitly tell the run-time
you're done with the object. The run-time does, however, have ways of figuring
out that you're done with the object. Typically, if a function creates an object,
when the function is finished the object can be cleaned up too. But not always:
The function might pass the object on to three more functions to use, for
example, and only after the run-time system figures out that all four
functions-the original and the three others-are finished can it figure out that
the object isn't needed anymore and free the memory.

But the problem is the
object might get saved away as a member within yet another object. Then the run-time
can't delete the first object until this other object is no longer needed! Can
you say, big mess? Yes, there is more than one reason it's called
"garbage collection," and I'm sure some people would like to include
other choice words instead of garbage, as well as directives about other people
cleaning up their own, uh, messes.

Garbage collection is always a problem with languages, because often the
actual garbage collector (the code that does the cleaning) only runs
occasionally, and when it does, the program slows waaaaaaay down.

Google describes in its developer documentation a sophisticated garbage
collector that Chrome uses. This collector stops everything and does its job
very quickly while only collecting what's necessary, and then allowing everything
else to resume. Personally, that sounds suspicious to me; however, I can
understand how that could be better than having the garbage collector slowly
churn away for minutes on end while you're continuing to do your work, albeit
slowly, due to the garbage collector slowing everything down-and, with the work
you're doing slowing the garbage collector down, causing it to run even longer.
So perhaps this new method is better.

Conclusion

Conclusion

I have a couple of Web sites I use regularly, including one for checking my
personal e-mail via a Web interface. This particular interface is really nice,
but it's always been horribly slow. For that reason, I only use it when
necessary.

I tried it using Chrome and was impressed. The first time the Compose box
opened, it was a little sluggish as all those formatting buttons slowly drew.
But the next time I ran it, it opened instantly, and definitely felt like I was
using a desktop (in other words, non-Web) application. Now this, of course, is
just anecdotal and not a benchmark test. But it was fast.

But is Chrome's V8 faster than the latest development
build of Firefox? And is it faster than anything Microsoft might secretly be
doing? (I'm bettin' that Microsoft is working on its own native compilers,
although I don't know for sure.)

So far, the jury is out. I've seen pages
"proving" through benchmarks that V8 is faster than Firefox's new
engine. But I've also seen pages "proving" that Firefox's engine is
faster. It's hard to say. One thing is for sure: They're both fast, and
they both fly. And that's great news for us developers, and even better news
for the users across the planet fighting with these slow Web 2.0 applications.

Jeff Cogswell is the author of Designing Highly Useable Software. Currently Jeff is a senior editor with Ziff Davis Enterprise. Prior to joining Ziff, he spent about 15 years as a software engineer, working on Windows and Unix systems, mastering C++, PHP, and ASP.NET development. He has written over a dozen books.