3 ms·
Assuming that we're using V8 and the function is hot, both the JS code and the WASM will be compiled to optimized bytecode by V8's TurboFan optimizing compiler.
by tylerhou 5y ago
Assuming that we're using V8 and the function is hot, both the JS code and the WASM will be compiled to optimized bytecode by V8's TurboFan optimizing compiler. The two big reasons why JS is inefficient vs Rust+WASM is because (1) everything is untyped -- without being able to statically resolve properties, the compiler is forced to resort to string lookups and (2) garbage collection. Compiling Rust to WASM will emit code that uses Rust's type system and lifetime analysis to create direct accesses and deallocate objects when necessary.
For such a small program (write the current time to a socket), it's trivial for TurboFan to examine the types of the JS code at runtime [1]. Also, escape analysis should also be trivial [2]. So, at runtime, the optimizing compiler can (1) replace string lookups with very fast address dereferences, and (2) insert appropriate deallocations. My guess is that with these two optimizations the performance difference can be reduced significantly. (Of course there is still some overhead -- deoptimization checks, etc. -- but it's not nearly as big as between a 5 MB JS file vs the same amount of code in Rust.)
[1] E.g. https://v8.dev/blog/fast-properties https://v8.dev/blog/fast-properties
[2] https://www.jfokus.se/jfokus18/preso/Escape-Analysis-in-V8.pdf https://www.jfokus.se/jfokus18/preso/Escape-Analysis-in-V8.p...
- saagarjha 5y ago> For such a small program (write the current time to a socket), it's trivial for TurboFan On the contrary, for short programs the JavaScript engine may not choose to do anything at all beyond run it through the baseline interpreter.
- josephg 5y ago> For such a small program ... the performance difference can be reduced significantly. I think you're wrong. Small programs don't necessarily minimize the difference between languages. Small programs often exacerbate them. Often for weird, idiosyncratic reasons. Especially if you're measuring time-to-first-byte, and not letting the VM warm up. For example, in this case I wouldn't be surprised if most of the CPU time was going into node + v8's startup, rather than executing the user's javascript at all. Look at the plaintext techempower benchmarks[1]. These benchmarks test tiny amounts of code - the programs only have to respond with "hello world" HTTP responses. The best performers are hitting hardware limits. If your theory that small program = small relative cost of using javascript was true, nodejs's performance should be similar to rust / C++. It is not - node is only 13% of the performance of the top performers. Weirdly "justjs" (another v8 based runtime) is ~5x faster than nodejs on this test. The reason probably has nothing to do with javascript at all, and is because justjs has less overhead and talks to the OS in a more efficient way. (It probably uses io_ring.) But maybe this is evidence you're technically correct. The performance differences can be reduced. But we have every reason to assume nodejs will have way more overhead than rust at executing the same code. In all, I agree with other posters. A benchmark showing rust on fastly is faster than javascript on cloudflare tells us nothing about the underlying hosting providers. https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=plaintext https://www.techempower.com/benchmarks/#section=data-r20&hw=...
- tylerhou 5y agoOf course you're right in cases of a cold start. But if I understand the benchmark in the linked post correctly, the TTFB was measured assuming that the VM was already hot & and the code optimized through TurboFan already. (Hence "assuming the function is hot.") Also, I don't see Rust + WASM on the linked benchmarks. WASM code still has to run in a VM and probably uses the Node.js runtime for syscalls. (Based on a quick search, it seems like most people compile to WASM and create Node bindings with wasm-bindgen.) Third, my claim isn't that JS can reach Rust+WASM speeds; just that it's not as slow as you might expect because you do have type information. Anyway, the whole point is moot because we're arguing over microsecond differences.
- d110af5ccf 5y agoIn many cases those TechEmpower benchmarks show JavaScript beating both C++ and Rust frameworks. Are those tests anywhere close to being representative of real world use? V8 really is an incredible piece of engineering, but then so is LLVM. For context I don't do much if any web stuff.
- josephg 5y agoI think whats going on is that the code involved really isn't spending much time in JS / C++ / whatever at all. The winners are probably libraries tuned to make good use of threading, io_uring and stuff like that.