libflif.js icon indicating copy to clipboard operation
libflif.js copied to clipboard

Slow processing vs poly-flif

Open FallingSnow opened this issue 9 years ago • 13 comments

libflif is much slower than poly-flif in my test and more unstable. Do you know if there are any specific optimizations that poly-flif does versus libflif?

https://github.com/UprootLabs/poly-flif/issues/27

FallingSnow avatar Jan 03 '17 20:01 FallingSnow

Can you provide an example to reproduce slow performance? Note that chromium-dev itself is unstable, so you have to test on the latest stable build to get more meaningful result.

saschanaz avatar Jan 04 '17 05:01 saschanaz

Got a test case done. If you use chromium, you will need to add --allow-file-access-from-files to your command line arguments.

libflif-performance-test-case.zip

In script.js you will see

decodeWebWorker(buffer);
// decodeSync(buffer);

Just switch between commenting each other and reload the page to see the difference.

FallingSnow avatar Jan 04 '17 19:01 FallingSnow

I ran some numbers. Both were set to scale to the image's native resolution of 5146x2935.

Web worker decode took 17053.045000000002 milliseconds.
Sync decode took 11826.785 milliseconds.
Web worker decode took 5226.260000000002 milliseconds longer.

When using poly-flif's scaling the results are much more dramatic.

FallingSnow avatar Jan 04 '17 21:01 FallingSnow

Using google-chrome-stable, same image, native resolution.

Web worker decode took 16493.545 milliseconds.
Sync decode took 12338.705000000002 milliseconds.
Web worker decode took 4154.8399999999965 milliseconds longer.

FallingSnow avatar Jan 05 '17 00:01 FallingSnow

Currently one key part is memory-growth compiler option. poly-flif currently gives -s TOTAL_MEMORY=100000000, which forces 100 MiB memory allocation from the start. On the other hand, libflif.js currently gives -s ALLOW_MEMORY_GROWTH=1, which allows starting with small memory space and growing if needed. However, the memory growth option limits compiler optimization which can cause slower speed.

WebAssembly will allow chasing two rabbits but the current asm.js can only chase one, smaller memory space or faster performance.

saschanaz avatar Jan 05 '17 04:01 saschanaz

The scaling decoder option is yet implemented, but you can still use it by manually inserting ~~decoder.setScale(scaleX, scaleY)~~decoder.setScale(scale) on the worker script if you want. I just opened #8 for this.

saschanaz avatar Jan 05 '17 04:01 saschanaz

Thanks for the responses. I'm not sure yet, but I think the scaling option will add enough of a performance boost for the time being. If you don't mind, I might ask you for advice in the future about memory growth. I was able to deduce that I can use decoder.setResize and decoder.setFit so that's awesome.

Is there a way I can have the web worker just decode once (the highest possible quality) rather than in waves? (In my experience each wave takes just as long as a single max quality decode)

BTW, correct syntax is decoder.setScale(scale) for anyone reading this in the future.

FallingSnow avatar Jan 05 '17 06:01 FallingSnow

You can decoder.setFirstCallbackQuality(10000) to get only single wave.

saschanaz avatar Jan 05 '17 06:01 saschanaz

Thank you.

FallingSnow avatar Jan 05 '17 07:01 FallingSnow

BTW,

(In my experience each wave takes just as long as a single max quality decode)

I can reproduce this and I doubt this is a problem on my code. The callback does not cause much delay so this is possibly a FLIF decoder problem.

saschanaz avatar Jan 05 '17 07:01 saschanaz

Well, I solved this issue by doing a decode where setFit was set to a much smaller size, this gives a quick decode and image to display. Then follow up with the correct setFit.

Basically the same thing you were trying to accomplish without the delay.

FallingSnow avatar Jan 05 '17 07:01 FallingSnow

Then follow up with the correct setFit.

You mean you call decodeWebWorker() multiple time with different setFit values?

saschanaz avatar Jan 05 '17 07:01 saschanaz

Yes.

Right now I'm trying to get the right setFit value for the final decode without knowing the image's dimensions beforehand. I basically want the opposite of --resize=WxH so that its lossy downscaled image to at least WxH instead of lossy downscaled image to fit inside WxH.

Sadly I'm still trying to figure out if this is possible without knowing the image's dimensions beforehand.

FallingSnow avatar Jan 05 '17 07:01 FallingSnow