Code Monkey home page Code Monkey logo

Comments (2)

andrei-markeev avatar andrei-markeev commented on August 22, 2024 3

Interesting observation!

I think there are 3 main parts that contributed to the surprising result you've got:

  1. Measuring performance is always tricky.
  2. C code is essentially faster - it's obvious, but if you hit some V8 optimization, then you're basically comparing apples to oranges... That's why V8 doesn't relay on benchmarks nowadays, instead, they measure load times for a random selection of real sites with big amount of users.
  3. TS2C is generating code that is far from perfect - that will hopefully be improved in future!

Tricky parts

Let's start with the tricky parts, and the most tricky part here I think is that you were probably measuring performance "the naΓ―ve way", so like this:

var start = performance.now();
for (var j = 0;j<1000000;j++) {
   // measured code here
}
console.log(performance.now() - start);

But in this case, you're leaving out the interpretation part from measurement. I mean, any Javascript code must be parsed before being actually executed, right? That's the main difference between using an interpreter/JIT vs real compiler that produces a binary and then you work with that.
Parsing is in fact what takes the most of time for a JIT. And by the time execution hits performance.now(), the whole code is obviously already compiled...

So in my opinion, the correct way to measure would be something like this:

var start = performance.now();
eval(`
    for (var j = 0;j<1000000;j++) {
       // measured code here
    }
`);
console.log(performance.now() - start);

It took 1064ms to execute on my machine compared to ~100ms in the first example. And obviously it'll take even more if you will execute a js file with with node executable because then you'll also take into account the node initialization time.
Btw I also tried putting eval inside the loop - that didn't work, Chrome thought for a minute and then the tab crashed πŸ˜„

V8 Optimizations

Ok, now about the optimizations that you might have hit:

If a compiler sees that same variable (like colorImage) is created over and over again inside a loop, it is a common thing to optimize this code out from the loop. Meaning that even though this code is written inside the loop, it is executed outside the loop, so only once! I actually tried to verify this assumption by manually taking this variable initialization outside of the loop, and voila, I've got exactly same ~100ms result...

In order to get similar behavior in C, you would need at least to build with -O2, and even then C might not recognize some of optimizations that V8 is able to do, because C is operating on much lower level.

TS2C is far from perfect

I want to remind that TS2C is still work in progress and it is made by me in my spare time. If interpretation time is excluded, then you're comparing quality of compilation by V8 (which is built by a big and experienced team of developers at Google) with quality of transpilation by TS2C (so the resulting code must also be readable!)... Well 😏

Your capacity trick improves performance because TS2C-generated code creates a dynamic array, and then this array is reallocated to twice the current size each time it reaches current maximum capacity. So it expands like this: 2 items => 4 => 8 => 16 => 32 => 64. So essentially for 1 million executions, it will do 6 million allocations, which is 5 millions more than necessary...

In this particular case, it is indeed possible to infer the initial capacity of the array to be set to length of the parameter array. I added this to my πŸ—’ TODO list and will try to implement this when I have time!

Additionally there are two arrays for garbage collection, which store references to all temporary arrays which need to be deallocated when executions reaches end. Try removing those completely and putting initialization of colorImage outside of the loop, and I think you will reach similar performance as the compiled V8 version.

Conclusion

V8 is pretty fast and has a lot of great performance optimizations, but in some cases, it cannot be used.

Main rationale for this project was to create a transpiler specifically tailored for IoT devices, as it is explained on the main project page. Low-memory microcontrollers often have just few kilobytes of memory available on board. They need to save battery energy, and for that reason, 99.9% of the time they sleep, waking up for just few milliseconds every 2-3 seconds. In such conditions, even small and optimized JS interpreters perform poorly...

from ts2c.

EmileSonneveld avatar EmileSonneveld commented on August 22, 2024 1

Hey Andrei,
Thanks for the extended explanation!
Counting the Eval time indeed makes sense, in that case, c is a very clear winner :D

Another great use case would be to use this concept for a scripting language for a game engine. Right now, Lua is a very popular scripting language for it's simple implementation and light runtime.
But this system would just beat it by an order of magnitude. I'd love to use it in a project one day!

Setting the initial capacity of the array could be a tricky problem, I guess language completeness is more important.

from ts2c.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.