производительность кода дротика в браузере против виртуальной машины - PullRequest
0 голосов
/ 03 октября 2019

Я был удивлен производительностью моего кода Dart в браузере по сравнению с виртуальной машиной Dart. Вот простой пример, который воспроизводит проблему.

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}');
  });

Если я запускаю этот код с помощью dart, я получаю где-то около 140 миллисекунд. Если я запускаю тот же код, что и тест браузера, с pub run test -p "chrome" ... я получаю время около 8000 миллисекунд.

Я готов дождаться расчета 0,1 с, но ждать что-то в браузере 8 с, нет - в принципе это невозможно. Когда я перехожу в режим релиза, производительность в браузере улучшается, но все равно она в 10 раз медленнее.

Я что-то упустил? Нужно ли избегать каких-либо расчетов в браузере?

Спасибо, Тони

1 Ответ

0 голосов
/ 03 октября 2019

Интересно, насколько это медленно.

Соответствующий код 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));
}());

работает всего за ~ 20 миллисекунд.

Итак, похожеDart каким-то образом запускает «медленный режим» для своего сгенерированного Javascript.

Если вы посмотрите на сгенерированный код, он содержит:

  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()));
  }

Вы можете попытаться настроить этот код, но большойстоимость исходит от C.JSArray_methods.$indexSet(x, j, t1 + i);. Если вы измените это значение на x[j] = t1 + i;, время упадет до нескольких сотен миллисекунд. Итак, это проблема текущего кода.

(Вы можете немного улучшить производительность, ~ 20%, сделав x List<num> вместо List<double>. Я понятия не имею, почемуэто имеет значение, сгенерированный код почти такой же, закрытие add использует checkDouble для проверки типа вместо checkNum, но они имеют абсолютно одинаковое тело).

Вы не 'нужно избегать любых вычислений в браузере. Возможно, вам придется немного оптимизировать такие медленные случаи (или сообщить об этом разработчикам компилятора, потому что это, вероятно, может быть распознано и оптимизировано, но пока это не так). Например, вы можете изменить свой список x парных чисел на Float64List с dart:typed_data:

var x = Float64List.fromList([for (var i = 0; i < n; i++) rand.nextDouble()]);

Тогда скорость значительно возрастет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...