4 ms·
I've used it for background image manipulation before. Paint the image to a canvas, then grab the imagedata off of it, split it into as many parts as you have
by Klathmon 10y ago
I've used it for background image manipulation before.
Paint the image to a canvas, then grab the imagedata off of it, split it into as many parts as you have threads, then use the "transferrableObjects" property of postMessage to zero-copy transfer the data to each worker to be processed, transferred back, and re-stitched together.
It's pretty powerful and suprisingly easy to work with once you understand it.
[0] is a snippet from the code, but be gentile... It was a personal project where I was trying out polymer 0.5 and made a lot of questionable design choices...
Also, I've heard of the idea of using webworkers as a "first class" platform. That is do all of the core parts of your application in them and only use the "main" thread as a "ui" thread. I haven't gotten a chance to try it out, but it seems like a great idea that could really work well in some SPAs.
[0] https://github.com/Klathmon/stitchpics/blob/master/app/elements/cross-stitch/element.js#L95-L118 https://github.com/Klathmon/stitchpics/blob/master/app/eleme...
- bartread 10y agoThat's interesting but, AFAIK (and, believe me, I'd be happy to be corrected), what you can't do is create a canvas element (even one not attached to the DOM), and paint directly to it using the standard 2D context and drawing primitives. Like I say, more than happy to be corrected, because that sort of thing would be incredibly helpful. Really, anything that lets you mess with a disconnected DOM in the background and then attach it in the foreground could be useful but (and, again, I'm very happy to be corrected), I don't think you can do this.
- vanderZwan 10y agoYou're talking about OffscreenCanvas. It's available in Firefox and nowhere else: https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCa... Having said that, if you want fast image manipulation, you're probably better off doing direct manipulation of Uint8Clamped arrays anyway, since that can be much faster.
- Klathmon 10y agoAnd if you can get away with it and don't mind a lot of bit shifting, it's even better working with the Uint32array which packs all 3 colors and alpha into one element which reduces your loops by 4X
- vanderZwan 10y agoBecause matching the native 32 word size is better for the prefetcher, right? Wouldn't most CPU's these days be smart enough to detect advancing the index by 4, and then using offsets? So: for(let i = 0; i < someUint8Array.length; i += 4){ let R = someUint8Array[i], G = someUint8Array[i+1], B = someUint8Array[i+2], A = someUint8Array[i+3]; // ... manipulations here }
- Klathmon 10y agoI'm honestly not sure why it is, but across all browsers on both ARM and x86_64 arches it was almost 3x faster than doing what you wrote. I have a feeling it's more of a JS JIT thing than a CPU prefetcher thing, but honestly I'm not really sure. In my program I linked above, it was actually faster to use Uint32array everywhere and then use functions to pull the 4 color values from it and another function to push the 4 values back to a uint32. Granted, it's been over a year since I last benchmarked that code, but I did reuse some of the image code recently and found iterating over a Uint32array to be significantly faster. (And funnily enough, manually unrolling the loop of Uint32array to something similar to what you wrote gave an additional small performance boost, but it was small enough to be not worth the extra weirdness in the code to me)
- vanderZwan 10y agoThanks for the info, that might save me some benchmarking time myself in the near future ;)
- Klathmon 10y ago
- Klathmon 10y agoAs the other commenter said, you are right that you can't work with canvas in the worker, but you can work directly with the array of image data which you'd often need to anyway for much processing. I saw a library a while ago that was trying to re-implement the canvas primitives using only typed arrays so it was worker safe but I'm not sure what happened to it.
- bartread 10y agoThanks - that might be interesting. See my comment above but, yes, I'd quite like to avoid implementing those primitives. I could get round it by drawing one image, and then processing the bytes for the rotations, but: - This might lead to the odd jaggy artifact because I'm rotating bitmaps rather than vectors, - It might not speed things up that much because I still need to create images from these arrays, - It starts to seem like quite a lot of work; maybe I'd be better off reducing the number of images slightly, and compensating by speeding up the minimum angular velocity. You can see what I'm up against at https://arcade.ly/games/asteroids/ https://arcade.ly/games/asteroids/. (Also, see my comment above, where I've made substantially the same points.)