Skip to content

Commit bb6b4d1

Browse files
committed
[patterns] Add benchmarks for exhaustiveness checking.
1 parent 6cfc61d commit bb6b4d1

File tree

2 files changed

+242
-0
lines changed

2 files changed

+242
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
import 'package:exhaustiveness_prototype/exhaustive.dart';
5+
import 'package:exhaustiveness_prototype/profile.dart' as profile;
6+
import 'package:exhaustiveness_prototype/space.dart';
7+
import 'package:exhaustiveness_prototype/static_type.dart';
8+
9+
import '../test/utils.dart';
10+
11+
void main() {
12+
profile.enabled = true;
13+
14+
// (A)
15+
// /|\
16+
// B C D
17+
var a = StaticType('A', isSealed: true);
18+
var b = StaticType('B', inherits: [a]);
19+
var c = StaticType('C', inherits: [a]);
20+
var d = StaticType('D', inherits: [a]);
21+
var t = StaticType('T', fields: {'w': a, 'x': a, 'y': a, 'z': a});
22+
23+
expectExhaustiveOnlyAll(t, [
24+
{'w': b, 'x': b, 'y': b, 'z': b},
25+
{'w': b, 'x': b, 'y': b, 'z': c},
26+
{'w': b, 'x': b, 'y': b, 'z': d},
27+
{'w': b, 'x': b, 'y': c, 'z': b},
28+
{'w': b, 'x': b, 'y': c, 'z': c},
29+
{'w': b, 'x': b, 'y': c, 'z': d},
30+
{'w': b, 'x': b, 'y': d, 'z': b},
31+
{'w': b, 'x': b, 'y': d, 'z': c},
32+
{'w': b, 'x': b, 'y': d, 'z': d},
33+
{'w': b, 'x': c, 'y': b, 'z': b},
34+
{'w': b, 'x': c, 'y': b, 'z': c},
35+
{'w': b, 'x': c, 'y': b, 'z': d},
36+
{'w': b, 'x': c, 'y': c, 'z': b},
37+
{'w': b, 'x': c, 'y': c, 'z': c},
38+
{'w': b, 'x': c, 'y': c, 'z': d},
39+
{'w': b, 'x': c, 'y': d, 'z': b},
40+
{'w': b, 'x': c, 'y': d, 'z': c},
41+
{'w': b, 'x': c, 'y': d, 'z': d},
42+
{'w': b, 'x': d, 'y': b, 'z': b},
43+
{'w': b, 'x': d, 'y': b, 'z': c},
44+
{'w': b, 'x': d, 'y': b, 'z': d},
45+
{'w': b, 'x': d, 'y': c, 'z': b},
46+
{'w': b, 'x': d, 'y': c, 'z': c},
47+
{'w': b, 'x': d, 'y': c, 'z': d},
48+
{'w': b, 'x': d, 'y': d, 'z': b},
49+
{'w': b, 'x': d, 'y': d, 'z': c},
50+
{'w': b, 'x': d, 'y': d, 'z': d},
51+
{'w': c, 'x': b, 'y': b, 'z': b},
52+
{'w': c, 'x': b, 'y': b, 'z': c},
53+
{'w': c, 'x': b, 'y': b, 'z': d},
54+
{'w': c, 'x': b, 'y': c, 'z': b},
55+
{'w': c, 'x': b, 'y': c, 'z': c},
56+
{'w': c, 'x': b, 'y': c, 'z': d},
57+
{'w': c, 'x': b, 'y': d, 'z': b},
58+
{'w': c, 'x': b, 'y': d, 'z': c},
59+
{'w': c, 'x': b, 'y': d, 'z': d},
60+
{'w': c, 'x': c, 'y': b, 'z': b},
61+
{'w': c, 'x': c, 'y': b, 'z': c},
62+
{'w': c, 'x': c, 'y': b, 'z': d},
63+
{'w': c, 'x': c, 'y': c, 'z': b},
64+
{'w': c, 'x': c, 'y': c, 'z': c},
65+
{'w': c, 'x': c, 'y': c, 'z': d},
66+
{'w': c, 'x': c, 'y': d, 'z': b},
67+
{'w': c, 'x': c, 'y': d, 'z': c},
68+
{'w': c, 'x': c, 'y': d, 'z': d},
69+
{'w': c, 'x': d, 'y': b, 'z': b},
70+
{'w': c, 'x': d, 'y': b, 'z': c},
71+
{'w': c, 'x': d, 'y': b, 'z': d},
72+
{'w': c, 'x': d, 'y': c, 'z': b},
73+
{'w': c, 'x': d, 'y': c, 'z': c},
74+
{'w': c, 'x': d, 'y': c, 'z': d},
75+
{'w': c, 'x': d, 'y': d, 'z': b},
76+
{'w': c, 'x': d, 'y': d, 'z': c},
77+
{'w': c, 'x': d, 'y': d, 'z': d},
78+
{'w': d, 'x': b, 'y': b, 'z': b},
79+
{'w': d, 'x': b, 'y': b, 'z': c},
80+
{'w': d, 'x': b, 'y': b, 'z': d},
81+
{'w': d, 'x': b, 'y': c, 'z': b},
82+
{'w': d, 'x': b, 'y': c, 'z': c},
83+
{'w': d, 'x': b, 'y': c, 'z': d},
84+
{'w': d, 'x': b, 'y': d, 'z': b},
85+
{'w': d, 'x': b, 'y': d, 'z': c},
86+
{'w': d, 'x': b, 'y': d, 'z': d},
87+
{'w': d, 'x': c, 'y': b, 'z': b},
88+
{'w': d, 'x': c, 'y': b, 'z': c},
89+
{'w': d, 'x': c, 'y': b, 'z': d},
90+
{'w': d, 'x': c, 'y': c, 'z': b},
91+
{'w': d, 'x': c, 'y': c, 'z': c},
92+
{'w': d, 'x': c, 'y': c, 'z': d},
93+
{'w': d, 'x': c, 'y': d, 'z': b},
94+
{'w': d, 'x': c, 'y': d, 'z': c},
95+
{'w': d, 'x': c, 'y': d, 'z': d},
96+
{'w': d, 'x': d, 'y': b, 'z': b},
97+
{'w': d, 'x': d, 'y': b, 'z': c},
98+
{'w': d, 'x': d, 'y': b, 'z': d},
99+
{'w': d, 'x': d, 'y': c, 'z': b},
100+
{'w': d, 'x': d, 'y': c, 'z': c},
101+
{'w': d, 'x': d, 'y': c, 'z': d},
102+
{'w': d, 'x': d, 'y': d, 'z': b},
103+
{'w': d, 'x': d, 'y': d, 'z': c},
104+
{'w': d, 'x': d, 'y': d, 'z': d},
105+
]);
106+
}
107+
108+
/// Test that [cases] are exhaustive over [type] if and only if all cases are
109+
/// included and that all subsets of the cases are not exhaustive.
110+
void expectExhaustiveOnlyAll(StaticType type, List<Object> cases) {
111+
var spaces = parseSpaces(cases);
112+
profile.reset();
113+
print(isExhaustive(Space(type), spaces));
114+
profile.log();
115+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
import 'dart:math';
5+
6+
import 'package:exhaustiveness_prototype/exhaustive.dart';
7+
import 'package:exhaustiveness_prototype/space.dart';
8+
import 'package:exhaustiveness_prototype/static_type.dart';
9+
10+
import '../test/utils.dart';
11+
12+
void main() {
13+
// (A)
14+
// /|\
15+
// B C D
16+
var a = StaticType('A', isSealed: true);
17+
var b = StaticType('B', inherits: [a]);
18+
var c = StaticType('C', inherits: [a]);
19+
var d = StaticType('D', inherits: [a]);
20+
var t = StaticType('T', fields: {'w': a, 'x': a, 'y': a, 'z': a});
21+
22+
expectExhaustiveOnlyAll(t, [
23+
{'w': b, 'x': b, 'y': b, 'z': b},
24+
{'w': b, 'x': b, 'y': b, 'z': c},
25+
{'w': b, 'x': b, 'y': b, 'z': d},
26+
{'w': b, 'x': b, 'y': c, 'z': b},
27+
{'w': b, 'x': b, 'y': c, 'z': c},
28+
{'w': b, 'x': b, 'y': c, 'z': d},
29+
{'w': b, 'x': b, 'y': d, 'z': b},
30+
{'w': b, 'x': b, 'y': d, 'z': c},
31+
{'w': b, 'x': b, 'y': d, 'z': d},
32+
{'w': b, 'x': c, 'y': b, 'z': b},
33+
{'w': b, 'x': c, 'y': b, 'z': c},
34+
{'w': b, 'x': c, 'y': b, 'z': d},
35+
{'w': b, 'x': c, 'y': c, 'z': b},
36+
{'w': b, 'x': c, 'y': c, 'z': c},
37+
{'w': b, 'x': c, 'y': c, 'z': d},
38+
{'w': b, 'x': c, 'y': d, 'z': b},
39+
{'w': b, 'x': c, 'y': d, 'z': c},
40+
{'w': b, 'x': c, 'y': d, 'z': d},
41+
{'w': b, 'x': d, 'y': b, 'z': b},
42+
{'w': b, 'x': d, 'y': b, 'z': c},
43+
{'w': b, 'x': d, 'y': b, 'z': d},
44+
{'w': b, 'x': d, 'y': c, 'z': b},
45+
{'w': b, 'x': d, 'y': c, 'z': c},
46+
{'w': b, 'x': d, 'y': c, 'z': d},
47+
{'w': b, 'x': d, 'y': d, 'z': b},
48+
{'w': b, 'x': d, 'y': d, 'z': c},
49+
{'w': b, 'x': d, 'y': d, 'z': d},
50+
{'w': c, 'x': b, 'y': b, 'z': b},
51+
{'w': c, 'x': b, 'y': b, 'z': c},
52+
{'w': c, 'x': b, 'y': b, 'z': d},
53+
{'w': c, 'x': b, 'y': c, 'z': b},
54+
{'w': c, 'x': b, 'y': c, 'z': c},
55+
{'w': c, 'x': b, 'y': c, 'z': d},
56+
{'w': c, 'x': b, 'y': d, 'z': b},
57+
{'w': c, 'x': b, 'y': d, 'z': c},
58+
{'w': c, 'x': b, 'y': d, 'z': d},
59+
{'w': c, 'x': c, 'y': b, 'z': b},
60+
{'w': c, 'x': c, 'y': b, 'z': c},
61+
{'w': c, 'x': c, 'y': b, 'z': d},
62+
{'w': c, 'x': c, 'y': c, 'z': b},
63+
{'w': c, 'x': c, 'y': c, 'z': c},
64+
{'w': c, 'x': c, 'y': c, 'z': d},
65+
{'w': c, 'x': c, 'y': d, 'z': b},
66+
{'w': c, 'x': c, 'y': d, 'z': c},
67+
{'w': c, 'x': c, 'y': d, 'z': d},
68+
{'w': c, 'x': d, 'y': b, 'z': b},
69+
{'w': c, 'x': d, 'y': b, 'z': c},
70+
{'w': c, 'x': d, 'y': b, 'z': d},
71+
{'w': c, 'x': d, 'y': c, 'z': b},
72+
{'w': c, 'x': d, 'y': c, 'z': c},
73+
{'w': c, 'x': d, 'y': c, 'z': d},
74+
{'w': c, 'x': d, 'y': d, 'z': b},
75+
{'w': c, 'x': d, 'y': d, 'z': c},
76+
{'w': c, 'x': d, 'y': d, 'z': d},
77+
{'w': d, 'x': b, 'y': b, 'z': b},
78+
{'w': d, 'x': b, 'y': b, 'z': c},
79+
{'w': d, 'x': b, 'y': b, 'z': d},
80+
{'w': d, 'x': b, 'y': c, 'z': b},
81+
{'w': d, 'x': b, 'y': c, 'z': c},
82+
{'w': d, 'x': b, 'y': c, 'z': d},
83+
{'w': d, 'x': b, 'y': d, 'z': b},
84+
{'w': d, 'x': b, 'y': d, 'z': c},
85+
{'w': d, 'x': b, 'y': d, 'z': d},
86+
{'w': d, 'x': c, 'y': b, 'z': b},
87+
{'w': d, 'x': c, 'y': b, 'z': c},
88+
{'w': d, 'x': c, 'y': b, 'z': d},
89+
{'w': d, 'x': c, 'y': c, 'z': b},
90+
{'w': d, 'x': c, 'y': c, 'z': c},
91+
{'w': d, 'x': c, 'y': c, 'z': d},
92+
{'w': d, 'x': c, 'y': d, 'z': b},
93+
{'w': d, 'x': c, 'y': d, 'z': c},
94+
{'w': d, 'x': c, 'y': d, 'z': d},
95+
{'w': d, 'x': d, 'y': b, 'z': b},
96+
{'w': d, 'x': d, 'y': b, 'z': c},
97+
{'w': d, 'x': d, 'y': b, 'z': d},
98+
{'w': d, 'x': d, 'y': c, 'z': b},
99+
{'w': d, 'x': d, 'y': c, 'z': c},
100+
{'w': d, 'x': d, 'y': c, 'z': d},
101+
{'w': d, 'x': d, 'y': d, 'z': b},
102+
{'w': d, 'x': d, 'y': d, 'z': c},
103+
{'w': d, 'x': d, 'y': d, 'z': d},
104+
]);
105+
}
106+
107+
/// Test that [cases] are exhaustive over [type] if and only if all cases are
108+
/// included and that all subsets of the cases are not exhaustive.
109+
void expectExhaustiveOnlyAll(StaticType type, List<Object> cases) {
110+
const trials = 100;
111+
112+
var best = 9999999;
113+
for (var j = 0; j < 100000; j++) {
114+
var watch = Stopwatch()..start();
115+
for (var i = 0; i < trials; i++) {
116+
var spaces = parseSpaces(cases);
117+
var actual = isExhaustive(Space(type), spaces);
118+
if (!actual) {
119+
throw 'Expected exhaustive';
120+
}
121+
}
122+
123+
var elapsed = watch.elapsedMilliseconds;
124+
best = min(elapsed, best);
125+
print('${elapsed / trials}ms (best ${best / trials}ms)');
126+
}
127+
}

0 commit comments

Comments
 (0)