react-native-canvas icon indicating copy to clipboard operation
react-native-canvas copied to clipboard

getImageData slow

Open runrevben opened this issue 5 years ago • 9 comments

This is a super component and we've been using extensively in a project. Happy to contribute should someone be able to point me in the right direction:

I'm implementing a component that has to use getImageData() multiple times in a loop. Of the 10 or so calls in each loop, some take up to 500ms to resolve, others just 5ms. I'm guessing that the performance issue relates to the messaging between RN and the WebView, rather than the getImageData() call.

  1. Is there a work around?
  2. If not, Would implementing a custom function like getImageDataMultiple(RectangleArray) likely solve the issue by reducing the RN -> WebView interaction to a single call?
  3. Would it be accepted back into the source? I'd prefer not to maintain a custom fork if poss.

runrevben avatar Nov 18 '20 23:11 runrevben

Hey, thank you for taking the time for explaining your issue. I’d say getImageDataMultiple is a little too specific but I’d be glad to add some batching functionally. I think it can be done if the component will wait for the next tick before sending the request to the WebView then multiple requests can be sent together and return together (assuming they are called with Promise.all or without await). Even without changes to the code if you are not using Promise.all right now it should really help with performance of multiple calls to the webview

iddan avatar Nov 19 '20 06:11 iddan

OK thanks. We are currently using a mixture of promise.all and await.. I'll look at refactoring to remove the await.

Batching sounds like a great idea though. If you think that's something that can realistically be added we'd be happy to help with development, unless it's straightforward for you? I'm expecting our app will increase its dependance on getImageData so being able to batch would be a bit benefit.

Cheers,

Ben

runrevben avatar Nov 23 '20 15:11 runrevben

I removed all my awaits and put the calls the getImageData in to a Promise.all call. It didn't make a great deal of difference to the performance. I'm wondering if I'm doing it right?

   const data = await Promise.all(
      parts.map(async (part) => {
        const [a, b, c, d] = getBoundsFromPath(part.path);
        ctx.getImageData(
            a * devicePixelRatio,
            b * devicePixelRatio,
            (c - a) * devicePixelRatio,
            (d - b) * devicePixelRatio
          )
          .then((imageData) => {
            return {
              name: part.name,
              data: Object.values(paintImageData.data),
            };
          });
      })
    );

All the data is returned as expected but there is a considerable wait between data being returned during the map

runrevben avatar Nov 23 '20 17:11 runrevben

I'm not sure how this get code works as you don't return the promise in the map function. But assuming you are, yes this is the correct way to do this (using async/await in the map function is fine). As I wrote in the previous comment. It is realistic to add on the RPC level between React Native and the WebView a batching mechanism that waits for the next tick and sends multiple calls to the WebView at once.

iddan avatar Nov 24 '20 10:11 iddan

Hi @iddan, we changed our code again as per your comments to return the promises and then resolved all our data once then promise.all returned. Unfortunately the performance improvement was minimal.

I'd be interested in your thoughts re implementing batching in your code. I think that would help us and others as it appears this library is the best on out there for Canvas and ReactNative. I'd be happy to show you what our app is doing and even get a developer to try and help implement the changes if that's useful.

runrevben avatar Nov 27 '20 09:11 runrevben

Check the code here: https://github.com/iddan/react-native-canvas/blob/master/src/Bus.js this is the object managing communication with the webview on the React Native side.

iddan avatar Nov 29 '20 08:11 iddan

Hi @idan,

I have found that getImageData is taking too long , Could you please help us with the batch approach ?

Thanks

ASKNJ avatar Mar 19 '22 20:03 ASKNJ

Hey @iddan ,

Can you please help me in finding out the batch approach? I am fetching imageData pixels but it is taking 30 seconds for reading 1080*1080 data

Thanks in advance for help!!

ASKNJ avatar Apr 08 '22 14:04 ASKNJ

Can someone post a MRE because nothing here proves that it's an underlying issue to the messager here.

getImageData is very slow by default, and calling it multiple times in a loop is expected to be very slow, in javascript.

nora-soderlund avatar Oct 05 '22 12:10 nora-soderlund