6 ms·
I think this is an interesting exploration because I really enjoyed the description of profiling and improving performance, but I came away feeling exactly the
by anp 9y ago
I think this is an interesting exploration because I really enjoyed the description of profiling and improving performance, but I came away feeling exactly the opposite of the title. I think it's really cool that JS optimization can provide so many wins, but this article makes it seem fairly fickle and if they're not familiar with VM internals I would not expect most developers to complete this journey. Using wasm+rust/c++ is interesting in part because you can get so much more predictable performance out of the box. When the performance comes from language features instead of VM-specific optimizations the performance might be easier to maintain across revisions and hopefully will be less subject to regression from VM changes.
- jandem 9y agoI work on SpiderMonkey JS performance (and got mentioned in the article for fixing a perf bug!) and this is exactly the point I wanted to make. If you're not a VM engineer, it's much harder to write fast JS. Wasm also gives you much more predictable performance across engines, without requiring (often engine-specific) 'hacks' like function cloning.
- Jasper_ 9y agoFrom what I can tell, doing basic things like a property get on an object in WASM/host-bindings will require a spill to function, with no chance of specialization: https://github.com/WebAssembly/host-bindings/issues/11#issuecomment-352577514 https://github.com/WebAssembly/host-bindings/issues/11#issue... If you think the assembly in this article is bad, WASM/host-bindings appear to be even worse.
- luke_wagner 9y agoThat comment (which I made) explains why probably the best we can expect for wasm accessing normal JS objects is the same level of speed as a modern JS engine's "tier 1"/"baseline" JIT. But the Rust code discussed in the OP wasn't accessing JS objects, it was accessing Rust memory which lives in wasm's "linear memory", so I don't see how my comment really disagrees with what jandem or dikaiosune are saying.
- aschampion 9y agoHaving micro-optimized and maintained JS code over years and dozens of browser versions, I cannot echo this enough. Tuning JS both the in face of fickleness of VM quirks and data/context is a losing proposition for all but the most speed- and core-functionality-critical code. The point of rust+wasm benchmarks is that one can write reasonable, maintainable, functionality-focused code (not to mention all the rust-specific benefits) and get good performance out of the box.
- zbentley 9y agoWriting an O(N^2) algorithm that processes lots of data in wasm is not going to speed it up more than writing an O(log N) algorithm in pure JS; the knowledge of how to identify problems like that will serve you better in many more cases than the selection of a "fast" runtime.
- vvanders 9y agoNot totally true, some algos while large O(n) are incredible cache friendly. Radix sort for instance comes to mind.
- b0rsuk 9y agoI'm afraid it's easier to get started as a Javascript developer than a Rust developer. What if it's easier to learn JS optimization quirks than to become an average Rust developer ?
- hateduser2 9y agoIt seems less reliable to learn is optimization quirks, since you’re depending on an (infrequently changing?) implementation detail. Also writing those things sounds muh messier and less maintainable. All heuristic points I’m making.
- kbenson 9y agoIt's a cost/benefit type of situation. Learning to optimize JavaScript might cost less, but the benefit is fairly narrow, and may lesson over time (or you may need to pay more in attention and time to keep up with JavaScript VM changes). Rust (or C++) to WASM costs more (if you don't already know the language), but the benefit should stay static and useful over time, and there are many other benefits as well (such as having a fast low-level language to fall back on for other needs. This isn't unique to this situation either. If you're writing Python and your choice is to either deep dive into various hacks to maximize performance of your pure python or learn Rust/C/C++ and call out using an FFI mechanism, if you have the time to space, I think it's almost always better to learn the new language. There are many benefits to learning new languages beyond just the different performance characteristics, so if you can afford to take that path, I think it's usually a good choice to do so.
- mraleph 9y ago[Thank you for reading the post! I am glad you enjoyed it] All optimizations in the post can mostly be divided into three large groups: 1) algorithmic improvements; 2) workarounds for implementation independent, but potentially language dependent issues; 3) workarounds for V8 specific issues; You need to think about algorithms no matter which language you write in, so we don't need to talk much about the first group. In the post it is represented by sorting improvements (sorting subsequences rather than the whole array) and by discussions of caching benefits (or lack of them there-off). The second group is represented by a monomorphisation trick: the fact that the performance suffers due to polymorphism is not really a V8 specific issue and it is not even JS specific issue. You can apply this approach across implementations and even languages. Some languages apply it in some form for you under the hood. The last group is represented by argument adaptation stuff. Finally an optimization I did to mappings representation (using typed array instead of an object) is an optimization that spans all three groups. It's about understanding limitations and costs of a GCed system as whole. Now... Why did I choose the title? That's because I think group #3 represents the issue that should and would be mostly fixed over time. While groups 1 and 2 represent universal knowledge that spans across implementations and languages. Obviously it is up to each developer and each team to choose between spending N rigorous hours profiling and reading and thinking about their JavaScript code, or to spend N hours rewriting their stuff in a language X. What I want is: a) that everybody was fully aware that the choice even exists; b) language designers and implementors worked together on making this choice less and less obvious - which means working on language features and tools and reducing the need in group #3 optimizations.
- zbentley 9y ago> Some languages apply it in some form for you under the hood. I suspect some respondents will say, or believe, that this falls under the category of "you have to know the VM/runtime intimately to get good performance". I don't think that's true. If you know the general problems with polymorphic call sites, you can (in JS and many other languages) check to see if the runtime is applying optimizations of this kind by being explicit. If it helps, you can get a free optimization by setting explicit arity/dispatch just because you happened to know about the issues surrounding polymorphic dispatch. That's a case of fundamental knowledge speeding up/improving your progress; not a case of "you need to know the VM guts like the back of your hand to make code fast".
- mpweiher 9y ago> cool optimizations ... but ... fickle ... internals ... Yes. I wrote about this in some detail 2 years ago, Jitterdämmerung: http://blog.metaobject.com/2015/10/jitterdammerung.html http://blog.metaobject.com/2015/10/jitterdammerung.html
- Cthulhu_ 9y agoAnd yet, which is better; finding someone that has the skill and knowledge needed to optimize this (e.g. bring in a consultant), or rewrite the thing - hundreds if not thousands of lines of code and working hours being replaced by even more. And not just rewrite it, but (IMO) replacing it with more complicated technology (additional steps required to make it usable, additional skills needed to work on the project). I think people think too lightly of rewrites. Actually, I'd even argue that in some cases, rewrites are done because they're easier than actually fixing the problem. Yes, Rust and other languages will give you better performance out of the box, but at what cost?
- dikaiosune 9y agoLike any situation in software, there are likely to be tradeoffs. I certainly wouldn't advocate for launching large rewrites except under extreme duress. That said, I'm not sure I agree with how you're characterizing the tradeoffs for using wasm here. For one thing, the library in question sounds like it is a few thousand lines, not some gargantuan project. For another, part of what's awesome about wasm is that it can be somewhat incrementally adopted inside an existing project. I would also point out that for many teams or projects maintaining a consultant's code is not going to be as cost effective in the long run, especially if that code has a lot of language or VM specific optimizationswork done to it. Part of my point here is that the addition of new tech (rust, wasm) isn't complicated where optimizing JS is simple, but that they both carry complexity cost and should be assessed in context as possible solutions to a performance problem. I agree that rewrites are often taken too lightly, but if they address the original problems I think it would be more accurate to say that they are often needlessly expensive ways to solve problems that can also be solved in other, cheaper ways. I'd also point out that in the case of many open source projects, finding an optimization consultant is not even remotely an option. For many of those projects, if performance is suffering, someone needs to step up and figure something out. Then the question becomes which approach can be applied by some contributor who's actually willing to do it. If you don't have someone who understands polymorphism in VM runtimes, I think in many cases you'd be well served by sprinkling some wasm on the problem. Of course this doesn't apply in all cases.