4 ms·
As anecdata, I've also found that using typed arrays does not speed up (actually slows down, by 10% or so) code which uses integer arrays. Making sure that arra
by joppy 5y ago
As anecdata, I've also found that using typed arrays does not speed up (actually slows down, by 10% or so) code which uses integer arrays. Making sure that arrays stay in packed-small-integer format (which is not always obvious: for example one has to replace x => -x with x => 0-x to avoid the old IEEE -0 from kicking in) consistently outperforms typed arrays for me, by a large margin if allocating many small arrays, and by a small margin if allocating one large array.
I found similarly "meh" performance improvements when trying to port my Javascript code to webassembly: either modern Javascript implementations are absolutely amazing, or webassembly runtimes still have a ways to go.
- vanderZwan 5y agoThis is most likely because allocating typed arrays is really, really slow in JavaScript. IIRC it has to do with the fact that there is a lot of flexibility regarding backing buffers or something; each typed array object has about 200 bytes of overhead compared to a dozen bytes for a plain array or object (roughly). Typed arrays are mainly faster in scenarios where you allocate one or a few large TypedArrays once and then re-use them a lot. That also explains your experience with many small arrays. That's basically the worst way to use TypedArrays.
- joppy 5y agoYes, I did think it wasn't a good way to used typed arrays, but I was still surprised that when allocating only a very small number of large arrays, just plain Javascript arrays outperformed typed arrays.
- yuri91 5y agoA good trick to convince JS engines that you are dealing with integers is to use the "`|0` operator": let a = 1; let b = 2; let c = a+b|0; // c is guaranteed to be a 32 bit signed integer This not only ensures correct 32 bit integer semantics (like wrapping around), but also helps the engines to use actual integer instructions in the generated machine code. For unsigned 32 bit integers, there is `>>>0`, and for multiplication, there is Math.imul().
- vanderZwan 5y agoOne of my colleagues told me to stop doing that because in (I think) V8 these values are immediately converted back to a double nowadays. So annotating all code with |0 doesn't really add speed benefits there, just extra conversions between doubles and integers. Said colleague used to maintain human-asmjs so I trust he knows what he's talking about. [0] https://github.com/zbjornson/human-asmjs https://github.com/zbjornson/human-asmjs
- cpleppert 5y ago>> This not only ensures correct 32 bit integer semantics (like wrapping around), but also helps the engines to use actual integer instructions in the generated machine code. But there is only one type of number in javascript. Everything is just a double(BigInt aside). You get a 32-bit integer because the bitwise operator casts the result to one. c has the exact same semantics as any other js number. Yeah there are tricks to convince the engine you are using an integral type but those unless you are doing a lot of benchmarks they aren't really useful. Any compilation tier can choose to use any intermediate representation it wants.
- vanderZwan 5y ago> But there is only one type of number in javascript. Everything is just a double(BigInt aside). There is nothing stopping JS engines from trying to infer when a number is only an integer and optimize for that. In fact, that's what Small Integer (SMI) optimizations are all about[0]. It's just that |0 isn't really able to guarantee that our number value is the type of SMI that V8 optimizes for (since the V8 SMIs are 31 bits, and bitmasking operations only guarantee 32 bit integers) https://ponyfoo.com/articles/an-introduction-to-speculative-optimization-in-v8 https://ponyfoo.com/articles/an-introduction-to-speculative-...