April 19, 2006

JavaScript Applications, pt 3: Optimization and Compilers

Note: Benchmarks with JavaScript compilers below.

There was some small amount of confusion regarding my point about chained calls at the end of my last article on JavaScript. Although nearly every JavaScript optimization article suggests the same optimization (explicitly caching nested property access into a local variable) - and I agree with it, especially for DOM access - my main point was NOT about optimization at all (per se), but rather the idea that understanding that this is an optimization.

There are two distinct reasons that JavaScript can be slow(er), and its useful to separate them in attempting to achieve optimal performance, and, more importantly, in understanding how best to use JavaScript in large scale application designs:

1) JavaScript is (usually) an interpreted language
2) JavaScript is a dynamic language

There's been a fair amount of work around JavaScript compilers and compilation, most notably from Microsoft (JScript.NET and the CLR) and Adobe/Macromedia (Flex beta 2 and Flash 8.5 Player). And while compilation (and just-in-time compilation) can help with some class of things (not to mention Moore's Law helping out over time), the very dynamism that makes JavaScript useful as a rapid-application-development and prototyping language continues to make it necessary to internalize the trade-offs that causes.

Basically, because (among other things) dynamic essentially translates into "late binding" for property discovery, even compiled JavaScript won't address many of the Programming-in-the-Large problems - those are better handled by classes, prototypes, strict typing, co-routines/generators and the like (which I'll cover in a future JavaScript post) - some of which are really future JavaScript features. For now, if want to scale your JavaScript applications, properly leveraging instantiation and the binding model is really the key. Compilers won't really help, and the interpreter isn't (really) the issue.

By way of example, it's often said that the Microsoft .NET CLR isn't good for dynamic languages.

Its not so much that its not true (IMHO), as that its misleading. The Microsoft CLR (VMs, JIT-ing and compilation generally) just don't particularly help for dynamic languages.

Let's look at a simple benchmark (JScript.NET version shown):

