I have recently been working on a small to medium sized game in JavaScript to familiarize myself with it and come from a background in C and Java. In my game I am using a few constant numbers to render all of my objects and I was wondering about the performance impact those would have. Both C and Java are languages with compilers that will automatically simplify simple statements such as 2 + 3 into 5 before the code is actually run. This is great because it means I can make my code more readable by having something like WINDOW_MAX_Y - SHIP_Y in my code and understand what it does later. Looking over my code recently however, I found a few lines of code that become very long when written in this style, and because JavaScript does not have a compiler I was wondering whether it would improve performance if I simplified everything into "magic numbers" or if JavaScript had some function that would automatically simplify the lines before execution like the C compiler. I would like to keep my code readable, however, if JavaScript does not simplify those statements I would love to know as they are run thousands of times per second.
Not necessarily before execution but when the interpreter detects that the code is being used heavily.
You mention Java and this is good because I think you may be familiar with the concept since Java was one of the first languages to implement it. It's called just-in-time compilation (or JIT for short).
There is no standard that covers how JIT is to be implemented in Javascript. And there is no standard that mandates that a javascript interpreter must implement JIT (this is exactly the same for Java by the way, it is perfectly legal to implement a JVM that does not implement a JIT compiler). However, market forces have ensured that all current major javascript interpreters have implemented JIT (which may seem bit odd since all major javascript interpreters are free but they are competing for market share, not profit).
Similarly you mentioned C, which is nice because it also means you should be familiar with another concept. In C there is no standard defining how a = 1 + 2 should be compiled to. There is a concept in the C standard that specifies the behaviour of such optimisations though: the as-if rule. It basically states that if a complier was to implement optimisations, the end result must be exactly the same as if there was no optimisation.
All major javascript interpreters currently have most of the common optimisations that compilers typically have. They are all slightly different (just as all C compilers are slightly different) but they all compile code just-in-time. In addition, most interpreters also perform optimisations during compilation to byte code.
Yes, there is byte code, just like Java. While there is no compilation step performed by the programmer, all current javascript interpreters compile to bytecode before execution just like Java. This is true for all modern "scripting" languages such as Python and Ruby.
My advice is basically if you don't worry about such things in C or Java then you should not need to worry about it in javascript. For things that you need to worry about in C (such as micro-optimisations) there is a subset of javascript called asm.js that is guaranteed to be compiled down to machine code instead of bytecode (if set up correctly).
Related
While searching about the difference, I came across these definitions:
Compiling is the general term for taking source code written in one language and transforming into another.
Transpiling is a specific term for taking source code written in one language and transforming into another language that has a similar level of abstraction.
I understand what Abstraction is.
But what does "similar level of abstraction" mean in the above definition? And how do we find the level of abstraction in a language?
The definition you have quoted above is too general for a beginner to understand completely and so let me just simplify it to something we see practically.
Compiler: is an umbrella term to describe a program that takes source code written in one language and produce a (or many) output file in some other language.
In practice we mostly use this term to describe a compiler such as gcc which takes in C code as input and produces a binary executable (machine code) as output.
Transpilers are also known as source-to-source compilers. So in essence they are a subset of compilers which take in a source code file and convert it to another source code file in some other language or a different version of the same language. The ouput is generally understandable by a human. This output still has to go through a compiler or interpreter to be able to run on the machine.
Some examples of transpilers:
Emscripten: Transpiles C/C++ to JavaScript
Babel: Transpiles ES6+ code to ES5 (ES6 and ES5 are different versions or generations of the JavaScript language)
Now, what do they mean by "similar level of abstraction":
As I said it compiles/transpiles to a source file, one can argue that assembly language is also a source file and thus gcc is also a transpiler. So, this argument is what this similar level of abstraction voids.
The notion of categorizing languages into lower, middle and higher level is based on the level of abstraction they provide from the actual working of the machine/architecture.
Lower level languages like assembly are very close to the processor architecture i.e. have different instructions for different processors. While C/C++/Java/JavaScript, abstract all this away providing more abstraction.
So, a transpiler compiles to a language that is closer to the language you started with in the terms of this abstraction (or is closer to the level of that language in the lower-middle-higher level language ladder).
Here's a sort of descriptive way to answer
If you think of layers of abstraction as this example:
(1) CPU-level (actual logic gates on the CPU)
(2)machine code
(3)assembly code
(4)[C/C++, JVM/bytecode]
(5)[JavaScript, Python]
A compiler goes to a lower level (lower number). A transpiler switches from one language (or version of a language) to another at the same number.
Ex: TypeScript ( a Microsoft superset of JavaScript with type safe checking) transpiles to JavaScript code which can run on different types of browsers.
https://en.wikipedia.org/wiki/Microsoft_TypeScript
"Microsoft TypeScript is an open-source programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript, and adds optional static typing to the language.
TypeScript is designed for development of large applications and transcompiles to JavaScript.[5] As TypeScript is a superset of JavaScript, existing JavaScript programs are also valid TypeScript programs. TypeScript may be used to develop JavaScript applications for both client-side and server-side (Node.js) execution."
I mostly agree with tapananand answer, but...
definition
Words are "made", so they serve a purpose. And this also changes with time.
We now tend to use transpiler to specify a compiler that translates code into some other code "more similar" to the source one, that what a compiler might do. And is used to differentiate both mostly when both of them are mentioned in the same context (again mostly implying that a transpile language will have to get compiled at least once more)
examples
So everything is very subjective. At the time of this writing:
Coming from the Java world I could call CoffeeScript/TypeScript transpilers to depict that the resulting code is no more efficient than the original one.
CoffeScript documentation says it's a compiler, and babel is a transpiler. The want do say that CoffeeScript, although very similar, is not Javascript. At least not a version of it, as that is what babel produces.
Babel calls itself a compiler.
fazit
So transpile is at this time very rarely used anymore, and only to tell two compilers apart.
It will probably dissapear as concept, since compilation is much more complicated than that (same/higher/lower language, version, etc), and the word doesn't seem to be useful anymore ("transpilers" are now ubiquitous)
Meaning of "similar level of abstraction"
Higher level languages are more abstracted than lower level languages. By abstracted I mean easier to understand.
Higher level language(highly abstracted)---- Similar level -----> Higher level Another language(highly abstracted)
(TypeScript Source code to JavaScript Source code)
Mid level language(poorly abstracted) ---- Similar level-----> Mid level language(poorly abstracted)
Higher level language(highly abstracted) ---- Not Similar level of abstraction -----> Mid level Another language(poorly abstracted)
Computers only understand 1s and 0s: You can think of computer as being a box, crammed full of switches - kinda like a light switch: they can either be "on" or "off" - they can either be a "1" or a "0". You can instruct a computer which switches you want on or off, with a series of "1s" and "0s".
People need programming languages: Human beings are not very good at reading/understanding hundreds of thousands of lines of "1s" and "0s"........ but we can be trained to understand human words: like: class and break.
Programming languages allow us to write computer instructions, which can be translated into 1s and 0s (compiling), or which can be translated into other programming languages. for example: if you have elm code, you can easily transform that into javascript (transpiling).
The word "preprocessor" often used as synonym for "transpiler".
The word "preprocessor" was already well-known in the 90th and emphasises that something is processed before something else. It is also used in a context of removing comments before code is compiled.
The word "transpiler" became more popular in the 2010th (I heared it first 2015 from a colleague with contact to AngularJS community), calling the process of bringing TypeScript to JavaScript as "transpiling" - as some kind of translation that is like a compilation (checking data-types etc.).
To sum it up:
"Transpilation" fits best when something is translated with some compilation-like functionalities.
"Preprocessor" is a more generic term where basically something is processed before.
Compilers are used to compile source code written in one language to another. A compiler will often use the same syntax as the input language, but it may also be designed for some other type of input, like bytecode.
Transpilers are different because they translate code from one programming language to another. The original program may have been written in JavaScript, but the transpiler converts it into HTML.
The other day during a tech interview, one of the question asked was "how can you optimize Javascript code"?
To my own surprise, he told me that while loops were usually faster than for loops.
Is that even true? And if yes, why is that?
You should have countered that a negative while loop would be even faster! See: JavaScript loop performance - Why is to decrement the iterator toward 0 faster than incrementing.
In while versus for, these two sources document the speed phenomenon pretty well by running various loops in different browsers and comparing the results in milliseconds:
https://blogs.oracle.com/greimer/entry/best_way_to_code_a and:
http://www.stoimen.com/blog/2012/01/24/javascript-performance-for-vs-while/.
Conceptually, a for loop is basically a packaged while loop that is specifically geared towards incrementing or decrementing (progressing over the logic according to some order or some length). For example,
for (let k = 0; k < 20; ++k) {…}
can be sped up by making it a negative while loop:
var k = 20;
while (--k) {…}
and as you can see from the measurements in the links above, the time saved really does add up for very large numbers.
While this is a great answer in minute detection of speed and efficiency I'd have to digress to #Pointy original statement.
The right answer would have been that it's generally pointless to
worry about such minutia, since any effort you put into such
optimizations could be rendered a complete waste by the next checkin
to V8 or SpiderMonkey
Since Javascript is client side determined and was originally having to be coded per browser for full cross-browser compatibility (back before ECMA was even involved it was worse) the speed difference may not even be a logical answer at this point due to the significant optimization and adoption of Javascript on browsers and their compiler engines.
We're not even talking about about non-strict script only writing such as applications in GAS, so while the answers and questions are fun they would most likely be more trivial than useful in real world application.
To expound on this topic you first need to understand where this topic is originally coming from and compiling vs interpreting. Let's take a brief history of the evolution of languages and then jump back to compiling vs interpreting. While not required reading you can just read Compiling vs Interpeting for the quick answer but for in-depth understanding I'd recommend reading through both Compiling vs Interpreting and the Evolution of Programming (showing how they are applied today).
COMPILING VS INTERPRETING
Compiled language coding is a method of programming in which you write your code in a compilable manner that a compiler understands, some of the more recognized languages today are Java, C++ and C#. These languages are written with the intent that a compiler program then translates the code into the machine code or bytecode used by your target machine.
Interpreted code
is code that is processed Just In Time (JIT) at the time of the execution without compiling first, it skips this step and allows for quicker writing, debugging, additions/changes, etc. It also will never store the script's interpretation for future use, it will re-interpret the script each time a method is called. The interpreted code is ran within a defined and intended program runtime environment (for javascript is usually a browser) to which once interpreted by the environment is then output to the desired result. Interpreted scripts are never meant to be stand-alone software and are always looking to plug into a valid runtime environment to be interpreted. This is why a script is not executable. They'll never communicate directly a operating system. If you look at the system processes occurring you'll never see your script being processed, instead you see the program being processed which is processing your script in its runtime environment.
So writing a hello script in Javascript means that the browser interprets the code, defines what hello is and while this occurs the browser is translating this code back down to machine level code saying I have this script and my environment wants to display the word hello so the machine then processes that into a visual representation of your script. It's a constant process, which why you have processors in computers and a constant action of processing occurring on the system. Nothing is ever static, processes are constantly being performed no matter the situation.
Compilers
usually compile the code into a defined bytecode system, or machine code language, that is now a static version of your code. It will not be re-interpreted by the machine unless the source code is recompiled. This is why you will see a runtime error post compilation which a programmer then has to debug in the source and recompile. Interpreter intended scripts (like Javascript or PHP) are simply instructions not compiled before being ran so the source code is easily edited and fixed without the need for additional compiling steps as the compilation is done in real-time.
Not All Compiled Code is Created Equal
An easy way to illustrate this is video game systems. The Playstation vs Xbox. Xbox system are built to support the .net framework to optimize coding and development. C# utilizes this framework in conjunction with a Common Language Runtime in order to compile the code into bytecode. Bytecode is not a strict definition of compiled code, it's a intermediate step placed in the process that allows the writing of code quicker and on a grander scale for programs, that is then interpreted when the code is executed at runtime using, you guessed it, Just In Time (JIT). The difference is this code is only interpreted once, once compiled the program will not re-interpret that code again unless restarted.
Interpreted script languages will never compile the code, so a function in an interpreted script is constantly being re-processed while a compiled bytecode's function is interpreted once and the instructions are stored until the program's runtime is stopped. The benefit is that the bytecode can be ported to another machine's architecture provided you have the necessary resources in place. This is why you have to install .net and possibly updates and frameworks to your system in order for a program to work correctly.
The Playstation does not use a .net framework for its machine. You will need to code in C++, C++ is meant to be compiled and assembled for a particular system architecture. The code will never be interpreted and will need to be exactly correct in order to run. You can never easily move this type language like you could an intermediate language. It's made specifically for that machine's architecture and will never be interpreted otherwise.
So you see even compiled languages are not inherently finalized versions of a compiled language. Compiled languages are meant, in their strict definition, to be compiled fully for use. Interpreted languages are meant to be interpreted by a program but are also the most portable languages in programming due to only needing a program installed that understand the script but they also use the most resources due to constantly being interpreted. Intermediate languages (such as Java and C#) are hybrids of these 2, compiling in part but also requiring outside resources in order to still be functional. Once ran they then compile again, which is a one time interpretation while in runtime.
Evolution of Programming
Machine Code
The lowest form of coding, this code is strictly binary in its representation (I won't get into ternary computation as it's based on theory and practical application for this discussion). Computers understand the natural values, on/off true/false. This is machine level numerical code, which is different from the next level, assembly code.
Assembly Code
The direct next level of code is assembly language. This is the first point in which a language is interpreted to be used by a machine. This code is meant to interpret mnemonics, symbols and operands that are then sent to the machine in machine level code. This is important to understand because when you first start programming most people make the assumption it's either this or that meaning either I compile or interpret. No coding language beyond low level machine code is either compile only instructions or interpret only instructions!!!
We went over this in "Not All Compiled Code is Created Equal". Assembly language is the first instance of this. Machine code is what the machine reads but assembly language is what a human can read. As computers process faster, through better technological advancements, our lower level languages begin to become more condensed in nature and not needed to be manually implemented. Assembly language used to be the high level coding language as it was the quicker method to coding a machine. It was essentially a syntax language that once assembled (the lowest form of compiling) directly converted to machine language. An assembler is a compiler but not all compilers are assemblers.
High Level Coding
High level coding languages are languages that are one step above assembly but may even contain an even higher level (this would be Bytecode/Intermediate languages). These languages are compiled from there defined syntax structure into either the machine code needed, the bytecode to be interpreted or a hybrid of either of the previous method combined with a special compiler that allows for assembly to be written inline. High level coding like it's predecessor, Assembly, is meant to reduce the workload of the developer and remove any chance for critical errors in redundant tasks, like the building of executable programs. In today's world rarely will you see a developer work in assembly for the sake of crunching data in for the benefit of size alone. More often than a developer may have a situation, like in video game console development, where they need a speed increase in the process. Because high level coding compilers are tools that seek to ease the development process they may not 100% of the compile the code in the most efficient manner for that system architecture. In that case Assembly code would be written to maximize the system's resources. But you'll never see a person writing in machine code, unless you just meet a weirdo.
THE SUMMARY
If you made it this far, congratulations! You just listened more in one sitting than my wife can, about this stuff, for a lifetime. The OP's question was about performance of while vs for loops. The reason this is a moot point in today's standards is two-fold.
Reason One
The days of interpreting Javascript are gone. All major browsers (Yes, even Opera and Netscape) utilize a Javascript Engine that is made to compile the script before implementing it. The performance tweaks discussed by JS developers in terms of non-call out methods are obsolete methods of study when looking at native functions within the language. The code is already compiled and optimized for that before ever being a part of the DOM. It's not interpreted again while that page is up because that page is the runtime environment. Javascript has really become an intermediate language more so than interpreted script. The reason it will never be called an intermediate scripting language is because Javascript is never compiled. That's the only reason. Besides that it's function in a browser environment a minified version of what happens with Bytecode.
Reason Two
The chances of you writing a script, or library of scripts, that would ever require as much processing power as an desktop application on a website is almost nill. Why? Because Javascript was never created with the intent to be an all encompassing language. It's creation was simply to provide a medium level language programming method that would allow processes to be done that weren't provided by HTML and CSS, while the alleviating development struggles of requiring dedicated high level coding languages, specifically Java.
CSS and JS was not supported for most of the early ages of web development. Till around 1997 CSS was not a safe integration and JS fought even longer. Everything besides HTML is a supplemental language in the web world.
HTML is specific for being the building blocks for a site. You'd never write javascript to fully frame a website. At most you'd do DOM manipulation but building a site.
You'd never style your site in JS as it's just not practical. CSS handles that process.
You'd never store, besides temporarily, using Javascript. You'd use a database.
So what are we left with then? Increasingly just functions and processes. CSS3 and its future iterations are going to take all methods of styling from Javascript. You see that already with animations and psuedo states(hover, active, etc.).
The only valid argument of optimization of code in Javascript at this point is for badly written functions, methods and operations that could be helped by optimization of the user's formula/code pattern. As long as you learn proper and efficient coding patterns Javascript, in today's age, has no loss of performance from its native functions.
for(var k=0; ++k; k< 20){ ... }
can be sped up by making it a negative
while loop:
var k = 20; while(--k){ ... };
A more accurate test would be to use for to the same extent as while. The only difference will be that using for loops offers more description. If we wanted to be super crazy we could just forgo the entire block;
var k = 0;
for(;;){doStuff till break}
//or we could do everything
for (var i=1, d=i*2, f=Math.pow(d, i); f < 1E9; i++, d=i*2, f=Math.pow(d,i)){console.log(f)}
Either way...in NodeJS v0.10.38 I'm handling a JavaScript loop of 109 in a quarter second with for being on average about 13% faster. But that really has no affect on my future decisions with which loop to use or the amount I choose to describe in a loop.
> t=Date.now();i=1E9;
> while(i){--i;b=i+1}console.log(Date.now()-t);
292
> t=Date.now();i=1E9;
> while(--i){b=i+1}console.log(Date.now()-t);
285
> t=Date.now();i=1E9;
> for(;i>0;--i){b=i+1}console.log(Date.now()-t);
265
> t=Date.now();i=1E9;
> for(;i>0;){--i;b=i+1}console.log(Date.now()-t);
246
2016 Answer
In JavaScript the reverse for loop is the fastest. For loops are trivially faster than while loops. Be more focused on readability.
Here is some bench marking.
The following loops where tested:
var i,
len = 100000,
lenRev = len - 1;
i = 0;
while (i < len) {
1 + 1;
i += 1;
}
i = lenRev;
while (-1 < i) {
1 + 1;
i -= 1;
}
for (i = 0; i < len; i += 1) {
1 + 1;
}
for (i = lenRev; - 1 < i; i -= 1) {
1 + 1;
}
2017 Answer
jsperf for vs foreach on Chrome 59
Here you can see Array.forEach has become fastest on the latest version of Chrome (59) as of the date written (7/31/17). You can find average times for other browser versions here: https://jsperf.com/for-vs-foreach/66.
This shows to prove that ES engine optimization changes what is more efficient at any time.
My recommendation is that you use whichever is more expressive for your use case.
Performance differences within the same magnitude will mostly be irrelevant in the future as computers become faster exponentially by Moore's Law.
There is quite a bit of excitement on asm.js and how it will be able to run some very heavy applications. However, it is compiled from C++ code. Is it still possible to get the benefit of current improvements without knowing C++ or other low level languages?
Here is the thought that I had: Is it at all possible that we can write the code in Js, have it recompiled for asm.js for optimisation?
If you have small function that is very computation-heavy (crunching numbers rather than manipulating DOM) you could rewrite it in asm.js style yourself, manually. It's possible (I've done it), but tedious.
There are other asm.js compilers, e.g. LLJS that you may use instead of C++.
However, asm.js is not magic. You will only get performance benefit when you use language that is much better suited for ahead-of-time optimization than JS. You can't take fully-featured JS and make it faster by running JS VM on top of JS VM, just like you can't make ZIP files smaller by zipping them.
However, it is compiled from C++ code.
It is not. It's a language. Any program can emit text files which contain asm.js code. Emscripten compiles LLVM IR into asm.js, and there are compilers from C and C++ to LLVM IR, but this is only one possible way of getting asm.js code. Admittedly, it's currently the most mature, practical and popular way, but I would not be surprised at all if other asm.js compilers for other languages pop up some time in the future.
Is it still possible to get the benefit of current improvements without knowing C++ or other low level languages?
Well, in theory any language that can efficiently be compiled to machine code ahead-of-time can be implemented efficiently using asm.js, and that includes some rather high-level ones (e.g. Haskell).
But currently, nobody has a working implementation, and I don't expect this to ever become very popular. Right now, if you want asm.js performance, you'd probably write C or C++ code and compile it to asm.js, yes.
Note that the above excludes (among many others) Javascript.The fact that asm.js is a subset of Javascript is convenient in that asm.js code will run on unmodified browsers, but it's not of much use for anyone writing Javascript. asm.js is basically just a thin layer above machine code, with some amends for security and JS interoperability. Compiling JS to asm.js is as hard as compiling it to machine code: Easy if you don't give a damn about performance (just always used boxed dynamically-typed values like an interpreter, and emit calls to runtime library functions), very hard when you do.
In fact, after decades of research into the subject, there's still no example of a highly dynamic language like Javascript, Ruby or Python being compiled into machine code ahead of time and running much faster than a clever interpreter. Just-in-time compilation, on the other hand, is very much practical -- but the major JS engines already do that, in a less roundabout way than compiling to asm.js, then parsing it again and compiling it to machine code.
Asm.js isn't a separate language, but a subset of Javascript. It's just Javascript with a lot stripped out for performance. This means that you don't need to learn another language, though in this case knowing C/C++ might be useful to understand it.
Asm.js is a very strict subset of JavaScript, that can be generated relatively easily when compiling from C/C++ to JavaScript. Asm.js code is much closer to machine code than ordinary JavaScript code, which allowed browsers to heavily optimise for any code written in asm.js. In browsers that implemented those optimizations, your code will typically run about 50% of the speed of a C/C++ program that is compiled to machine code... which may seem slow, but is a hell of a lot faster than any ordinary JavaScript!
However, precisely because it's optimized for machines rather than humans, asm.js is practically impossible to handcode by any human developer... even though it's just JavaScript. While it is technically possible to convert - at least a subset of - ordinary JavaScript to an asm.js equivalent, such a conversion is not an easy task and I haven't encountered any project yet that made any attempt to achieve this.
Until someone achieves such a Herculean task, the best approach to producing asm.js code remains writing your code in C/C++ and converting it to JavaScript.
For more info on asm.js, see eg. John Resig's article from 2013 or the official specs.
I've read the article about Google's upcoming DASH/DART language, which I found quite interesting.
One thing I stumbled upon is that they say they will remove the inherent performance problems of JavaScript. But what are these performance problems exactly? There aren't any examples in the text. This is all it says:
Performance -- Dash is designed with performance characteristics in
mind, so that it is possible to create VMs that do not have the performance
problems that all EcmaScript VMs must have.
Do you have any ideas about what those inherent performance problems are?
This thread is a must read for anyone interested in dynamic language just in time compilers:
http://lambda-the-ultimate.org/node/3851
The participants of this thread are the creator of luajit, the pypy folks, Mozilla's javascript developers and many more.
Pay special attention to Mike Pall's comments (he is the creator of luajit) and his opinions about javascript and python in particular.
He says that language design affects performance. He gives importance to simplicity and orthogonality, while avoiding the crazy corner cases that plague javascript, for example.
Many different techiques and approaches are discussed there (tracing jits, method jits, interpreters, etc).
Check it out!
Luis
The article is referring to the optimization difficulties that come from extremely dynamic languages such as JavaScript, plus prototypal inheritance.
In languages such as Ruby or JavaScript, the program structure can change at runtime. Classes can get a new method, functions can be eval()'ed into existence, and more. This makes it harder for runtimes to optimize their code, because the structure is never guaranteed to be set.
Prototypal inheritance is harder to optimize than more traditional class-based languages. I suspect this is because there are many years of research and implementation experience for class-based VMs.
Interestingly, V8 (Chrome's JavaScript engine) uses hidden classes as part of its optimization strategy. Of course, JS doesn't have classes, so object layout is more complicated in V8.
Object layout in V8 requires a minimum of 3 words in the header. In contrast, the Dart VM requires just 1 word in the header. The size and structure of a Dart object is known at compile time. This is very useful for VM designers.
Another example: in Dart, there are real lists (aka arrays). You can have a fixed length list, which is easier to optimize than JavaScript's not-really-arrays and always variable lengths.
Read more about compiling Dart (and JavaScript) to efficient code with this presentation: http://www.dartlang.org/slides/2013/04/compiling-dart-to-efficient-machine-code.pdf
Another performance dimension is start-up time. As web apps get more complex, the number of lines of code goes up. The design of JavaScript makes it harder to optimize startup, because parsing and loading the code also executes the code. In Dart, the language has been carefully designed to make it quick to parse. Dart does not execute code as it loads and parses the files.
This also means Dart VMs can cache a binary representation of the parsed files (known as a snapshot) for even quicker startup.
One example is tail call elimination (I'm sure some consider it required for high-performance functional programming). A feature request was put in for Google's V8 Javascript VM, but this was the response:
Tail call elimination isn't compatible with JavaScript as it is used in the real
world.
By now, most mainstream browsers have started integrating optimizing JIT compilers to their JavaScript interpreters/virtual machines. That's good for everyone. Now, I'd be hard-pressed to know exactly which optimizations they do perform and how to best take advantage of them. What are references on optimizations in each of the major JavaScript engines?
Background:
I'm working on a compiler that generates JavaScript from a higher-level & safer language (shameless plug: it's called OPA and it's very cool) and, given the size of applications I'm generating, I'd like my JavaScript code to be as fast and as memory-efficient as possible. I can handle high-level optimizations, but I need to know more about which runtime transformations are performed, so as to know which low-level code will produce best results.
One example, from the top of my mind: the language I'm compiling will soon integrate support for laziness. Do JIT engines behave well with lazy function definitions?
This article series discusses the optimisations of V8. In summary:
It generates native machine code - not bytecode (V8 Design Elements)
Precise garbage collection (Wikipedia)
Inline caching of called methods (Wikipedia)
Storing class transition information so that objects with the same properties are grouped together (V8 Design Elements)
The first two points might not help you very much in this situation. The third might show insight into getting things cached together. The last might help you create objects with same properties so they use the same hidden classes.
This blog post discusses some of the optimisations of SquirrelFish Extreme:
Bytecode optimizations
Polymorphic inline cache (like V8)
Context threaded JIT (introduction of native machine code generation, like V8)
Regular expression JIT
TraceMonkey is optimised via tracing. I don't know much about it but it looks like it detects the type of a variable in some "hot code" (code run in loops often) and creates optimised code based on what the type of that variable is. If the type of the variable changes, it must recompile the code - based off of this, I'd say you should stay away from changing the type of a variable within a loop.
I found an additional resource:
What does V8 do with that loop?