Skip to content

Commit 2495b5e

Browse files
authored
test: Enhance performance tests and add insertion_and_removal (#53)
1 parent 882d9fc commit 2495b5e

File tree

5 files changed

+172
-109
lines changed

5 files changed

+172
-109
lines changed

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
- uses: dart-lang/setup-dart@v1
1212
- run: dart pub get
1313

14-
- uses: luanpotter/dart-benchmark-action@v0.1.10
14+
- uses: luanpotter/dart-benchmark-action@v0.1.11
1515
with:
1616
paths: "."
1717
ignore-tag: "no-benchmark"

benchmark/comprehensive_benchmark.dart

Lines changed: 130 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import 'package:benchmark_harness/benchmark_harness.dart';
44
import 'package:ordered_set/comparing.dart';
55
import 'package:ordered_set/ordered_set.dart';
66

7-
const _maxOperations = 2500;
7+
const _maxOperations = 1000;
88
const _maxElement = 10000;
9-
const _startingSetSize = 500;
9+
const _startingSetSize = 250;
1010

1111
class ComprehensiveBenchmark extends BenchmarkBase {
1212
final Random r;
@@ -83,7 +83,7 @@ class _Runtime {
8383

8484
void _populateSet() {
8585
for (var i = 0; i < _startingSetSize; i++) {
86-
_queueOp(_AddOperation(_randomElement()));
86+
_queueOp(_OperationType.add.create(_randomElement()));
8787
}
8888
}
8989

@@ -93,165 +93,188 @@ class _Runtime {
9393
}
9494

9595
_Operation _randomOperation() {
96-
final type = _OperationType.values[r.nextInt(_OperationType.values.length)];
97-
switch (type) {
98-
case _OperationType.add:
99-
return _AddOperation(_randomElement());
100-
case _OperationType.removeIdx:
101-
if (_set.isEmpty) {
102-
return _AddOperation(_randomElement());
103-
}
104-
return _RemoveIdxOperation(r.nextInt(_set.length));
105-
case _OperationType.removeElement:
106-
if (_set.isEmpty) {
107-
return _AddOperation(_randomElement());
108-
}
109-
return _RemoveElementOperation(_set.elementAt(r.nextInt(_set.length)));
110-
case _OperationType.removeWhere:
111-
return _RemoveWhereOperation(_randomElement());
112-
case _OperationType.visit:
113-
return _VisitOperation(_randomElement());
114-
case _OperationType.iterateThenAdd:
115-
return _IterateThenAddOperation(_randomElement());
116-
case _OperationType.iterateThenRemove:
117-
return _IterateThenRemoveOperation(_randomElement());
118-
}
96+
final type = _set.isEmpty
97+
? _OperationType.add
98+
: _OperationType.values[r.nextInt(_OperationType.values.length)];
99+
final value = switch (type) {
100+
_AddOp() => _randomElement(),
101+
_RemoveIdxOp() => r.nextInt(_set.length),
102+
_RemoveElementOp() => _set.elementAt(r.nextInt(_set.length)),
103+
_RemoveWhereOp() => _randomElement(),
104+
_VisitOp() => _randomElement(),
105+
_IterateThenAddOp() => _randomElement(),
106+
_IterateThenRemoveOp() => _randomElement(),
107+
};
108+
return type.create(value);
119109
}
120110

121111
int _randomElement() => r.nextInt(_maxElement) + 1;
122112
}
123113

124-
enum _OperationType {
125-
// when queued, generates a random element; then adds using `add`
126-
add,
127-
// when queued, selects a random index; then removes using `removeAt`
128-
removeIdx,
129-
// when queued, selects a random element; then removes using `remove`
130-
removeElement,
131-
// when queued, generates a random factor; then removes all elements with
132-
// that factor using `removeWhere`
133-
removeWhere,
134-
// when queued, generates a random factor; then finds the elements matching
135-
// that factor, using normal for iteration
136-
visit,
137-
// when queued, generates two random factors; iterates over the set,
138-
//finds elements that match the first factor, then multiplies them by
139-
//the second factor, queue adding the results with the `add` operation
140-
iterateThenAdd,
141-
// when queued, generates a random factor; iterates over the set, finding
142-
// elements that match the factor, then queue their removal with
143-
// the `removeElement` operation
144-
iterateThenRemove,
145-
}
146-
147-
abstract class _Operation {
148-
final _OperationType type;
149-
150-
const _Operation(this.type);
151-
152-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set);
114+
sealed class _OperationType {
115+
static const add = _AddOp();
116+
static const removeIdx = _RemoveIdxOp();
117+
static const removeElement = _RemoveElementOp();
118+
static const removeWhere = _RemoveWhereOp();
119+
static const visit = _VisitOp();
120+
static const iterateThenAdd = _IterateThenAddOp();
121+
static const iterateThenRemove = _IterateThenRemoveOp();
122+
123+
static const values = [
124+
add,
125+
removeIdx,
126+
removeElement,
127+
removeWhere,
128+
visit,
129+
iterateThenAdd,
130+
iterateThenRemove,
131+
];
132+
133+
const _OperationType();
134+
135+
_Operation create(int factor) => (type: this, value: factor);
136+
137+
List<_Operation> execute(
138+
_Operation operation,
139+
_Runtime runtime,
140+
OrderedSet<int> set,
141+
);
153142
}
154143

155-
class _AddOperation extends _Operation {
156-
final int element;
157-
158-
_AddOperation(this.element) : super(_OperationType.add);
144+
/// When queued, generates a random element; then adds using `add`.
145+
class _AddOp extends _OperationType {
146+
const _AddOp();
159147

160148
@override
161-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
162-
set.add(element);
149+
List<_Operation> execute(
150+
_Operation operation,
151+
_Runtime runtime,
152+
OrderedSet<int> set,
153+
) {
154+
set.add(operation.value);
163155
return [];
164156
}
165157
}
166158

167-
class _RemoveIdxOperation extends _Operation {
168-
final int index;
169-
170-
_RemoveIdxOperation(this.index) : super(_OperationType.removeIdx);
159+
/// When queued, selects a random index; then removes using `removeAt`.
160+
class _RemoveIdxOp extends _OperationType {
161+
const _RemoveIdxOp();
171162

172163
@override
173-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
174-
if (index < set.length) {
175-
set.removeAt(index);
164+
List<_Operation> execute(
165+
_Operation operation,
166+
_Runtime runtime,
167+
OrderedSet<int> set,
168+
) {
169+
if (set.isEmpty) {
170+
return [];
176171
}
172+
set.removeAt(operation.value);
177173
return [];
178174
}
179175
}
180176

181-
class _RemoveElementOperation extends _Operation {
182-
final int element;
183-
184-
_RemoveElementOperation(this.element) : super(_OperationType.removeElement);
177+
/// When queued, selects a random element; then removes using `remove`.
178+
class _RemoveElementOp extends _OperationType {
179+
const _RemoveElementOp();
185180

186181
@override
187-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
188-
set.remove(element);
182+
List<_Operation> execute(
183+
_Operation operation,
184+
_Runtime runtime,
185+
OrderedSet<int> set,
186+
) {
187+
set.remove(operation.value);
189188
return [];
190189
}
191190
}
192191

193-
class _RemoveWhereOperation extends _Operation {
194-
final int factor;
195-
196-
_RemoveWhereOperation(this.factor) : super(_OperationType.removeWhere);
192+
/// When queued, generates a random factor; then removes all elements with
193+
/// that factor using `removeWhere`.
194+
class _RemoveWhereOp extends _OperationType {
195+
const _RemoveWhereOp();
197196

198197
@override
199-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
200-
set.removeWhere((e) => e % factor == 0);
198+
List<_Operation> execute(
199+
_Operation operation,
200+
_Runtime runtime,
201+
OrderedSet<int> set,
202+
) {
203+
set.removeWhere((e) => e % operation.value == 0);
201204
return [];
202205
}
203206
}
204207

205-
class _VisitOperation extends _Operation {
206-
final int factor;
207-
208-
_VisitOperation(this.factor) : super(_OperationType.visit);
208+
/// When queued, generates a random factor; then finds the elements matching
209+
/// that factor, using normal for iteration.
210+
class _VisitOp extends _OperationType {
211+
const _VisitOp();
209212

210213
@override
211-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
214+
List<_Operation> execute(
215+
_Operation operation,
216+
_Runtime runtime,
217+
OrderedSet<int> set,
218+
) {
212219
final output = <_Operation>[];
213220
for (final e in set) {
214-
if (e % factor == 0) {
215-
output.add(_AddOperation(e * factor));
221+
if (e % operation.value == 0) {
222+
output.add(_OperationType.add.create(e * operation.value));
216223
}
217224
}
218225
return output;
219226
}
220227
}
221228

222-
class _IterateThenAddOperation extends _Operation {
223-
final int factor;
224-
225-
_IterateThenAddOperation(this.factor) : super(_OperationType.iterateThenAdd);
229+
/// When queued, generates two random factors; iterates over the set,
230+
/// finds elements that match the first factor, then multiplies them by
231+
/// the second factor, queue adding the results with the `add` operation
232+
class _IterateThenAddOp extends _OperationType {
233+
const _IterateThenAddOp();
226234

227235
@override
228-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
229-
final toAdd = <int>[];
236+
List<_Operation> execute(
237+
_Operation operation,
238+
_Runtime runtime,
239+
OrderedSet<int> set,
240+
) {
241+
final output = <_Operation>[];
230242
for (final e in set) {
231-
if (e % factor == 0) {
232-
toAdd.add(e);
243+
if (e % operation.value == 0) {
244+
output.add(_OperationType.add.create(e * operation.value));
233245
}
234246
}
235-
236-
return toAdd.map(_AddOperation.new).toList();
247+
return output;
237248
}
238249
}
239250

240-
class _IterateThenRemoveOperation extends _Operation {
241-
final int factor;
242-
243-
_IterateThenRemoveOperation(this.factor)
244-
: super(_OperationType.iterateThenRemove);
251+
/// When queued, generates a random factor; iterates over the set, finding
252+
/// elements that match the factor, then queue their removal with
253+
/// the `removeElement` operation.
254+
class _IterateThenRemoveOp extends _OperationType {
255+
const _IterateThenRemoveOp();
245256

246257
@override
247-
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
248-
final toRemove = <int>[];
258+
List<_Operation> execute(
259+
_Operation operation,
260+
_Runtime runtime,
261+
OrderedSet<int> set,
262+
) {
263+
final output = <_Operation>[];
249264
for (final e in set) {
250-
if (e % factor == 0) {
251-
toRemove.add(e);
265+
if (e % operation.value == 0) {
266+
output.add(_OperationType.removeElement.create(e));
252267
}
253268
}
254-
return toRemove.map(_RemoveElementOperation.new).toList();
269+
return output;
270+
}
271+
}
272+
273+
typedef _Operation = ({_OperationType type, int value});
274+
275+
extension on _Operation {
276+
List<_Operation> execute(_Runtime runtime, OrderedSet<int> set) {
277+
return type.execute(this, runtime, set);
255278
}
256279
}
257280

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:benchmark_harness/benchmark_harness.dart';
2+
import 'package:ordered_set/ordered_set.dart';
3+
4+
import '../test/comparable_object.dart';
5+
6+
const _iterationAmount = 1000;
7+
8+
class InsertionAndRemovalBenchmark extends BenchmarkBase {
9+
late final OrderedSet<ComparableObject> set;
10+
late final Map<int, ComparableObject> objects;
11+
12+
InsertionAndRemovalBenchmark() : super('Insertion and Removal Benchmark');
13+
14+
static void main() {
15+
InsertionAndRemovalBenchmark().report();
16+
}
17+
18+
@override
19+
void setup() {
20+
set = OrderedSet<ComparableObject>();
21+
objects = {
22+
for (var i = 0; i < _iterationAmount; i++) i: ComparableObject(i, '$i'),
23+
};
24+
}
25+
26+
@override
27+
void exercise() {
28+
for (var i = 0; i < _iterationAmount; i++) {
29+
set.add(objects[i]!);
30+
}
31+
32+
for (var i = 0; i < _iterationAmount; i++) {
33+
set.remove(objects[i]!);
34+
}
35+
}
36+
}

benchmark/iteration_benchmark.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import 'package:ordered_set/ordered_set.dart';
55

66
import '../test/comparable_object.dart';
77

8+
const _iterationAmount = 1000;
9+
810
class IterationBenchmark extends BenchmarkBase {
911
late final OrderedSet<ComparableObject> set;
1012

@@ -17,7 +19,7 @@ class IterationBenchmark extends BenchmarkBase {
1719
@override
1820
void setup() {
1921
set = OrderedSet();
20-
for (var i = 0; i < 1000; i++) {
22+
for (var i = 0; i < _iterationAmount; i++) {
2123
final l = (10 + sqrt(i)).floor();
2224
for (var j = 0; j <= l; j++) {
2325
set.add(ComparableObject(i, '$i-$j'));

benchmark/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import 'comprehensive_benchmark.dart';
2+
import 'insertion_and_removal_benchmark.dart';
23
import 'iteration_benchmark.dart';
34

45
void main() {
56
IterationBenchmark.main();
7+
InsertionAndRemovalBenchmark.main();
68
ComprehensiveBenchmark.main();
79
}

0 commit comments

Comments
 (0)