-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Generated JS for blur algorithm is too slow #2845
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for the information. We're actively working on propagating type information so that we can generate better JavaScript code. Our new Dart-to-JavaScript compiler (dart2js) does try to use real indexers and raw JS primitives for + and * when we can tell it is safe to do so. If you could put a small benchmark that you care about somewhere and make it easy to run (maybe just a small version of what you've already posted), we'd be happy to try it out as part of tuning our compiler. Thanks again! Added Area-Dart2JS, Accepted labels. |
This comment was originally written by @bp74 Thank you very much for your reply, i'm happy to provide the benchmark. Here is the URL: It contains the dart-file, as well as the dart.js-file. |
Thanks, Bernhard! This is very useful. |
Changed the title to: "Generated JS for blur algorithm is too slow". |
This comment was originally written by @bp74 Updated numbers of the benchmark for Dart Build 8641: Chrome: 616ms, 571ms, 571ms Firefox 13: failed because of issue #2535 Well, i keep my faith in the Dart team to make in faaaaaast in the future :) |
cc @madsager. |
If we make our Uint8ClampedArray implement JavaScriptIndexingBehavior the numbers do improve a lot. It is still too slow, but at least we avoid using the blurFilter$bailout variant. --- a/lib/html/frog/html_frog.dart cc @rakudrama. |
Stephen landed his change (r8882) to make your benchmark not get stuck in the slow bailout version (basically allowing us to use [] on the Uint8ClampedArray). This should help a bit, but we still have more work ahead of us. |
This comment was originally written by @bp74 Thank you very much for the update. Yes this change makes a huge difference: Chrome : 157ms, 95ms, 95ms The code looks better too - most operations are native JS operations now, except the binary AND. Let me clarify that this issue is not about this particular function, it's just an example of code that does a lot of number crunching. Another example i have is a 2D-Matrix class which is frequently used in my graphics engine. Believe it or not, the "copyFromAndConcat" method below has 26(!!) type checkes for bailout code (if i write the code in a different way i can bring it down to 12 type checks). For a function that should be stupidly fast this is a high burden. Personally, i think the dart2js compiler should use type annotations much more to make good JS-code. Kasper gave a short response on Google+ about this topic and i know there are good reasons for not using the type annotations. Maybe in the end we will have a compiler switch to enable unsafe but fast JS-code!? class Matrix { BTW: the JS-code uses "getters" to access the fields of "copyMatrix" and "concatMatrix". Maybe the dart2js compiler can access the fields directly and not using a getter implementation in the future. PS: Sorry for being annoying, but JS-speed is the most important point for me. And don't get me wrong, i know you all do great work to make it better day after day. |
Thanks for the update, Bernhard! We will continue to try to improve the performance of the dart2js output and we really value your input. I'm sure we will be able to get rid of most of the 26 checks you mention. FWIW, I expect us to fix the binary AND issue tomorrow. |
It looks like we did manage to fix the AND issue. Next steps involve more type propagation and type inferencing (a few things have already landed). What's the current status seen from your side, Bernhard? It is a bit wrong to mark this as fixed (because it certainly still is work in progress), but we'll try to file more actionable issue going forward. Thanks again for the bug report, Bernhard. Added Fixed label. |
This comment was originally written by @bp74 Thanks Kasper, it's okay to close this issue. I know there is a lot of work going on with type propagation and type inferencing. Sure there is still a lot of room for improvements. In Chrome the code runs almost as fast as before when compiled with frog. In IE9 and Firefox the code is almost twice as fast with dart2js (very strange)! |
This comment was originally written by [email protected] FWIW, Nicolas just landed a change that may improve this even further (by getting rid of some bounds checks through value range propagation). |
This comment was originally written by @bp74 Thanks Kasper for the notice, i did a test with Build 13015 and the JavaScript code looks much(!) better now. All range checks are gone, only a few type checks remain. If i have a List<int> and all i do is write ints to the list, after a read from the list the type is still check if it is really a number. But i don't want to complain, it's great to see this fantastic progress in dart2js. Thanks to you and your team! |
This comment was originally written by @bp74 Wow, i'm speechless! With the latest build of Dart, the benchmark is more than twice as fast as before. You guys are geniuses :) I compared the previous version to the current version and only one small thing has changed - the fixed length of the Uint8ClampedArray [canvas.context2D.getImageData().data] is stored in a temporary variable in front of the loop! This is an awesome optimization. http://code.google.com/p/dart/source/detail?r=13224 First three runs: |
Included commits: ``` git log --format="%C(auto) %h %s" 0402c467547daa5886352cb315338ae54552d21c..0e657414a472e74ca5dd76ae0db50cc060251dec 0e657414 Show outdated and discontinued in listing in get (#2844) f842ae22 Include a deprecation notice in .packages (#2845) ``` Change-Id: Iaf03c5ea0380c16332ce65f2c4b3bf935873d30c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180841 Reviewed-by: Jonas Jensen <[email protected]> Commit-Queue: Sigurd Meldgaard <[email protected]>
This issue was originally filed by @bp74
Hello
I know you are early in the process and a lot of optimizations will come in the future, but please let me show you a small sample what could be done:
I wrote an image blur algorithm in Dart and here are the most important parts of the code:
List<int> buffer = new List<int>(1024);
...
if (y >= 0) dif += 6 * buffer[y & 1023] + buffer[(y - ry2) & 1023] - 4 * (buffer[(y - ry1) & 1023] + buffer[(y + ry1) & 1023]);
else if (y + ry1 >= 0) dif += 6 * buffer[y & 1023] - 4 * (buffer[(y - ry1) & 1023] + buffer[(y + ry1) & 1023]);
else if (y + ry2 >= 0) dif += 6 * buffer[y & 1023] - 4 * (buffer[(y + ry1) & 1023]);
else if (y + ry3 >= 0) dif -= 4 * buffer[(y + ry1) & 1023];
...
destinationData[offsetY] = (sum / weight).toInt();
Full sourcecode is here: http://code.google.com/p/dartflash/source/browse/trunk/library/filters/BlurFilter.dart
Here are the benchmarks (3 runs), thumbs up for Chrome!!
Chrome: 106ms 83ms 82ms
IE9: 1329ms 555ms 554ms
Firefox: 694ms 741ms 748ms
Now a take a look at the generated javascript, and i see this:
var buffer = new Array((1024));$add$ ($mul$ ((6), buffer.$index(y & (1023))), buffer.$index((y - ry2) & (1023))) - $mul$ ((4), ($add$ (buffer.$index((y - ry1) & (1023)), buffer.$index((y + ry1) & (1023))))));$mul$ ((6), buffer.$index(y & (1023))) - $mul$ ((4), ($add$ (buffer.$index((y - ry1) & (1023)), buffer.$index((y + ry1) & (1023))))));$mul$ ((6), buffer.$index(y & (1023))) - $mul$ ((4), (buffer.$index((y + ry1) & (1023)))));$mul$ ((4), buffer.$index((y + ry1) & (1023))));
...
if (y >= (0)) dif += (
else if (y + ry1 >= (0)) dif += (
else if (y + ry2 >= (0)) dif += (
else if (y + ry3 >= (0)) dif -= (
...
destinationData.$setindex(offsetY, (sum / weightY).toInt());
Well, that looks like you have replaced the index-setters to "$index" methods, which makes it very hard for the javascript-VM to make it really fast.
Now i "optimized" the JavaScript with 3 simple changes:
* i replaced the index-setters with real indexer.$add$ and $mul$ with "+" and "".
* i replaced
i replace the "num.toInt()" method with an inline version "num | 0".
Please look at the new benchmarks:
Chrome: 26ms, 15ms, 15ms
IE9: 278ms, 58ms, 58ms
Firefox: 236ms, 231ms, 231ms
That's a factor of 5 to 10 (firefox only 3). With only a very small change to the generated code.
As said in the beginning, i know that optimization is not a top priority right now and a lot of things will come in the future. I only want to show and remind how much impact such small code changes can have.
Thank you very much for your good work an Dart.
The text was updated successfully, but these errors were encountered: