mirror of
https://github.com/dart-lang/sdk
synced 2024-07-01 07:14:29 +00:00
Fix analysis issues in benchmarks/ directory
Now that I'm able to open the entire SDK in VSC, I'm fixing some of the analysis issues in various files (carefully) without changing their meaning. In this case, I removed unnecessary imports from benchmarks. In regexp_benchmark I ignored one warning which likely would have changed the behavior of the code. BUG=https://github.com/dart-lang/sdk/issues/52419 Change-Id: I9a195a4e45121313bd9f065f2579a165c3fec05b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/303901 Auto-Submit: Eric Seidel <eric@shorebird.dev> Reviewed-by: William Hesse <whesse@google.com> Commit-Queue: William Hesse <whesse@google.com>
This commit is contained in:
parent
987c7a7c35
commit
4c20cedd30
|
@ -7,14 +7,14 @@ import 'dart:isolate';
|
|||
import 'json_benchmark.dart';
|
||||
import 'latency.dart';
|
||||
|
||||
main() async {
|
||||
Future<void> main() async {
|
||||
// Start GC pressure from helper isolate.
|
||||
final exitPort = ReceivePort();
|
||||
final exitFuture = exitPort.first;
|
||||
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
|
||||
|
||||
// Measure event loop latency.
|
||||
const tickDuration = const Duration(milliseconds: 1);
|
||||
const tickDuration = Duration(milliseconds: 1);
|
||||
const numberOfTicks = 8 * 1000; // min 8 seconds.
|
||||
final EventLoopLatencyStats stats =
|
||||
await measureEventLoopLatency(tickDuration, numberOfTicks);
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// 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 'dart:math';
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
class JsonRoundTripBenchmark {
|
||||
void run() {
|
||||
|
|
|
@ -9,14 +9,14 @@ import 'dart:isolate';
|
|||
import 'json_benchmark.dart';
|
||||
import 'latency.dart';
|
||||
|
||||
main() async {
|
||||
Future<void> main() async {
|
||||
// Start GC pressure from helper isolate.
|
||||
final exitPort = ReceivePort();
|
||||
final exitFuture = exitPort.first;
|
||||
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
|
||||
|
||||
// Measure event loop latency.
|
||||
const tickDuration = const Duration(milliseconds: 1);
|
||||
const tickDuration = Duration(milliseconds: 1);
|
||||
const numberOfTicks = 8 * 1000; // min 8 seconds.
|
||||
final EventLoopLatencyStats stats =
|
||||
await measureEventLoopLatency(tickDuration, numberOfTicks);
|
||||
|
|
|
@ -7,14 +7,14 @@ import 'dart:isolate';
|
|||
import 'json_benchmark.dart';
|
||||
import 'latency.dart';
|
||||
|
||||
main() async {
|
||||
Future<void> main() async {
|
||||
// Start GC pressure from helper isolate.
|
||||
final exitPort = ReceivePort();
|
||||
final exitFuture = exitPort.first;
|
||||
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
|
||||
|
||||
// Measure event loop latency.
|
||||
const tickDuration = const Duration(milliseconds: 1);
|
||||
const tickDuration = Duration(milliseconds: 1);
|
||||
const numberOfTicks = 8 * 1000; // min 8 seconds.
|
||||
final EventLoopLatencyStats stats =
|
||||
await measureEventLoopLatency(tickDuration, numberOfTicks);
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// 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 'dart:math';
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
class JsonRoundTripBenchmark {
|
||||
void run() {
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'regexp_benchmark.dart';
|
||||
import 'latency.dart';
|
||||
import 'regexp_benchmark.dart';
|
||||
|
||||
main() async {
|
||||
Future<void> main() async {
|
||||
final exitPort = ReceivePort();
|
||||
final exitFuture = exitPort.first;
|
||||
final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
|
||||
|
||||
// Measure event loop latency.
|
||||
const tickDuration = const Duration(milliseconds: 1);
|
||||
const tickDuration = Duration(milliseconds: 1);
|
||||
const numberOfTicks = 8 * 1000; // min 8 seconds.
|
||||
final EventLoopLatencyStats stats =
|
||||
await measureEventLoopLatency(tickDuration, numberOfTicks);
|
||||
|
|
|
@ -2,12 +2,10 @@
|
|||
// 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 'dart:math';
|
||||
import 'dart:convert';
|
||||
|
||||
class RegexpBenchmark {
|
||||
void run() {
|
||||
final re = RegExp(r'(x+)*y');
|
||||
// ignore: prefer_interpolation_to_compose_strings
|
||||
final s = 'x' * 26 + '';
|
||||
re.allMatches(s).iterator.moveNext();
|
||||
}
|
||||
|
|
|
@ -80,11 +80,11 @@ class D<T> {
|
|||
}
|
||||
''');
|
||||
|
||||
final maxCount = instantiateCounts.reduce(((v, e) => max(v, e)));
|
||||
final maxCount = instantiateCounts.reduce(max);
|
||||
for (int i = 0; i < maxCount; i++) {
|
||||
output.write('''
|
||||
|
||||
class C${i} {}
|
||||
class C$i {}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
// 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 'dart:collection';
|
||||
// Benchmark for https://github.com/dart-lang/sdk/issues/48641.
|
||||
//
|
||||
// Measures the average time needed for a lookup in Sets of integers.
|
||||
|
||||
import 'dart:math';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||
|
||||
class SetBenchmark extends BenchmarkBase {
|
||||
|
@ -30,13 +31,13 @@ void main() {
|
|||
final randomList = List<int>.generate(14790, (_) => r.nextInt(1 << 31));
|
||||
|
||||
final benchmarks = [
|
||||
() => SetBenchmark("IntegerSetLookup.DefaultHashSet", {...list}),
|
||||
() => SetBenchmark('IntegerSetLookup.DefaultHashSet', {...list}),
|
||||
() =>
|
||||
SetBenchmark("IntegerSetLookup.HashSet", HashSet<int>()..addAll(list)),
|
||||
SetBenchmark('IntegerSetLookup.HashSet', HashSet<int>()..addAll(list)),
|
||||
() =>
|
||||
SetBenchmark("IntegerSetLookup.DefaultHashSet_Random", {...randomList}),
|
||||
SetBenchmark('IntegerSetLookup.DefaultHashSet_Random', {...randomList}),
|
||||
() => SetBenchmark(
|
||||
"IntegerSetLookup.HashSet_Random", HashSet<int>()..addAll(randomList)),
|
||||
'IntegerSetLookup.HashSet_Random', HashSet<int>()..addAll(randomList)),
|
||||
];
|
||||
for (final benchmark in benchmarks) {
|
||||
benchmark().report();
|
||||
|
|
|
@ -49,7 +49,7 @@ class SendReceiveHelper {
|
|||
outbox.send(null);
|
||||
await workerExitedPort.first;
|
||||
workerExitedPort.close();
|
||||
inbox.cancel();
|
||||
await inbox.cancel();
|
||||
}
|
||||
|
||||
// Send regexp to worker, get one back, repeat few times.
|
||||
|
@ -78,7 +78,7 @@ Future<void> isolate(SendPort sendPort) async {
|
|||
break;
|
||||
}
|
||||
// use RegExp to ensure it is compiled
|
||||
RegExp re = received as RegExp;
|
||||
final RegExp re = received as RegExp;
|
||||
re.firstMatch('h' * 1000);
|
||||
// send the RegExp
|
||||
sendPort.send(re);
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
// via exit/send.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'latency.dart';
|
||||
|
||||
main() async {
|
||||
Future<void> main() async {
|
||||
final statsFuture =
|
||||
measureEventLoopLatency(const Duration(milliseconds: 1), 4000, work: () {
|
||||
// Every 1 ms we allocate some objects which may trigger GC some time.
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:typed_data';
|
||||
|
||||
|
|
|
@ -8,10 +8,11 @@ import 'dart:io';
|
|||
import 'dart:isolate';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import '../../../pkg/vm/bin/gen_kernel.dart' as gen_kernel;
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
import 'package:vm_service/vm_service_io.dart' as vm_service_io;
|
||||
|
||||
import '../../../pkg/vm/bin/gen_kernel.dart' as gen_kernel;
|
||||
|
||||
const String compilerIsolateName = 'isolate-compiler';
|
||||
|
||||
class Result {
|
||||
|
|
|
@ -264,12 +264,12 @@ void main() {
|
|||
setNativeResolverForTest(getRootLibraryUrl());
|
||||
|
||||
final benchmarks = [
|
||||
() => Uint8x01(),
|
||||
() => Int64x20(),
|
||||
() => Doublex01(),
|
||||
() => Doublex20(),
|
||||
() => Handlex01(),
|
||||
() => Handlex20(),
|
||||
Uint8x01.new,
|
||||
Int64x20.new,
|
||||
Doublex01.new,
|
||||
Doublex20.new,
|
||||
Handlex01.new,
|
||||
Handlex20.new,
|
||||
];
|
||||
for (final benchmark in benchmarks) {
|
||||
benchmark().report();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// Benchmark for `Object.hash` and `Object.hashAll`.
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||
|
||||
int get nextHash => Random().nextInt(0x20000000);
|
||||
|
@ -134,11 +135,11 @@ void main() {
|
|||
generalUses();
|
||||
|
||||
final benchmarks = [
|
||||
() => BenchmarkNode5Hash(),
|
||||
() => BenchmarkNode5Manual(),
|
||||
() => BenchmarkNode5List(),
|
||||
() => BenchmarkNode5HashHashAll(),
|
||||
() => BenchmarkNode5ManualHashAll(),
|
||||
BenchmarkNode5Hash.new,
|
||||
BenchmarkNode5Manual.new,
|
||||
BenchmarkNode5List.new,
|
||||
BenchmarkNode5HashHashAll.new,
|
||||
BenchmarkNode5ManualHashAll.new,
|
||||
];
|
||||
|
||||
// Warmup all benchmarks so that JIT compilers see full polymorphism before
|
||||
|
|
|
@ -15,8 +15,8 @@ import '../../BigIntParsePrint/dart/BigIntParsePrint.dart'
|
|||
as lib_BigIntParsePrint;
|
||||
import '../../Iterators/dart/Iterators.dart' as lib_Iterators;
|
||||
import '../../ListCopy/dart/ListCopy.dart' as lib_ListCopy;
|
||||
import '../../MapCopy/dart/MapCopy.dart' as lib_MapCopy;
|
||||
import '../../MD5/dart/md5.dart' as lib_MD5;
|
||||
import '../../MapCopy/dart/MapCopy.dart' as lib_MapCopy;
|
||||
import '../../RecordCollections/dart/RecordCollections.dart'
|
||||
as lib_RecordCollections;
|
||||
import '../../RuntimeType/dart/RuntimeType.dart' as lib_RuntimeType;
|
||||
|
|
|
@ -15,8 +15,8 @@ import '../../BigIntParsePrint/dart/BigIntParsePrint.dart'
|
|||
deferred as lib_BigIntParsePrint;
|
||||
import '../../Iterators/dart/Iterators.dart' deferred as lib_Iterators;
|
||||
import '../../ListCopy/dart/ListCopy.dart' deferred as lib_ListCopy;
|
||||
import '../../MapCopy/dart/MapCopy.dart' deferred as lib_MapCopy;
|
||||
import '../../MD5/dart/md5.dart' deferred as lib_MD5;
|
||||
import '../../MapCopy/dart/MapCopy.dart' deferred as lib_MapCopy;
|
||||
import '../../RecordCollections/dart/RecordCollections.dart'
|
||||
deferred as lib_RecordCollections;
|
||||
import '../../RuntimeType/dart/RuntimeType.dart' deferred as lib_RuntimeType;
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:collection';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||
|
||||
import 'sound_splay_tree.dart';
|
||||
|
||||
List<int> sieve(List<int> initialCandidates) {
|
||||
|
@ -85,7 +86,7 @@ void busyWork() {
|
|||
exercise(M2.values);
|
||||
}
|
||||
|
||||
main() {
|
||||
void main() {
|
||||
final benchmarks = [
|
||||
Base(sieve, 'CollectionSieves-SplayTreeSet-removeLoop'),
|
||||
Base(sieveSound, 'CollectionSieves-SoundSplayTreeSet-removeLoop'),
|
||||
|
@ -105,6 +106,7 @@ class Base extends BenchmarkBase {
|
|||
final algorithm;
|
||||
Base(this.algorithm, String name) : super(name);
|
||||
static final input = range(2, 5000);
|
||||
@override
|
||||
void run() {
|
||||
final primes = algorithm(input);
|
||||
if (primes.length != 669) throw 'Wrong result for $name: ${primes.length}';
|
||||
|
|
|
@ -7,17 +7,18 @@ abstract class EfficientLengthIterable<T> extends Iterable<T> {
|
|||
///
|
||||
/// This is an efficient operation that doesn't require iterating through
|
||||
/// the elements.
|
||||
@override
|
||||
int get length;
|
||||
}
|
||||
|
||||
/// Creates errors throw by [Iterable] when the element count is wrong.
|
||||
abstract class IterableElementError {
|
||||
/// Error thrown by, e.g., [Iterable.first] when there is no result.
|
||||
static StateError noElement() => StateError("No element");
|
||||
static StateError noElement() => StateError('No element');
|
||||
|
||||
/// Error thrown by, e.g., [Iterable.single] if there are too many results.
|
||||
static StateError tooMany() => StateError("Too many elements");
|
||||
static StateError tooMany() => StateError('Too many elements');
|
||||
|
||||
/// Error thrown by, e.g., [List.setRange] if there are too few elements.
|
||||
static StateError tooFew() => StateError("Too few elements");
|
||||
static StateError tooFew() => StateError('Too few elements');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'iterable.dart';
|
||||
|
||||
typedef _Predicate<T> = bool Function(T value);
|
||||
|
@ -347,7 +348,7 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
return map;
|
||||
}
|
||||
|
||||
static _id(x) => x;
|
||||
static dynamic _id(x) => x;
|
||||
|
||||
static void fillMapWithMappedIterable<K, V, E>(
|
||||
Map<K, V> map, Iterable<E> iterable, K Function(E element)? key, V Function(E element)? value) {
|
||||
|
@ -360,8 +361,8 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
}
|
||||
|
||||
static void fillMapWithIterables(Map map, Iterable keys, Iterable values) {
|
||||
Iterator keyIterator = keys.iterator;
|
||||
Iterator valueIterator = values.iterator;
|
||||
final Iterator keyIterator = keys.iterator;
|
||||
final Iterator valueIterator = values.iterator;
|
||||
|
||||
bool hasNextKey = keyIterator.moveNext();
|
||||
bool hasNextValue = valueIterator.moveNext();
|
||||
|
@ -373,7 +374,7 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
}
|
||||
|
||||
if (hasNextKey || hasNextValue) {
|
||||
throw ArgumentError("Iterables do not have same length.");
|
||||
throw ArgumentError('Iterables do not have same length.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,17 +389,19 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
/// It is an error if the two [Iterable]s don't have the same length.
|
||||
factory SoundSplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
|
||||
[int Function(K key1, K key2)? compare, bool Function(Object? potentialKey)? isValidKey]) {
|
||||
SoundSplayTreeMap<K, V> map = SoundSplayTreeMap<K, V>(compare, isValidKey);
|
||||
final SoundSplayTreeMap<K, V> map = SoundSplayTreeMap<K, V>(compare, isValidKey);
|
||||
fillMapWithIterables(map, keys, values);
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
int _compare(K key1, K key2) => _comparator(key1, key2);
|
||||
|
||||
@override
|
||||
V? operator [](Object? key) {
|
||||
if (!_validKey(key)) return null;
|
||||
if (_root != null) {
|
||||
int comp = _splay(key as K);
|
||||
final int comp = _splay(key as K);
|
||||
if (comp == 0) {
|
||||
return _root!.value;
|
||||
}
|
||||
|
@ -406,6 +409,7 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
V? remove(Object? key) {
|
||||
if (!_validKey(key)) return null;
|
||||
final _SoundSplayTreeMapNode<K, V>? mapRoot = _remove(key as K) as _SoundSplayTreeMapNode<K, V>?;
|
||||
|
@ -413,11 +417,12 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(K key, V value) {
|
||||
if (key == null) throw ArgumentError(key);
|
||||
// Splay on the key to move the last node on the search path for
|
||||
// the key to the root of the tree.
|
||||
int comp = _splay(key);
|
||||
final int comp = _splay(key);
|
||||
if (comp == 0) {
|
||||
_root!.value = value;
|
||||
return;
|
||||
|
@ -425,15 +430,16 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
_addNewRoot(_SoundSplayTreeMapNode<K, V>(key, value), comp);
|
||||
}
|
||||
|
||||
V putIfAbsent(K key, V ifAbsent()) {
|
||||
@override
|
||||
V putIfAbsent(K key, V Function() ifAbsent) {
|
||||
if (key == null) throw ArgumentError(key);
|
||||
int comp = _splay(key);
|
||||
if (comp == 0) {
|
||||
return _root!.value!;
|
||||
}
|
||||
int modificationCount = _modificationCount;
|
||||
int splayCount = _splayCount;
|
||||
V value = ifAbsent();
|
||||
final int modificationCount = _modificationCount;
|
||||
final int splayCount = _splayCount;
|
||||
final V value = ifAbsent();
|
||||
if (modificationCount != _modificationCount) {
|
||||
throw ConcurrentModificationError(this);
|
||||
}
|
||||
|
@ -446,40 +452,48 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
void addAll(Map<K, V> other) {
|
||||
other.forEach((K key, V value) {
|
||||
this[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isEmpty {
|
||||
return (_root == null);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isNotEmpty => !isEmpty;
|
||||
|
||||
void forEach(void f(K key, V value)) {
|
||||
Iterator<_SoundSplayTreeNode<K>?> nodes = _SoundSplayTreeNodeIterator<K>(this);
|
||||
@override
|
||||
void forEach(void Function(K key, V value) f) {
|
||||
final Iterator<_SoundSplayTreeNode<K>?> nodes = _SoundSplayTreeNodeIterator<K>(this);
|
||||
while (nodes.moveNext()) {
|
||||
_SoundSplayTreeMapNode<K, V> node = nodes.current as _SoundSplayTreeMapNode<K, V>;
|
||||
final _SoundSplayTreeMapNode<K, V> node = nodes.current as _SoundSplayTreeMapNode<K, V>;
|
||||
f(node.key, node.value!);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get length {
|
||||
return _count;
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
_clear();
|
||||
}
|
||||
|
||||
@override
|
||||
bool containsKey(Object? key) {
|
||||
return _validKey(key) && _splay(key as K) == 0;
|
||||
}
|
||||
|
||||
@override
|
||||
bool containsValue(Object? value) {
|
||||
int initialSplayCount = _splayCount;
|
||||
final int initialSplayCount = _splayCount;
|
||||
bool visit(_SoundSplayTreeMapNode<K, V>? node) {
|
||||
while (node != null) {
|
||||
if (node.value == value) return true;
|
||||
|
@ -495,8 +509,10 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
return visit(_root);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<K> get keys => _SoundSplayTreeKeyIterable<K>(this);
|
||||
|
||||
@override
|
||||
Iterable<V> get values => _SoundSplayTreeValueIterable<K, V>(this);
|
||||
|
||||
/// Get the first key in the map. Returns [:null:] if the map is empty.
|
||||
|
@ -516,7 +532,7 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
K? lastKeyBefore(K key) {
|
||||
if (key == null) throw ArgumentError(key);
|
||||
if (_root == null) return null;
|
||||
int comp = _splay(key);
|
||||
final int comp = _splay(key);
|
||||
if (comp < 0) return _root!.key;
|
||||
_SoundSplayTreeNode<K>? node = _root!.left;
|
||||
if (node == null) return null;
|
||||
|
@ -531,7 +547,7 @@ class SoundSplayTreeMap<inout K, inout V> extends _SoundSplayTree<K>
|
|||
K? firstKeyAfter(K key) {
|
||||
if (key == null) throw ArgumentError(key);
|
||||
if (_root == null) return null;
|
||||
int comp = _splay(key);
|
||||
final int comp = _splay(key);
|
||||
if (comp > 0) return _root!.key;
|
||||
_SoundSplayTreeNode<K>? node = _root!.right;
|
||||
if (node == null) return null;
|
||||
|
@ -563,12 +579,12 @@ abstract class _SoundSplayTreeIterator<inout K, inout T> implements Iterator<T>
|
|||
///
|
||||
/// Not final because some iterators may modify the tree knowingly,
|
||||
/// and they update the modification count in that case.
|
||||
int _modificationCount;
|
||||
final int _modificationCount;
|
||||
|
||||
/// Count of splay operations on [_tree] when [_workList] was built.
|
||||
///
|
||||
/// If the splay count on [_tree] increases, [_workList] becomes invalid.
|
||||
int? _splayCount;
|
||||
final int? _splayCount;
|
||||
|
||||
/// Current node.
|
||||
_SoundSplayTreeNode<K>? _currentNode;
|
||||
|
@ -580,6 +596,7 @@ abstract class _SoundSplayTreeIterator<inout K, inout T> implements Iterator<T>
|
|||
_findLeftMostDescendant(tree._root);
|
||||
}
|
||||
|
||||
@override
|
||||
T get current {
|
||||
if (_currentNode == null) {
|
||||
throw StateError('Use moveNext to detect the end of an iterator');
|
||||
|
@ -612,6 +629,7 @@ abstract class _SoundSplayTreeIterator<inout K, inout T> implements Iterator<T>
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool moveNext() {
|
||||
if (_modificationCount != _tree._modificationCount) {
|
||||
throw ConcurrentModificationError(_tree);
|
||||
|
@ -637,14 +655,18 @@ abstract class _SoundSplayTreeIterator<inout K, inout T> implements Iterator<T>
|
|||
}
|
||||
|
||||
class _SoundSplayTreeKeyIterable<inout K> extends EfficientLengthIterable<K> {
|
||||
_SoundSplayTree<K> _tree;
|
||||
final _SoundSplayTree<K> _tree;
|
||||
_SoundSplayTreeKeyIterable(this._tree);
|
||||
@override
|
||||
int get length => _tree._count;
|
||||
@override
|
||||
bool get isEmpty => _tree._count == 0;
|
||||
@override
|
||||
Iterator<K> get iterator => _SoundSplayTreeKeyIterator<K>(_tree);
|
||||
|
||||
@override
|
||||
Set<K> toSet() {
|
||||
SoundSplayTreeSet<K> set = SoundSplayTreeSet<K>(_tree._comparator, _tree._validKey);
|
||||
final SoundSplayTreeSet<K> set = SoundSplayTreeSet<K>(_tree._comparator, _tree._validKey);
|
||||
set._count = _tree._count;
|
||||
set._root = set._copyNode(_tree._root);
|
||||
return set;
|
||||
|
@ -652,10 +674,13 @@ class _SoundSplayTreeKeyIterable<inout K> extends EfficientLengthIterable<K> {
|
|||
}
|
||||
|
||||
class _SoundSplayTreeValueIterable<inout K, inout V> extends EfficientLengthIterable<V> {
|
||||
SoundSplayTreeMap<K, V> _map;
|
||||
final SoundSplayTreeMap<K, V> _map;
|
||||
_SoundSplayTreeValueIterable(this._map);
|
||||
@override
|
||||
int get length => _map._count;
|
||||
@override
|
||||
bool get isEmpty => _map._count == 0;
|
||||
@override
|
||||
Iterator<V> get iterator => _SoundSplayTreeValueIterator<K, V>(_map);
|
||||
}
|
||||
|
||||
|
@ -667,8 +692,9 @@ class _SoundSplayTreeKeyIterator<inout K> extends _SoundSplayTreeIterator<K, K>
|
|||
|
||||
class _SoundSplayTreeValueIterator<inout K, inout V> extends _SoundSplayTreeIterator<K, V> {
|
||||
_SoundSplayTreeValueIterator(SoundSplayTreeMap<K, V> map) : super(map);
|
||||
@override
|
||||
V _getValue(_SoundSplayTreeNode<K> node) {
|
||||
_SoundSplayTreeMapNode<K, V> mapNode = node as _SoundSplayTreeMapNode<K, V>;
|
||||
final _SoundSplayTreeMapNode<K, V> mapNode = node as _SoundSplayTreeMapNode<K, V>;
|
||||
return mapNode.value!;
|
||||
}
|
||||
}
|
||||
|
@ -697,10 +723,14 @@ class _SoundSplayTreeNodeIterator<inout K>
|
|||
/// in that case.
|
||||
class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E>
|
||||
with IterableMixin<E>, SetMixin<E> {
|
||||
@override
|
||||
_SoundSplayTreeNode<E>? _root;
|
||||
@override
|
||||
final _SoundSplayTreeNode<E> _dummy = _DummySoundSplayTreeNode<E>();
|
||||
|
||||
@override
|
||||
Comparator<E> _comparator;
|
||||
@override
|
||||
_Predicate _validKey;
|
||||
|
||||
/// Create a new [SoundSplayTreeSet] with the given compare function.
|
||||
|
@ -744,9 +774,9 @@ class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E>
|
|||
/// ```
|
||||
factory SoundSplayTreeSet.from(Iterable elements,
|
||||
[int Function(E key1, E key2)? compare, bool Function(Object? potentialKey)? isValidKey]) {
|
||||
SoundSplayTreeSet<E> result = SoundSplayTreeSet<E>(compare, isValidKey);
|
||||
final SoundSplayTreeSet<E> result = SoundSplayTreeSet<E>(compare, isValidKey);
|
||||
for (final element in elements) {
|
||||
E e = element;
|
||||
final E e = element;
|
||||
result.add(e);
|
||||
}
|
||||
return result;
|
||||
|
@ -764,27 +794,36 @@ class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E>
|
|||
Set<T> _newSet<T>() =>
|
||||
SoundSplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);
|
||||
|
||||
@override
|
||||
Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newSet);
|
||||
@override
|
||||
int _compare(E e1, E e2) => _comparator(e1, e2);
|
||||
|
||||
// From Iterable.
|
||||
|
||||
@override
|
||||
Iterator<E> get iterator => _SoundSplayTreeKeyIterator<E>(this);
|
||||
|
||||
@override
|
||||
int get length => _count;
|
||||
@override
|
||||
bool get isEmpty => _root == null;
|
||||
@override
|
||||
bool get isNotEmpty => _root != null;
|
||||
|
||||
@override
|
||||
E get first {
|
||||
if (_count == 0) throw IterableElementError.noElement();
|
||||
return _first!.key;
|
||||
}
|
||||
|
||||
@override
|
||||
E get last {
|
||||
if (_count == 0) throw IterableElementError.noElement();
|
||||
return _last!.key;
|
||||
}
|
||||
|
||||
@override
|
||||
E get single {
|
||||
if (_count == 0) throw IterableElementError.noElement();
|
||||
if (_count > 1) throw IterableElementError.tooMany();
|
||||
|
@ -792,41 +831,47 @@ class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E>
|
|||
}
|
||||
|
||||
// From Set.
|
||||
@override
|
||||
bool contains(Object? element) {
|
||||
return _validKey(element) && _splay(element as E) == 0;
|
||||
}
|
||||
|
||||
@override
|
||||
bool add(E element) {
|
||||
int compare = _splay(element);
|
||||
final int compare = _splay(element);
|
||||
if (compare == 0) return false;
|
||||
_addNewRoot(_SoundSplayTreeNode<E>(element), compare);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
bool remove(Object? object) {
|
||||
if (!_validKey(object)) return false;
|
||||
return _remove(object as E) != null;
|
||||
}
|
||||
|
||||
@override
|
||||
void addAll(Iterable<E> elements) {
|
||||
for (E element in elements) {
|
||||
int compare = _splay(element);
|
||||
final int compare = _splay(element);
|
||||
if (compare != 0) {
|
||||
_addNewRoot(_SoundSplayTreeNode<E>(element), compare);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void removeAll(Iterable<Object?> elements) {
|
||||
for (Object? element in elements) {
|
||||
if (_validKey(element)) _remove(element as E);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void retainAll(Iterable<Object?> elements) {
|
||||
// Build a set with the same sense of equality as this set.
|
||||
SoundSplayTreeSet<E> retainSet = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
int modificationCount = _modificationCount;
|
||||
final SoundSplayTreeSet<E> retainSet = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
final int modificationCount = _modificationCount;
|
||||
for (Object? object in elements) {
|
||||
if (modificationCount != _modificationCount) {
|
||||
// The iterator should not have side effects.
|
||||
|
@ -845,35 +890,39 @@ class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E>
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
E? lookup(Object? object) {
|
||||
if (!_validKey(object)) return null;
|
||||
int comp = _splay(object as E);
|
||||
final int comp = _splay(object as E);
|
||||
if (comp != 0) return null;
|
||||
return _root!.key;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<E> intersection(Set<Object?> other) {
|
||||
Set<E> result = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
final Set<E> result = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
for (E element in this) {
|
||||
if (other.contains(element)) result.add(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<E> difference(Set<Object?> other) {
|
||||
Set<E> result = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
final Set<E> result = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
for (E element in this) {
|
||||
if (!other.contains(element)) result.add(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<E> union(Set<E> other) {
|
||||
return _clone()..addAll(other);
|
||||
}
|
||||
|
||||
SoundSplayTreeSet<E> _clone() {
|
||||
var set = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
final set = SoundSplayTreeSet<E>(_comparator, _validKey);
|
||||
set._count = _count;
|
||||
set._root = _copyNode(_root);
|
||||
return set;
|
||||
|
@ -888,11 +937,14 @@ class SoundSplayTreeSet<inout E> extends _SoundSplayTree<E>
|
|||
..right = _copyNode(node.right));
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
_clear();
|
||||
}
|
||||
|
||||
@override
|
||||
Set<E> toSet() => _clone();
|
||||
|
||||
@override
|
||||
String toString() => IterableBase.iterableToFullString(this, '{', '}');
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'match_class.dart' as match_class;
|
||||
import 'match_enum.dart' as match_enum;
|
||||
|
@ -85,8 +85,9 @@ class Benchmark extends BenchmarkBase {
|
|||
return repeats + padding;
|
||||
}
|
||||
|
||||
static convert(String s) => Uint8List.fromList(s.codeUnits);
|
||||
static Uint8List convert(String s) => Uint8List.fromList(s.codeUnits);
|
||||
|
||||
@override
|
||||
void run() {
|
||||
Expect.equals(true, match(testInput));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user