Skip to content

Commit e4fca16

Browse files
authored
Add sparse enum decoding benchmarks (#984)
With upcoming change we'll improve decoding performance of enums, but there will be a difference between "sparse" and "dense" enum decoding performance, even though they'll both be faster. To be able to measure the difference add a "sparse" enum type and a benchmark for decoding it. "Sparse" means the enum has large gaps between known enum values, or negative enum values. When decoding this kind of enums, the mapping from the wire `varint` to the Dart value for the enum needs to be done by binary search, map lookup, or similar. For "dense" enums, we can have a list of enum values and index the list directly with the `varint` value, after a range check. These changes will be done in the follow-up PR(s).
1 parent 006d3aa commit e4fca16

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

benchmarks/bin/binary_decode_packed.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,25 @@ class PackedEnumDecodingBenchmark extends BenchmarkBase {
181181
}
182182
}
183183

184+
class PackedSparseEnumDecodingBenchmark extends BenchmarkBase {
185+
late final Uint8List encoded;
186+
187+
PackedSparseEnumDecodingBenchmark() : super('PackedSparseEnumDecoding') {
188+
final rand = Random(123);
189+
final message = PackedFields();
190+
final numEnums = SparseEnum.values.length;
191+
for (var i = 0; i < 1000000; i += 1) {
192+
message.sparseEnum.add(SparseEnum.values[rand.nextInt(numEnums)]);
193+
}
194+
encoded = message.writeToBuffer();
195+
}
196+
197+
@override
198+
void run() {
199+
sink = PackedFields()..mergeFromBuffer(encoded);
200+
}
201+
}
202+
184203
void main() {
185204
PackedInt32DecodingBenchmark().report();
186205
PackedInt64DecodingBenchmark().report();
@@ -190,6 +209,7 @@ void main() {
190209
PackedSint64DecodingBenchmark().report();
191210
PackedBoolDecodingBenchmark().report();
192211
PackedEnumDecodingBenchmark().report();
212+
PackedSparseEnumDecodingBenchmark().report();
193213

194214
if (int.parse('1') == 0) print(sink);
195215
}

benchmarks/protos/packed_fields.proto

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ message PackedFields {
1010
repeated bool packedBool = 7 [packed = true];
1111
repeated Enum1 packedEnum1 = 8 [packed = true];
1212
repeated Enum2 packedEnum2 = 9 [packed = true];
13+
repeated SparseEnum sparseEnum = 10 [packed = true];
1314
}
1415

1516
enum Enum1 {
@@ -27,3 +28,23 @@ enum Enum2 {
2728
ENUM_2_4 = 4;
2829
ENUM_2_5 = 5;
2930
}
31+
32+
// An enum with large gaps between the known values, and with negative values.
33+
//
34+
// This will be slower to decode as the varint to enum value mapping needs to be
35+
// done with binary search, or map lookup etc.
36+
enum SparseEnum {
37+
ENUM_ZERO = 0;
38+
ENUM_MIN_INT = -2147483648;
39+
ENUM_1 = -1000000000;
40+
ENUM_2 = -100000000;
41+
ENUM_3 = -10000000;
42+
ENUM_4 = -1000000;
43+
ENUM_5 = -100000;
44+
ENUM_6 = 100000;
45+
ENUM_7 = 1000000;
46+
ENUM_8 = 10000000;
47+
ENUM_9 = 100000000;
48+
ENUM_10 = 1000000000;
49+
ENUM_MAX_INT = 2147483647;
50+
}

0 commit comments

Comments
 (0)