| ▲ | Why Object of Arrays beat interleaved arrays: a JavaScript performance issue(royalbhati.com) | |||||||||||||||||||||||||
| 32 points by howToTestFE 7 days ago | 13 comments | ||||||||||||||||||||||||||
| ▲ | andersa 2 hours ago | parent | next [-] | |||||||||||||||||||||||||
I had a similar problem when I was making a tool processing a lot of data in the browser. I'd naively made a large array of identical objects each holding a bunch of fields with numbers. Turns out, this works completely fine in Firefox. However, in Chrome, it produces millions of individual HeapNumber allocations (why is that a thing??) in addition to the objects and uses GBs of RAM, and is slow to access, making the whole thing unusable. Replacing it with a SoA structure using TypedArray made it fast in both browsers and fixed the memory overhead in Chrome. As someone more familiar with systems programming than web, the concept of creating individual heap allocations for a single double baffles me beyond belief. What were they thinking? | ||||||||||||||||||||||||||
| ||||||||||||||||||||||||||
| ▲ | Koffiepoeder an hour ago | parent | prev | next [-] | |||||||||||||||||||||||||
For those interested in browser differences, on my machine: Firefox
Chrome
Seems the interleaved being slower is consistent across browsers! | ||||||||||||||||||||||||||
| ▲ | gethly 2 hours ago | parent | prev | next [-] | |||||||||||||||||||||||||
SoA is nothing new. Not sure why it needs to be even discussed... Anyway, here's few videos of interest: https://www.youtube.com/watch?v=WwkuAqObplU https://www.youtube.com/watch?v=IroPQ150F6c Odin also supports SoA natively https://odin-lang.org/docs/overview/#soa-data-types | ||||||||||||||||||||||||||
| ▲ | saghm 6 hours ago | parent | prev | next [-] | |||||||||||||||||||||||||
> Eliminating per-element object overhead — This is the biggest win (~5-6x) I feel like this phrasing might be easy to misinterpret. Without carefully considering the context, it seems like it's implying that objects have higher overhead than arrays, and my intuition is that this is true, but I'd argue that there's a potentially more relevant way of looking at things. In the "object of arrays" layout, you have one object and three arrays, but in the "array of objects" layout, you have one array and N objects, where N is the size of the array. Even if the overhead of objects was the same as can array, you'd be looking at more overhead as soon as you went past three elements. In fact, even if the overhead of an object was lower than the overhead of an array, you'd still reach more overhead with the "array of objects" layout if you have enough elements to make up for the difference. With a TypedArray (or an array of a single type that's optimized by the runtime in the way described fairly early on in the article), you're not looking at an extra level of indirection per element like you would with an object. I'd be curious to see what the results would be if they repeated the "array of objects" benchmark with an "array of arrays", where each element is an array of size 3. I could imagine them being quite similar, but I'm also not sure if there's even more nuance that I'm falling to account for (e.g. maybe the runtime would recognize that an array of N/3 elements each being an array of 3 numbers could be "flattened" to an underlying representation of array of size N in memory and perform the same optimizations. I think the meta lesson here may be that intuition about performance of arrays in JavaScript might be pretty tricky. At least in terms of external semantics, they're supposed to be roughly equivalent to objects with numbers as keys, but in practice there are probably enough optimizations being done (like the implicit recognition of an array of numbers as described in the article) that I suspect that intuition might be a bit naive in a lot of cases, and it's probably better to verify what's actually happening at runtime rather than trying to guess. (The meta meta lesson is that this is true for a lot of things in pretty much every language, and it's sometimes going to be necessary to verify your assumptions about what performance will be, but I think that's something easy to fail to do even when you're aware of it being an easy trap, so having some general things to look out for like arrays potentially not being intuitive can still be helpful). | ||||||||||||||||||||||||||
| ||||||||||||||||||||||||||
| ▲ | anematode 6 hours ago | parent | prev | next [-] | |||||||||||||||||||||||||
> Sometimes even SIMD (eez nuts?) I'm a bit rusty here, does V8 actually do auto-vectorization of JavaScript code these days? | ||||||||||||||||||||||||||
| ||||||||||||||||||||||||||
| ▲ | jonny_eh 7 hours ago | parent | prev [-] | |||||||||||||||||||||||||
> This test is a manufactured problem, a silly premise, false test cases and honestly dishonest if not ignorant It’s amazing how vitriolicly wrong people can be. Before publicly criticizing someone in the above way, prove them wrong first. Don’t just assume they’re wrong. | ||||||||||||||||||||||||||
| ||||||||||||||||||||||||||