In the last post,
I outlined some of the architectural difficulties bringing
matplotlib's interactivity to the browser. In short, there's a big
chunk of code that lies between building the tree of artists and
rendering them to the screen that needs to run either in the Python
interpreter, as it does now, or inside of the web browser to support
interactive web applications. It would be great to avoid having two
code bases, one in Python and one in Javascript, that would need to be
kept in sync. Writing code for both contexts from a single code base
may turn out to be a pipe dream, but bear with me as I explore tools
that might help.

Tools

There are a few interesting projects that help bridge the gap between
Python and Javascript.

PyJs

PyJs (formerly called Pyjamas) is a
Python-to-Javascript converter. It also includes an environment much
like Google Web Toolkits for developing rich client-side applications
in Python, but those features are probably not useful here.

Skulpt

Skulpt is a Python interpreter written in
Javascript. It can compile and run Python code entirely within the
web browser. In terms of language features, it doesn't seem as mature
as PyJs, but the fact that it has no dependencies other than a couple
of Javascript files may be an advantage in terms of deployment. An
obvious shortcoming of both Skulpt and PyJs is the lack of support for
Numpy -- none of the existing matplotlib Python code, which depends so
heavily on Numpy, would work in that context.

PyV8

Unlike the other two, which allow Python to run in the browser, PyV8 allows Javascript to run inside of
the Python interpreter. It is a wrapper around Google's open source
V8 Javascript engine and allows sharing objects between Python and
Javascript somewhat transparently. If the drawing code were to be
rewritten in Javascript, it could then, theoretically, be used both
from Python on the desktop and inside the web browser.

Playing around

As a first pass playing with these tools, I've created a new project
on github py-js-blending-experiments. I've
started by writing a very simple benchmark that does a simple 2D
affine transformation, in pure Python, Python with Numpy, Javascript
and C. This test, while a real-world bottleneck from the real-world
matplotlib, is probably too simple to read too much into the results.
A real test would involve classes with complex interactions between
them, to show how the same flexible system of transformations,
tickers, formatters etc. would work, and would take into account the
penalty of stepping over the gap between Python and Javascript. But
all that will have to wait for a future blog post.

The benchmarks

The benchmarks compare a number of different possible approaches.

Pure Python: This is just a simple pure Python implementation.
transform.py

Results

The following results are on a quad-core Intel Core i5-2520M CPU @
2.50GHz running Fedora Linux 17. Python 2.7.3, Numpy 1.6.1, Google
Chrome 21.0.1180.57 beta and Firefox 14.0.1 were used. The benchmark
is performing a 2D affine transformation on 128,000 points. Note that
the timings in the web browser are quite variable. I've included the
average and independent results of 5 runs.

Conclusion

So what can we conclude? Remember what I said about not reading too
much into these results? Well, I'm going to do it anyway with an
enormous caveat.

There is considerable overhead when trying to shoehorn Python into the
browser (comparing Skulpt and PyJs to Pure Javascript). I personally
am surprised by how much more successful the Python interpreter
approach is vs. the Python to Javascript conversion approach, though
that may be due to the relative incompleteness of Skulpt. (EDIT:
Though the Firefox results tell the opposite story). It's pretty
clear where the overhead of PyJs comes from. The line:

You can see how basic numeric operators in Python don't translate
directly to those in Javascript, so it's forced to do something a
whole lot more dynamic, including typechecking within every loop
iteration. I pity the fool Javascript engine that tries to optimize
that.

Not surprisingly, the PyV8 engine performs comparably to the V8 engine
embedded in Google Chrome, which also beats pure Python by at least a
factor of 2. We could do rather well implementing this core in
Javascript.

Numpy and C extensions, of course, beat everything handily for this
very numerically-biased benchmark.

Where does that leave us? Who knows... Interesting ride, though.
Stay tuned and leave comments... There's more to hack away at.