Home > Mobile >  Is Dart `startsWith` mega slower than the same method in JavaScript?
Is Dart `startsWith` mega slower than the same method in JavaScript?

Time:06-08

A link to a benchmark test in DartPad that executes Dart code, compiling it to JavaScript.

https://dartpad.dev/?id=e110b8bc0ad72298517fb286d21bccdc

Test code is simple

void _test1(int count) {
  final source = ' 123 ';
  for (var i = 0; i < count; i  ) {
    var x = source.startsWith('123', 1);
  }
}

void _test2(int count) {
  final source = ' 123 ';
  for (var i = 0; i < count; i  ) {
    var ok = source.codeUnitAt(1) == 0x31 &&
        source.codeUnitAt(2) == 0x32 &&
        source.codeUnitAt(3) == 0x33;
    var x = ok;
  }
}

Results for JavaScript:

Time passed: 0.000, Test 'startsWith': 105.4 ms
Time passed: 0.106, Test 'codeUnitAt': 87.8 ms
Time passed: 0.194, Test 'startsWith': 86.7 ms
Time passed: 0.280, Test 'codeUnitAt': 87.101 ms
Time passed: 0.368, Test 'startsWith': 87 ms
Time passed: 0.455, Test 'codeUnitAt': 87.2 ms
Time passed: 0.542, Test 'startsWith': 86.699 ms
Time passed: 0.629, Test 'codeUnitAt': 85.6 ms
Time passed: 0.715, Test 'startsWith': 85.7 ms
Time passed: 0.801, Test 'codeUnitAt': 86.6 ms

No questions.

Results for Dart (JIT):

Time passed: 0.000, Test 'startsWith': 837.2 ms
Time passed: 0.842, Test 'codeUnitAt': 125.094 ms
Time passed: 0.968, Test 'startsWith': 924.482 ms
Time passed: 1.892, Test 'codeUnitAt': 131.861 ms
Time passed: 2.024, Test 'startsWith': 736.603 ms
Time passed: 2.761, Test 'codeUnitAt': 76.636 ms
Time passed: 2.838, Test 'startsWith': 792.341 ms
Time passed: 3.631, Test 'codeUnitAt': 61.732 ms
Time passed: 3.693, Test 'startsWith': 721.816 ms
Time passed: 4.415, Test 'codeUnitAt': 73.93 ms

85.7 ms vs 721.816 ms

These results raise a huge number of questions and the main one is: "Why startsWith is so slow compared to JavaScript?What is the reason?"

CodePudding user response:

Your test shows that Google Chrome are great at detecting functions that does nothing and/or functions that does end with the same result given the same input value.

It is in general quite hard to do this kind of benchmark testing where we want some optimization being done but not too many since we have the risk of optimizing away the thing we wanted to test.

E.g. your inner for-loop are just looping though the same data and saves the result in a local non-used variable. The more clever the compiler is, the more it ends up getting rid of.

So the question quickly becomes: "what do we actual want to test here?"

The current test shows for sure that Dart VM are worse than Chrome when it comes to optimize the functions down to do basically nothing.

If we instead changes the test so we are enforcing both Chrome and Dart VM to be less predictable (and therefore make less optimizations), we could try something like this:

Random _rnd = Random();

void _test1(int count) {
  final source = ' 123 ';
  var x = false;
  for (var i = 0; i < count; i  ) {
    x = source.startsWith('123', _rnd.nextBool() ? 0 : 1);
  }
  print(x);
}

Then Chrome returns (I have removed the codeUnitAt results):

true
Time passed: 0.000, Test 'startsWith': 3531 ms
false
Time passed: 3.531, Test 'startsWith': 3498 ms
false
Time passed: 7.029, Test 'startsWith': 3289 ms
true
Time passed: 10.319, Test 'startsWith': 3316 ms
true
Time passed: 13.635, Test 'startsWith': 3266 ms

And Dart VM:

false
Time passed: 0.000, Test 'startsWith': 2119 ms
false
Time passed: 2.121, Test 'startsWith': 1901 ms
true
Time passed: 4.023, Test 'startsWith': 2012 ms
true
Time passed: 6.035, Test 'startsWith': 1998 ms
false
Time passed: 8.033, Test 'startsWith': 2009 ms

And Dart compiled to an exe file:

false
Time passed: 0.000, Test 'startsWith': 1364 ms
true
Time passed: 1.365, Test 'startsWith': 1360 ms
true
Time passed: 2.726, Test 'startsWith': 1369 ms
false
Time passed: 4.095, Test 'startsWith': 1355 ms
false
Time passed: 5.451, Test 'startsWith': 1362 ms

Similar thing can also be seen if we change the codeUnitAt test.

  • Related