90997b96b0
This stops string operator == from being inlined in the VM.
When not inlining it uses an intrinsic which is faster.
For situations where String.== calls weren't inlined before this should
be a no-op.
For situations where String.== calls were inlined before this should
make it use the intrinsic instead, making it faster.
In a microbenchmark (see below) runtimes go to
"String length" # iterations New runtime
1 10000000 63.68%
10 1000000 61.92%
100 100000 60.70%
1000 10000 74.48%
10000 1000 73.37%
100000 100 100.31%
i.e. for many iterations (though seemingly fewer than one might expect)
the time it takes to compare strings is now between 60-75% of what it
was before (i.e. something like 25-40% faster).
Raw data:
Before:
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1 10000000
833
837
834
838
829
828
818
834
816
828
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10 1000000
487
452
452
457
458
452
452
455
454
453
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100 100000
438
422
423
421
420
421
424
420
420
420
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1000 10000
330
331
333
330
414
330
332
335
413
331
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10000 1000
342
387
341
340
341
374
342
341
341
377
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100000 100
247
248
249
248
279
284
249
271
250
263
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 1 10000000
670
669
676
669
670
670
669
673
670
670
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 10 1000000
553
554
558
553
552
555
552
553
555
551
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 100 100000
502
504
504
501
502
503
503
505
503
506
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 1000 10000
496
495
496
494
494
495
494
494
495
494
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 10000 1000
494
502
494
495
494
495
494
499
499
494
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 100000 100
572
493
494
495
495
494
497
495
494
494
With change:
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1 10000000
532
534
532
528
532
526
523
519
523
533
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10 1000000
287
291
283
283
280
280
279
281
280
287
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100 100000
270
257
254
255
255
255
255
255
254
257
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1000 10000
248
249
251
287
248
262
248
273
248
277
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10000 1000
268
281
247
247
247
282
251
247
247
270
$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100000 100
248
277
256
286
248
275
247
248
254
257
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 1 10000000
490
488
488
481
493
498
484
498
491
494
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 10 1000000
202
202
235
226
215
206
203
232
208
202
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 100 100000
173
172
184
194
203
172
177
173
192
172
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 1000 10000
166
169
178
180
176
169
200
198
197
198
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 10000 1000
167
180
195
195
187
180
176
196
173
195
$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 100000 100
190
171
173
167
166
172
166
171
166
170
where
$ type runxtimes
runxtimes is a function
runxtimes ()
{
number=$1;
shift;
for i in `seq $number`;
do
$@;
done
}
and `stringCompareSpeed.dart` is
```
late final String long;
late final String long1;
late final String long2;
void main(List<String> args) {
if (args.length != 2) throw "expect 2 arguments: <string-length> <iteration count>";
final int length = int.parse(args[0]);
final int iterations = int.parse(args[1]);
long = "foo" * length;
long1 = long + "1" + long;
long2 = long + "2" + long;
final String localLong1 = long + "1" + long;
final String localLong2 = long + "2" + long;
for (int i = 0; i < iterations; i++) {
if (compare(localLong1, localLong2) != 105) {
throw "got ${compare(localLong1, localLong2)}";
}
}
Stopwatch stopwatch = new Stopwatch()..start();
for (int i = 0; i < iterations; i++) {
if (compare(localLong1, localLong2) != 105) {
throw "got ${compare(localLong1, localLong2)}";
}
}
print("${stopwatch.elapsedMilliseconds}");
}
int compare(String localLong1, String localLong2) {
int result = 0;
if (long1 == localLong1) {
result |= 0x01;
}
if (long1 != localLong1) {
result |= 0x02;
}
if (long1 == localLong2) {
result |= 0x04;
}
if (long1 != localLong2) {
result |= 0x08;
}
if (long2 == localLong1) {
result |= 0x10;
}
if (long2 != localLong1) {
result |= 0x20;
}
if (long2 == localLong2) {
result |= 0x40;
}
if (long2 != localLong2) {
result |= 0x80;
}
return result;
}
```
TEST=Existing tests, benchmarked here.
Change-Id: Iecf6c228b3040db0e0b403241ea6380dfed6dbb7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233100
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>