Bug 1943811 Comment 5 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

It looks like there are just a large number of Canvas2D getImageData calls here, and every time we do this, it allocates a new JS buffer object when it immediately tries to read the data from the canvas.

This is in general not a great strategy and we probably need some sort of lazy/deferred/copy-on-write approach to representing this data so that we don't always allocate every time you call getImageData, especially when the data is not modified. Also the requests are only for 1x1 pixel areas over and over, return as an ImageData encapsulating a JS array, both allocated on the GC heap. So the larger overhead is the ImageData and JS array object itself, not the small single pixel value in it, just to represent the 4 bytes of single pixel data. Pretty embarrassing. But that's potentially a larger project for down the road to fix, I don't know off hand that it would be simple.

Maybe there is some way we could consider to represent these small area requests inline to avoid allocating as much, if not able to avoid the allocation entirely.

Regardless, it does put a lot of strain on the GC, so maybe the GC team or JS can look into this and see if there's anything that can be done to make this demo run a bit faster.
It looks like there are just a large number of Canvas2D getImageData calls here, and every time we do this, it allocates an ImageData and a new JS array object when it immediately tries to read the data from the canvas. This is in general not a great strategy and we probably need some sort of lazy/deferred/copy-on-write approach to representing this data so that we don't always allocate every time you call getImageData, especially when the data is not modified.

Also the requests are only for 1x1 pixel areas over and over, return as an ImageData encapsulating a JS array, both allocated on the GC heap. So the larger overhead is the ImageData and JS array object itself, not the small single pixel value in it, just to represent the 4 bytes of single pixel data. Pretty embarrassing. But that's potentially a larger project for down the road to fix, I don't know off hand that it would be simple.

Maybe there is some way we could consider to represent these small area requests inline to avoid allocating as much, if not able to avoid the allocation entirely.

Regardless, it does put a lot of strain on the GC, so maybe the GC team or JS can look into this and see if there's anything that can be done to make this demo run a bit faster.

The offending JS app loop looks like:

    for (let i = 0; i < x.length; i++) {
        let xx = Math.round(x[i] * canvas.width);
        let yy = Math.round(y[i] * canvas.height);
        let px = name.getImageData(xx, yy, 1, 1).data;
        if (px[3] !== 0) {
            scales[i] = 0.1
        } else {
            scales[i] = 1
        }
    }
It looks like there are just a large number of Canvas2D getImageData calls here, and every time we do this, it allocates an ImageData and a new JS array object when it immediately tries to read the data from the canvas. This is in general not a great strategy and we probably need some sort of lazy/deferred/copy-on-write approach to representing this data so that we don't always allocate every time you call getImageData, especially when the data is not modified.

Also the requests are only for 1x1 pixel areas over and over (a common access pattern for looking up individual pixels), returned as an ImageData encapsulating a JS array, both allocated on the GC heap. So the larger overhead is the ImageData and JS array object itself, not the small single pixel value in it, just to represent the 4 bytes of single pixel data. Pretty embarrassing. But that's potentially a larger project for down the road to fix, I don't know off hand that it would be simple.

Maybe there is some way we could consider to represent these small area requests inline to avoid allocating as much, if not able to avoid the allocation entirely.

Regardless, it does put a lot of strain on the GC, so maybe the GC team or JS can look into this and see if there's anything that can be done to make this demo run a bit faster.

The offending JS app loop looks like:

    for (let i = 0; i < x.length; i++) {
        let xx = Math.round(x[i] * canvas.width);
        let yy = Math.round(y[i] * canvas.height);
        let px = name.getImageData(xx, yy, 1, 1).data;
        if (px[3] !== 0) {
            scales[i] = 0.1
        } else {
            scales[i] = 1
        }
    }

Back to Bug 1943811 Comment 5