5 ms·
Since I replied in that thread, here's an update. A year's subsequent experience has diluted my enthusiasm, though not too much (say by 20%). JS is an easy lang
by gruseom 16y ago
Since I replied in that thread, here's an update. A year's subsequent experience has diluted my enthusiasm, though not too much (say by 20%). JS is an easy language to generate because it's so flexible. Some of its most loosey-goosey weirdnesses (like the arguments pseudo-array) turn out to work really well for representing other languages' constructs (such as, say, named args). The big downside is if you're trying to do anything computationally intensive. To the extent that you want code to do anything numeric or binary, you're in trouble - forced to work at too high and too kludgey a level. Of course JS wasn't designed for anything like this and the fact that we're even talking about it in this context is a testament to fantastic technical and not just market success.
A couple side notes...
Actionscript is the inverse case, an abominable language that manages to wreak incredible damage on something pretty good (ECMAScript) in surprisingly few steps -- mainly, as far as I can tell, by trying to turn into something "proper" a.k.a Java, a fate that JS itself was fortunately forced to avoid -- but it provides access to one lower level than JS does, and this is a big deal for some kinds of programs. We're probably going to use Flash (when available) as a computational accelerator for this reason.
Second, our results suggest that the real gamechanger here is V8. I know that most of the benchmarks out there show Tamarin and other VMs somewhat competitive with V8. Not in our world. I'm talking a couple of orders of magnitude difference. It's astonishing. If everyone would just use Chrome, we would have no performance problems at all.
- acqq 16y ago> an abominable language that manages to wreak incredible damage on something pretty good (ECMAScript) in surprisingly few steps Can you please give some specific examples? I'm curious. I think you mention yourself that you can get faster execution with it, so that's the positive side. What's the damage?
- gruseom 16y agoIt's all the little things they screw up by trying to turn JS into Java. It seems like that's the way to 'improve' the language (add 'proper' classes, 'proper' typing). But the result is a mishmash. They've added stucco to an oil painting. Sorry for the lack of specific examples, but my way of dealing with the incessant irritations is to deliberately forget them. Even the performance is misleading. It comes from one thing, the static typing, and having played that card there doesn't seem to be anywhere else for them to go. AVM2 bytecode is very interesting; if you try to optimize it you get counterintuitive results: it either stays the same or gets slower. (The one exception is the fast memory opcodes that were added for the abortive Alchemy project, but that's another story.) The proper point of comparison is V8. Adobe had an eternity of a head start. They just bet on the wrong horse. Had they understood the problem more deeply they could have grabbed the V8 guys before Google even thought about it. In that case their head start might have turned into total dominance of the browser runtime. The biggest advantage Flash has -- 95%+ market penetration -- is one of the most valuable assets on the internet. (Is any single asset more valuable? I mean executables, as in IE counts but google.com doesn't.) Imagine if Adobe had done V8 before Chrome existed. The few users who didn't have Flash would have had to install it just to make web apps usable. People might not have bothered for a 2x speedup, but a 1000x speedup? I think so. Edit: to be clear, I'm not talking about (heaven forbid) Flash apps. I'm saying that Flash could have become the standard runtime for web apps. They were on the VM performance track years before anyone else. But it's easy to see that they weren't thinking about this at all, because the facilities for communicating between Flash and the browser are unbelievably poor. (They actually marshal all calls into XML messages! Grrrrrrraaaaaaagh.)
- acqq 16y ago> Sorry for the lack of specific examples, but my way of dealing with the incessant irritations is to deliberately forget them. Pity, as the rest of us then can't learn anything without the examples of the errors. > I'm not talking about (heaven forbid) Flash apps. I'm saying that Flash could have become the standard runtime for web apps. And how were they supposed to reach that when having only Flash which runs as it runs? How were they to make a whole browser that would be widely accepted? What do you think they should have done actually?
- gruseom 16y agoWhat do you think they should have done actually? What I said: make the fastest JS VM in the world years before others got started and make it cheap to call into from the browser. Then web apps could have used Flash's JS if it were available and just run more slowly if it weren't. Since V8 runs far faster than AS3 (in any measurement I've done), this was obviously technically possible. Had Adobe done this, Flash's extraordinary ubiquity would have meant we had access to something like V8 in nearly every browser out there, right down to IE6. Instead, what they produced was a dead end -- faster than the old JS implementations but not as fast as the new ones -- and a monstrosity called ExternalInterface that makes interaction between JS and AVM2 too slow for all but the most expensive computations.
- acqq 16y ago> make the fastest JS VM > ExternalInterface that makes interaction between JS and AVM2 So how were they to have a JS VM without the overheads but not making a full browser? Note that Google doesn't manage that either, they just have the thing that inserts the whole Chrome window in the IE frame. (The examples or specifics for each your claim are still missing).
- gruseom 16y agoThey could have started by not translating every single ExternalInterface call into XML and then back again. However, this is a useless argument: my thoughts are just a silly thought experiment and you're just being adversarial. Tell you what, have a free point on me.
- BrendanEich 16y agoI gave a concrete example in a comment on jwz's blog, referencing my blog for the 2007 @media ajax talk I gave, showing how AS3's type annotations can slow things down. If you have a loop and annotate the loop control variable as int, but it flows into expressions that evaluate arithmetic, then per the unchanged-from-JS rules, you get IEEE754 double evaluation. This means widening not wraparound on overflow. It is non-trivial to optimize to remain in the ALU. But the int storage type means stores have to be narrowed correctly from double to int. Not annotating the loop control variable lets two things happen: 1) everything on the FPU, which if SSE has a lot of bandwidth in parallel to the integer units, which can still handle addressing and known-int chores; 2) tracing JITs can speculate, and type inferencing JITs can infer, that the loop control fits in an int, and all evaluation and storage can use int domain.
- acqq 16y agoYes, once you have type inferencing, starting from "just a number" is more convenient and forcing everywhere, needed or not, the bigger number back to int is certainly problematic. Moreover the fastest conversion (on a typical hardware) of IEEE numbers to ints is not truncation but rounding. Excuse me for not knowing that but does JavaScript today manage not to truncate at the places (if they exist) where rounding would be acceptable?
- BrendanEich 16y agoI wish! Converting from double to int32 or uint32 in JS is far from a simple truncate or round, although it entails floor. From ECMA-262 5th Edition: 9.5 ToInt32: (Signed 32 Bit Integer) The abstract operation ToInt32 converts its argument to one of 2^32 integer values in the range −2^31 through 2^31−1, inclusive. This abstract operation functions as follows: 1. Let number be the result of calling ToNumber on the input argument. 2. If number is NaN, +0, −0, +∞, or −∞, return +0. 3. Let posInt be sign(number) * floor(abs(number)). 4. Let int32bit be posInt modulo 2^32; that is, a finite integer value k of Number type with positive sign and less than 2^32 in magnitude such that the mathematical difference of posInt and k is mathematically an integer multiple of 2^32. 5. If int32bit is greater than or equal to 2^31, return int32bit − 2^32, otherwise return int32bit. NOTE Given the above definition of ToInt32: • The ToInt32 abstract operation is idempotent: if applied to a result that it produced, the second application leaves that value unchanged. • ToInt32(ToUint32(x)) is equal to ToInt32(x) for all values of x. (It is to preserve this latter property that +∞ and −∞ are mapped to +0.) • ToInt32 maps −0 to +0. --- end snip --- Note that this path is rare in code that does not use shift or bitwise-logical operators or certain built-in functions. See https://bugzilla.mozilla.org/show_bug.cgi?id=597814 https://bugzilla.mozilla.org/show_bug.cgi?id=597814.