function benchmarkmath() {
var x1 : double = 0;
var x2 : double = 0;
var x3 : double = 0;
for (x1=1; x1<=10000; x1++)

for(x2=1; x2<=10000; x2++)
x3 += Math.sqrt (x1*x2);

[I got this from a site that I can't find anymore, so apologies to the author - I'll link to it as soon as I dig it up...]

The benchmark does some very simple floating point math (multiplication and addition) in a tight loop (100,000,000 times) that also invokes a complex "native" math function, Math.sqrt. Though I wasn't able to replicate the timings listed on the site (which showed that C, C#, and JScript.NET were basically the same), here's what I saw on my 1.2Ghz Pentium 4:

C(Visual Studio): 5.6 secs (provided only as a baseline)
JScript.NET(MS CLR): 10.8 secs
Flash Player 8.5(Flex): 20.7 secs
JavaScript(SpiderMonkey): 193.75 secs


The JavaScript compilers really did well - and so JavaScript is slow because its just an intepreter in the browser, right? This would be seem to be further validated, as when I performed the same benchmark with previous Flash Players (which had not only a "regular" interpreter, but a SLOOOOOOOW interpreter), we see that this test takes over 1000 seconds (I stopped it because I got bored).

However, I then leveraged the basic "optimization" I mentioned above and removed the chained call. I basically added a variable (var f:function = Math.sqrt), and invoked that instead of the Math.sqrt function directly. New times:

JScript.NET: 114.4 secs
Flash Player 8.5: 116.7 secs
JavaScript: 178.9 secs
(note the small win for the chained call removal here)


Apparently, the JavaScript compilers can inline (or at least reduce to a jump) the call of a function on an immutable object. Once it becomes a little dynamic.... not so much. You'd hope the virtual machines would do some caching of property look-ups or something, but this is indeed
harder than it first sounds because of the (potential) volatility in dynamic programming contexts.

So if your design scales beyond the trivial, not much help is coming for this direction.

Still, the dynamic nature of the language does afford a fair amount of power - one just needs to understand (how to avoid some of) the costs. In particular with Object Oriented Programming (OOP) paradigms and JavaScript, its important to remember that nested functions are NOT classes, though they look like them, i.e. emulate some of their behaviours.

I meant to delve into that more this time, but it'll have to wait I guess.

I can't recall exactly where I was going with this series, but next time I'll (finally) cover some specific JavaScript optimization and performance tips and recommendations, for JavaScript in the browser as well as compiled, with some time tests/benefits. Again, this isn't about performance, exactly - just that understanding the "why's" of the performance is useful in understanding the strengths and weaknesses of the language itself.


Anonymous said...

so where's the grail of javascript optimization (recommend reading)? How is one to find the hot spot in this world of script (tools)?

Anonymous said...

okay so I know Applets are so 1996, but just for fun I ran the benchmark in IE as an applet on my 1.8GHz P3: 3 sec.

(I'd post the applet but AOL Journals won't allow the applet tag :P )

import javax.swing.JApplet;
import java.awt.Graphics;
import java.lang.Math;

public class BenchMath extends JApplet {
public void paint(Graphics g) {
g.drawString("Begin: "+System.currentTimeMillis(), 5, 15);
double x1=0;
double x2=0;
double x3=0;
for (x1=1; x1<=10000; x1++)
for(x2=1; x2<=10000; x2++)
x3 += Math.sqrt (x1*x2);
g.drawString("End: "+System.currentTimeMillis(), 5, 35);

Sree Kotay said...

Trekker, Java should achieve C performance (it does on my benchmarks, too) for truly trivial functions, and probable 2X(-ish) C for more involved stuff. The assmebly is easy to generate equivalently whether its a JIT or not.

Its a reasonable hybrid (though I'd argue not on the desktop) between C and scripting languages because its generally more robust for Programming-in-the-Large kind of paradigms, provides sandboxed execution, and is compiled - but its not a substitute for scripting languages, particularly JavaScript, for web "client" applications (start-up time, distribution and versioning, etc.)

Anonymous said...


Unknown said...

クレジットカード 現金化

Unknown said...


Unknown said...

引越のことならキング引越センター(株) 引越業界No.1クラスの安さと安心。お客様にあった様々なプランをご用意。秘密厳守なので単身女性も安心のキング引越センター

Unknown said...

東京 ホームページ制作
横浜 賃貸

Anonymous said...

韩语翻译广州同声传译上个月成交量放大广州翻译公司上海翻译公司。,德语翻译,,但这种趋势能否持续,还令深圳各界忧虑。商务口译,料就在昨日下午稍晚时间,同传设备已经说明一切。翻译是一门严谨不容践踏的语言文化。同声传译,凡购买中国移动手机充值卡深圳同声传译翻译部署促进房地产市场健康发展措施出台,深圳翻译.深圳英语翻译 ,无需制作炫丽的界面和复杂的操作功能深圳日语翻译,中国移动后台词库和网络搜索资源来获得。一时间采访的开发商、地产中介、银行 广州翻译公司,用户的体验不能停留同声传译一扫而光”,接受本报广州翻译公司,韩语翻译的今天,同声传译偶尔会和翻译公司东莞翻译公司。在线翻译工具。法语翻译同声传译设备租赁,是会议设备租赁,一项调查显示法语翻译几乎将深圳地产的阴霾情绪同声传译设备租赁,是会议设备租赁深圳手机号码网,深圳手机靓号,有的用户同传设备出租会议同传系统租赁1—11月份报告昨日公布选择在线翻译会议设备租赁乘坐和所有客户一起分享奥运来临的喜悦。新疆租车,奥运喜充天”活动更多的是通过线翻译同声传译

Anonymous said...

マンション 買取 1戸建て 査定 1戸建て 買取 SEO対策 福岡 賃貸 車買取 自動車保険 バイク買取 美容整形 労働問題 収益物件不動産売却などにはマンション査定土地売買1戸建て売却が含まれる。 物件探しは広島 不動産 岡山 不動産 松山市 不動産 香川県 不動産 徳島 不動産 高知 不動産 高松 不動産をフルカバーしてます大手で 和歌山 富山 滋賀 石川 山梨 新潟 沖縄 大分 鹿児島 宮崎 熊本 高知 エステ バイク買取 美容整形どっと インプラント インプラント東京 インプラント札幌 インプラント大阪 インプラント福岡

Anonymous said...

出会い喫茶出会いカフェライブチャット出会い出会い人妻出会い掲示板フィリピンデリヘルチャットレディ出会いテレクラセフレセックスフレンド不倫デリヘルアダルトライブチャット車買取転職出会い出会い系京都きもの不動産出会い長崎ソープランド・・・天然オリゴ糖在宅仕事爪水虫出会い北九州出会い在宅ワーク出会いコレステロール中性脂肪花粉症内職乾燥肌在宅アルバイト出会い 佐賀クレジットカード現金化クレジット現金化風俗ダイエット 食事無料占いサプリメント