json_serializable.dart
json_serializable.dart copied to clipboard
enumDecode performance
I'm noticing json_serializable's enumDecode function iterates over the values of a map containing the enum values. Wouldn't it be better to generate a reversed map and use it for this purpose ? It could possibility impact performance over large quantities of data.
Has anyone investigated this performance impact before ?
Relevant code at enum_helpers.dart line 76 :
for (var entry in enumValues.entries) {
if (entry.value == source) {
return entry.key;
}
}
In theory, yes. One could imagine creating the inverse map from values to keys, but then you're increasing your compilation output – and adding complexity.
Running this code on a Flutter release app :
void testMap() {
var num = 'five';
print(DateTime.now());
for(int i = 0; i < 1000000; i++) {
var res = $enumDecode(_$TestEnumEnumMap, num);
}
print(DateTime.now());
for(int i = 0; i < 1000000; i++) {
var res = $enumDecodeInverted(_$TestEnumEnumMapInverted, num);
}
print(DateTime.now());
}
const _$TestEnumEnumMap = {
TestEnum.one: 'one',
TestEnum.two: 'two',
TestEnum.three: 'three',
TestEnum.four: 'four',
TestEnum.five: 'five',
TestEnum.six: 'six',
TestEnum.seven: 'seven',
TestEnum.eigth: 'eigth',
TestEnum.nine: 'nine',
};
const _$TestEnumEnumMapInverted = {
'one': TestEnum.one,
'two': TestEnum.two,
'three': TestEnum.three,
'four': TestEnum.four,
'five': TestEnum.five,
'six': TestEnum.six,
'seven': TestEnum.seven,
'eigth': TestEnum.eigth,
'nine': TestEnum.nine,
};
K $enumDecodeInverted<K extends Enum, String>(
Map<String, K> enumValues,
String? source, {
K? unknownValue,
}) {
if (source == null) {
throw ArgumentError(
'A value must be provided. Supported values: '
'${enumValues.values.join(', ')}',
);
}
// Will be null is source isn't in enumValues
unknownValue = enumValues[source];
if (unknownValue == null) {
throw ArgumentError(
'`$source` is not one of the supported values: '
'${enumValues.values.join(', ')}',
);
}
return unknownValue;
}
Yields :
I/flutter (20434): 2022-04-29 09:35:56.056985
I/flutter (20434): 2022-04-29 09:35:57.897399
I/flutter (20434): 2022-04-29 09:35:57.952474
I don't suppose this is "good-practice" benchmarking, but it does show a tremendous gap between the two implementations. I think it warrants looking into changing this implementation, although it might have been made as such for certain reasons I am not aware of.