blob: fd1170b06364ef4e20c6f20fa0edaea3fc9fc9e8 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:characters/src/grapheme_clusters/breaks.dart';
import 'package:characters/src/grapheme_clusters/constants.dart';
import '../test/src/text_samples.dart';
import '../test/src/unicode_grapheme_tests.dart';
import '../test/src/various_tests.dart';
// Low-level benchmark of the grapheme cluster step functions.
void main(List<String> args) {
var count = 5;
if (args.isNotEmpty) {
count = int.parse(args[0]);
}
var gcsf = 0;
var gcsb = 0;
var text = genesis +
hangul +
genesis +
diacretics +
recJoin(splitTests) +
recJoin(emojis) +
recJoin(zalgo);
var codeUnits = text.length;
var codePoints = text.runes.length;
for (var i = 0; i < count; i++) {
gcsf = benchForward(text, i, codePoints, codeUnits);
gcsb = benchBackward(text, i, codePoints, codeUnits);
}
print('gc: Grapheme Clusters, cp: Code Points, cu: Code Units.');
if (gcsf != gcsb) {
print('ERROR: Did not count the same number of grapheme clusters: '
'$gcsf forward vs. $gcsb backward.');
} else {
print('Total: $gcsf gc, $codePoints cp, $codeUnits cu');
print('Avg ${(codePoints / gcsf).toStringAsFixed(3)} cp/gc');
print('Avg ${(codeUnits / gcsf).toStringAsFixed(3)} cu/gc');
}
}
String recJoin(Iterable<List<String>> texts) =>
texts.map((x) => x.join('')).join('\n');
int benchForward(String text, int i, int cp, int cu) {
var n = 0;
var gc = 0;
var e = 0;
var sw = Stopwatch()..start();
do {
var breaks = Breaks(text, 0, text.length, stateSoTNoBreak);
while (breaks.nextBreak() >= 0) {
gc++;
}
e = sw.elapsedMilliseconds;
n++;
} while (e < 2000);
print('Forward #$i: ${(gc / e).round()} gc/ms, '
'${(n * cp / e).round()} cp/ms, '
'${(n * cu / e).round()} cu/ms, '
'$n rounds');
return gc ~/ n;
}
int benchBackward(String text, int i, int cp, int cu) {
var n = 0;
var gc = 0;
var e = 0;
var sw = Stopwatch()..start();
do {
var breaks = BackBreaks(text, text.length, 0, stateEoTNoBreak);
while (breaks.nextBreak() >= 0) {
gc++;
}
e = sw.elapsedMilliseconds;
n++;
} while (e < 2000);
print('Backward #$i: ${(gc / e).round()} gc/ms, '
'${(n * cp / e).round()} cp/ms, '
'${(n * cu / e).round()} cu/ms, '
'$n rounds');
return gc ~/ n;
}