| // Copyright (c) 2020, 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. | |
| // | |
| // Benchmark for UTF-8 encoding | |
| import 'dart:convert'; | |
| import 'package:benchmark_harness/benchmark_harness.dart'; | |
| import 'datext_latin1_10k.dart'; | |
| import 'entext_ascii_10k.dart'; | |
| import 'netext_3_10k.dart'; | |
| import 'rutext_2_10k.dart'; | |
| import 'sktext_10k.dart'; | |
| import 'zhtext_10k.dart'; | |
| class Utf8Encode extends BenchmarkBase { | |
| final String language; | |
| final String originalText; | |
| // Size is measured in number of runes rather than number of bytes. | |
| // This differs from the Utf8Decode benchmark, but runes are the input | |
| // to the encode function which makes them more natural than bytes here. | |
| final int size; | |
| List<String> benchmarkTextChunks = List.empty(growable: true); | |
| static String _makeName(String language, int size) { | |
| String name = 'Utf8Encode.$language.'; | |
| name += size >= 1000000 | |
| ? '${size ~/ 1000000}M' | |
| : size >= 1000 | |
| ? '${size ~/ 1000}k' | |
| : '$size'; | |
| return name; | |
| } | |
| Utf8Encode(this.language, this.originalText, this.size) | |
| : super(_makeName(language, size)); | |
| @override | |
| void setup() { | |
| final int nRunes = originalText.runes.toList().length; | |
| final String repeatedText = originalText * (size / nRunes).ceil(); | |
| final List<int> runes = repeatedText.runes.toList(); | |
| final int nChunks = (size < nRunes) ? (nRunes / size).floor() : 1; | |
| for (int i = 0; i < nChunks; i++) { | |
| final offset = i * size; | |
| benchmarkTextChunks.add( | |
| String.fromCharCodes(runes.sublist(offset, offset + size)), | |
| ); | |
| } | |
| } | |
| @override | |
| void run() { | |
| for (int i = 0; i < benchmarkTextChunks.length; i++) { | |
| final encoded = utf8.encode(benchmarkTextChunks[i]); | |
| if (encoded.length < benchmarkTextChunks[i].length) { | |
| throw 'There should be at least as many encoded bytes as runes'; | |
| } | |
| } | |
| } | |
| @override | |
| void exercise() { | |
| // Only a single run per measurement. | |
| run(); | |
| } | |
| @override | |
| double measure() { | |
| // Report time per input rune. | |
| return super.measure() / size / benchmarkTextChunks.length; | |
| } | |
| @override | |
| void report() { | |
| // Report time in nanoseconds. | |
| final double score = measure() * 1000.0; | |
| print('$name(RunTime): $score ns.'); | |
| } | |
| } | |
| void main(List<String> args) { | |
| const texts = {'en': en, 'da': da, 'sk': sk, 'ru': ru, 'ne': ne, 'zh': zh}; | |
| final benchmarks = [ | |
| for (int size in [10, 10000, 10000000]) | |
| for (String language in texts.keys) | |
| () => Utf8Encode(language, texts[language]!, size), | |
| ]; | |
| for (var bm in benchmarks) { | |
| bm().report(); | |
| } | |
| } |