Is it really that bad in Dart?

81 views
Skip to first unread message

Andrew Mezoni

unread,
Jun 6, 2021, 12:05:04 PM6/6/21
to Dart Misc
The test that blows my brain.

AOT mode.
In JIT mode, everything is not very good either.
Nightmare.
Are the closures unusable? 
Even without the captured content?
I can imagine how this can slow down the execution of asynchronous operations.
The same simple operation.

Time passed: 23.366, Test 'good': 9.205 ms
Time passed: 23.376, Test 'bad': 223.224 ms
Time passed: 23.599, Test 'ugly': 782.464 ms
Time passed: 24.382, Test 'good': 9.086 ms
Time passed: 24.392, Test 'bad': 221.495 ms
Time passed: 24.614, Test 'ugly': 785.416 ms
Time passed: 25.400, Test 'good': 9.022 ms
Time passed: 25.409, Test 'bad': 220.241 ms
Time passed: 25.630, Test 'ugly': 785.412 ms
Time passed: 26.416, Test 'good': 9.093 ms
Time passed: 26.425, Test 'bad': 221.584 ms
Time passed: 26.647, Test 'ugly': 789.252 ms
Time passed: 27.437, Test 'good': 9.0 ms
Time passed: 27.446, Test 'bad': 220.065 ms
Time passed: 27.666, Test 'ugly': 784.87 ms
Time passed: 28.452, Test 'good': 9.215 ms
Time passed: 28.461, Test 'bad': 220.894 ms
Time passed: 28.682, Test 'ugly': 784.547 ms
Time passed: 29.467, Test 'good': 9.063 ms
Time passed: 29.477, Test 'bad': 221.141 ms

Source code.
Iteration 10000000 times.

======
void main() {
  final count = 10000000;
  final names = ['good', 'bad', 'ugly'];
  final tests = [_test1, _test2, _test3];
  final sw = Stopwatch();
  var repeat = 150;
  sw.start();
  while (repeat-- > 0) {
    for (var i = 0; i < tests.length; i++) {
      final name = names[i];
      final test = tests[i];
      final seconds = (sw.elapsedMilliseconds / 1000).toStringAsFixed(3);
      final title = 'Time passed: $seconds, Test \'$name\'';
      _measure(title, 1, () => test(count));
    }
  }
}

void _measure(String name, int count, Function() f) {
  final sw = Stopwatch();
  sw.start();
  for (var i = 0; i < count; i++) {
    f();
  }
  sw.stop();
  final time = sw.elapsedMicroseconds / 1000;
  print('$name: $time ms');
}

void _test1(int count) {
  final p1 = P1<int>(T1(0));
  for (var i = 0; i < count; i++) {
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
    p1.foo(0);
  }
}

void _test2(int count) {
  final p2 = P2<int>((x) => x == 0);
  for (var i = 0; i < count; i++) {
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
  }
}

void _test3(int count) {
  final p2 = P2<int>(isX);
  for (var i = 0; i < count; i++) {
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
    p2.foo(0);
  }
}

bool isX<T>(T x) => x == 0;

class P1<T> {
  final T1<T> t;

  P1(this.t);

  bool foo(T x) => t.f(x);
}

class P2<T> {
  bool Function(T) f;

  P2(this.f);

  bool foo(T x) => f(x);
}

class T1<T> {
  final x;

  T1(this.x);

  bool f(T x) => this.x == x;
}

======

As the saying goes, "comments are superfluous."
Как говорится, "комментарии излишни".

Vijay Menon

unread,
Jun 7, 2021, 9:46:06 AM6/7/21
to General Dart Discussion

In the "good" case here, it appears that (a) the call to `foo` is inlined and (b) the inlined body of foo is eliminated as dead code.  In other words, the baseline becomes an empty loop.  A loop of closure invocations is indeed slower than an empty loop.  :-)

You can annotate all the foo declaration sites with `@pragma('vm:never-inline')` to suppress inlining.  

--
For more ways to connect visit https://dart.dev/community
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
To view this discussion on the web visit https://groups.google.com/a/dartlang.org/d/msgid/misc/3623eb61-3203-47c0-8a70-7c817445754cn%40dartlang.org.

Andrew Mezoni

unread,
Jun 7, 2021, 11:15:27 AM6/7/21
to Dart Misc, v...@google.com
OK. Thank you.
Is it really impossible to compile an expression function into inline code if it assigned to final variable?
After all, this is just one single expression that is enclosed in a function. Lambda expression.

понедельник, 7 июня 2021 г. в 18:46:06 UTC+5, v...@google.com:
Reply all
Reply to author
Forward
0 new messages