0

I am writing an interpreter for a functional programming language that is going to run in the browser. Needless to say, performance is the one and only concern in this application. Emscripten is an LLVM→JavaScript compiler which claims to produce programs that run only 2~3 times slower than native. It is really surprising, considering actual JavaScript applications tend to run 7 to 10 times slower than native, according to the Computer Benchmarks Game. And those are exactly the types of application I am worried about.

So, said that, would it be profitable to code my application in C, and then compile it to JavaScript using asm.js, or is there something I am missing?

MaiaVictor
  • 5,820
  • 7
  • 27
  • 45
  • A "runtime" as in "a library supplying run-time services to a program", or as in "an interpreter"? –  Jun 20 '14 at 19:45
  • I guess so, but it also takes care of the memory management, so I am not sure that is considered an interpreter by the terminology. – MaiaVictor Jun 20 '14 at 19:47
  • 1
    Not familiar with `asm.js` or the likes, but from your description it seems you will end dealing with Javascript... and which is worse, machine generated Javascript where the generator probably won't have input to decide about optimizations. If I wanted performance, I would go fully native with a plugin. – SJuan76 Jun 20 '14 at 19:48
  • No, memory management is just normal part of runtime services. But it seems strange to have explicit(-ly implemented) memory management in something running in a JS environment. How is your functional language implemented, by compilation to ordinary JavaScript? –  Jun 20 '14 at 19:49
  • 2
    @SJuan76 From what I understand `asm.js` is a subset of JavaScript that avoids the features that really limit the important optimizations. See e.g. *Why not just keep optimizing JavaScript JIT compilers instead?* in the [asmjs.org FAQ](http://asmjs.org/faq.html) – Doval Jun 20 '14 at 19:50

1 Answers1

3

Your proposed approach is as follows:

  1. Code your interpreter in C.
  2. Compile the C to Javascript using Emscripten or asm.js.
  3. Run Javascript using (I guess) a browser resident Javascript implementation.

(If the Javascript implementation is not browser resident, then I don't see the point of Javascript. Compiling the C directly to native code will be faster.)

You postulate that (based on the assertions of the Emscripten / asm.js proponents), this would give you a faster interpreter than if you coded directly in Javascipt.

Now it may well be true that a C -> Javascript application runs faster than a typical hand-written Javascript version of a C application. But when you think about it, if the tools capable of generating javascript that runs fast, then someone who understands how to write optimizable javascript should be able to write code that runs just as fast. And in fact, they may even be able to do better, especially if they take the time to profile and tune the javascript.

And as comments pointed out, if you take the C -> Javascript route it will be impractical to hand optimize the generated Javascript.

But it really boils down to how good you are at writing Javascript ... compared to what those tools will generate it from some hypothethical C code that hasn't even been written yet. Nobody can give you an answer that is both definite and credible.


But I think that your big picture thinking is a bit astray:

Needless to say, performance is the one and only concern in this application.

That is short-sighted. There are other concerns; i.e. speed of coding, easy of debugging, maintainability, portability and ... correctness. And in fact, these should be taken into account your choice of implementation approach.

And the flipside is that if interpreter performance is really your one and only concern, then maybe you should implement it in C, compile directly to native code and ship it as a native plugin. Or implement a compiler for your functional language rather than an interpreter.

Stephen C
  • 25,180
  • 6
  • 64
  • 87
  • I agree with you, but it could be the case that while someone very good at optimising JavaScript could do a better job than emscripten, he must not just be good, but **really** good. Probably inhumanly good, because in order to get that kind of performance out of it, you'll be probably writing some ridiculously obfuscated asm.js, going through reinventing pointers and allocators, up to a point it isn't really JavaScript anymore. But if you mean you can get such performance by using usual JS, including its builtin arrays, objects, functions etc, I fear that is really unlikely.... – MaiaVictor Jun 21 '14 at 03:52
  • If you think about it, Emscripten makes use of decades of research in optimising C, including a wide range of optimisations that are not even possible in JavaScript - V8 or not. That kinda makes my hypothesis more believable. – MaiaVictor Jun 21 '14 at 03:54
  • @Dokkat Emscripten compiles to Javascript that can be run anywhere Javascript can be run (meaning, no plugin for a browser or any other native piece of code). Emscripten cannot generate "not even possible in Javascript" code, because Javascript is all it generates. – Izkata Jun 21 '14 at 04:19
  • 1
    @Dokkat Or of you meant optimizing the C code and then converting that, that's an even bigger issue - a C optimization isn't necessarily going to speed up Javascript. It might even do the opposite, given how different the languages and memory management are. – Izkata Jun 21 '14 at 04:21
  • The latter. It performs optimisations that are not possible in JavaScript. For example, a specific function as coded in C could be optimised taking account its type, which is not possible in JavaScript. So in order to get the same kind of optimisation in JS, you couldn't rely on the compiler nor using built-in JS functions. You could, in theory, yes, but then you'd not have something very far from linguistic JS. – MaiaVictor Jun 21 '14 at 05:00
  • And as much as your statement about optimisations is interesting, it is simply not true in all cases. Certain optimisations will mostly likely always generate faster code. For example, optimising `for (var i=0;i<1000;++i) x+=1` to `x += 1000` will pretty much always be faster in any kind of target, because you just decreased the number of operations. Or, more obviously, `map f . map g` will mostly always be slower than `map (f . g)`, for the same reason. In other words, albeit not guaranteed, it is often **likely** that a program with fewer reductions will have better performance. – MaiaVictor Jun 21 '14 at 05:04