[英]performance of dart code in browser vs. VM
I was surprised by the performance of my Dart code in the browser vs. the Dart VM.我对浏览器中的 Dart 代码与 Dart VM 的性能对比感到惊讶。 Here is a simple example that reproduces the issue.这是一个重现该问题的简单示例。
test('speed test', () {
var n = 10000;
var rand = Random(0);
var x = List.generate(n, (i) => rand.nextDouble());
var res = <num>[];
var sw = Stopwatch()..start();
for (int i=0; i<1000; i++) {
for (int j=0; j<n; j++) {
x[j] += i;
}
res.add(x.reduce((a, b) => a + b));
}
sw.stop();
print('Milliseconds: ${sw.elapsedMilliseconds}');
});
If I run this code with dart, I get somewhere around 140 milliseconds.如果我用 dart 运行这段代码,我会得到大约 140 毫秒。 If I run the same code as a browser test with pub run test -p "chrome"
... I get times around 8000 milliseconds.如果我使用pub run test -p "chrome"
与浏览器测试相同的代码......我会得到大约 8000 毫秒的时间。
I am willing to wait for a 0.1 s calculation, but to wait 8 s for something in the browser, no -- it is basically unusable.我愿意等待 0.1 秒的计算,但在浏览器中等待 8 秒,不——它基本上无法使用。 When I go in release mode, the performance in browser improve but it's still 10x slower.当我在发布模式下 go 时,浏览器的性能有所提高,但仍然慢了 10 倍。
Am I missing something?我错过了什么吗? Do I have to avoid any calculations in the browser?我是否必须避免在浏览器中进行任何计算?
Thanks, Tony谢谢,托尼
It's interesting how slow this is.有趣的是这有多慢。
The corresponding JavaScript code:对应的JavaScript代码:
(function() {
"use strict";
var n = 10000;
var x = [];
var res = [];
for (var i = 0; i < n; i++) x.push(Math.random());
var t0 = Date.now();
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < n; j++) {
x[j] += i;
}
res.push(x.reduce((a, b) => a + b));
}
var t1 = Date.now();
console.log("Milliseconds: " + (t1 - t0));
}());
runs in as little as ~20 milliseconds.只需约 20 毫秒即可运行。
So, it looks like Dart is somehow triggering "slow mode" for its generated Javascript.因此,看起来 Dart 以某种方式为其生成的 Javascript 触发了“慢速模式”。
If you look at the generated code, it contains:如果您查看生成的代码,它包含:
for (i = 0; i < 1000; ++i) {
for (j = 0; j < 10000; ++j) {
if (j >= x.length)
return H.ioore(x, j);
t1 = x[j];
if (typeof t1 !== "number")
return t1.$add();
C.JSArray_methods.$indexSet(x, j, t1 + i);
}
C.JSArray_methods.add$1(res, C.JSArray_methods.reduce$1(x, new A.main_closure0()));
}
You can try to tweak this code, but the big cost comes from C.JSArray_methods.$indexSet(x, j, t1 + i);
您可以尝试调整此代码,但最大的成本来自C.JSArray_methods.$indexSet(x, j, t1 + i);
. . If you change that to x[j] = t1 + i;
如果将其更改为x[j] = t1 + i;
, the time drops to a few hundred milliseconds. ,时间下降到几百毫秒。 So, this is the problem with the current code.所以,这是当前代码的问题。
(You can improve performance a little, ~20%, by making x
a List<num>
instead of a List<double>
. I have no idea why that makes a difference, the generated code is almost the same, the add
closure uses checkDouble
to check the type instead of checkNum
, but they have exactly the same body). (您可以通过使x
成为List<num>
而不是List<double>
来提高性能约 20%。我不知道为什么会有所不同,生成的代码几乎相同, add
闭包使用checkDouble
来检查类型而不是checkNum
,但它们具有完全相同的主体)。
You don't have to avoid any computation in the browser.您不必避免在浏览器中进行任何计算。 You may have to optimize a little for slow cases like this (or report them to the compiler developers, because this probably can be recognized and optimized, it just fails to be so for now).您可能需要针对这种缓慢的情况进行一些优化(或将它们报告给编译器开发人员,因为这可能可以被识别和优化,但目前还不能这样)。 For example, you can change your list x
of doubles to a Float64List
from dart:typed_data
:例如,您可以将双精度列表x
从dart:typed_data
Float64List
var x = Float64List.fromList([for (var i = 0; i < n; i++) rand.nextDouble()]);
Then speed increases quite a lot.然后速度增加了很多。
The Dart tracking issue for this is https://github.com/dart-lang/sdk/issues/38705 . Dart 跟踪问题是https://github.com/dart-lang/sdk/issues/38705 。
The performance of this kind of code has recently improved considerably and is much closer to the Dart VM.此类代码的性能最近有了显着提高,并且更接近 Dart VM。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.