On May 13, 2008, at 4:28 PM, Vladimir Vukicevic wrote:


On May 13, 2008, at 4:10 PM, Oliver Hunt wrote:

My experience implementing this in WebKit showed a pure byte array backing store was significantly faster than using boxed values.

Faster for which operation, though? The put, or the actual manipulation? It's a tradeoff, really; if you're doing limited pixel manipulation, but lots of putImageData, you can optimize that directly by just calling putImageData once to an offscreen canvas and then blitting that with drawImage. If you're doing lots of pixel manipulation but only one putImageData, I guess you can use a JS array for your intermediate ops to avoid the checking overhead, and set the image data pixels all at once (though again paying the checking penalty per pixel), but having cheap putImageData.

Throwing the error at putImageData time lets the implementation optimize in whatever way is most convenient/performant (either at pixel operation time by setting an error bit in the ImageData object which is checked by putImageData, or at putImageData time), and is (IMO) more flexible.. given that errors are an exceptional case, I don't think the spec should force the checking per pixel.

I found it faster in general across quite a few tests. I would argue that if you are using ImageData in a way that leads to you writing to the same pixel multiple times you should improve your algorithms (this is just the generic over painting issue).

I dunno, some kind of iterative algorithm that you want to visualize at random timesteps. You could keep the output in a separate array and copy over when you want to render it.

I'm not sure what you mean. By my interpretation that would require more work when you validate on blit, because while you would not have to validate when you copy the invalidated region of your buffer into the ImageData buffer it would not need to be validated, but when you then go to blit the ImageData, putImageData *must* revalidate the entirety of the ImageData buffer (hmmm, i suppose the UA could try tracking dirty regions in the ImageData buffer to minimise revalidation? i suspect this would not be significantly better than just validating on every pixel put)

If you actually meant you were using the ImageData buffer as your working buffer then you would possibly be doing excessive revalidation, but in my experience such a case would be atypical (and we're more interested in the performance of the normal case vs. edge cases) and the cost of clamping, etc is dwarfed by the dispatch cost just to do the assignment (at least in WebKit) so i'm not sure there would a significant loss in performance anyway.



A very reall issue to consider though is the case where I've been very careful to only update those pixels that need to be updated. If the ImageData is not clamped, etc on put then *every* blit must do a complete revalidation of the entire ImageData data buffer.

Yep, that's true.

I think we need a list of use cases for ImageData, off the top of my head i can think of: * filters -- in general a single write per pixel, potentially multiple reads
* Generated images -- still arguably single write per pixel
* I'm not sure what to call this -- but things like 
http://jsmsxdemo.googlepages.com/jsmsx.html

I honestly can't think of something that would (sanely) expect to be writing multiple times to the same pixel between blits, but i should note i haven't actively spent any significant time trying to come up with these. That said in all of the above cases the cost of immediate clamping is technically the same as delaying the clamp, although it also has the benefit of allowing reduced memory usage.

Yeah, those are all good use cases -- it just seems like requiring immediate clamping is basically specifying for a specific implementation, when the overall goal is "checking for invalid data". Specifying that the error should come from putImageData would give implementations more flexibility, without limiting error checking. (You could argue that it's easier to get a precise error location by checking on pixel assignment, but I don't think that the potential cost and loss of flexibility is worth it. Once authors know that they have an error in their data, they can take other action to track it down.)

There is no implementor freedom here -- you either clamp immediately, or you do not clamp immediately, if one UA does not clamp then it will have different behaviour from the other UAs leading to behavioural incompatibility (eg. one site may expect the values to be clamped immediately, and therefore not work in UAs that don't clamp, another may believe that the clamping happens later leading it to break in those UAs that clamp immediately).

This is not to say there's no room for implementation variation -- an implementation *could* maintain the data as an array of boxed values provided it performed the requisite toNumber and clamping and rounding operations, or it could store as an array of unboxed types -- there are potential advantages in doing it in either way. The issue is when clamping occurs, which isn't an implementation detail, it's fundamental to how the data structure works.

   - Vlad

--Oliver

Reply via email to