You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While investigating why decoding packed enums is so much slower in AOT compared
to decoding packed int32 (both are varints on the wire) I noticed that the enum
decoding benchmark should actually be slower, because currently TFA is able to
specialize the enum int value to Dart enum value mapping to a direct call, in
this function:
```dart
ProtobufEnum? _decodeEnum(
int tagNumber, ExtensionRegistry? registry, int rawValue) {
final f = valueOfFunc(tagNumber);
if (f != null) {
return f(rawValue); // <------------------- HERE
}
...
}
```
Wasm code for this function, before this PR:
```wat
(func $BuilderInfo._decodeEnum (;641;) (param $var0 (ref $BuilderInfo_214)) (param $var1 i64) (param $var2 i64) (result (ref null $Enum))
(local $var3 (ref null $FieldInfo_223))
local.get $var0
struct.get $BuilderInfo_214 $field4
i32.const 71
local.get $var1
struct.new $BoxedInt
call $_DefaultMap&_HashFieldBase&MapMixin&_HashBase&_OperatorEqualsAndHashCode&_LinkedHashMapMixin.[]
ref.cast null $FieldInfo_223
local.tee $var3
ref.is_null
if (result (ref null $#Closure-0-1_815))
ref.null none
else
local.get $var3
struct.get $FieldInfo_223 $field9
end
ref.is_null
i32.eqz
if
local.get $var2
call $Enum.valueOf
return
end
ref.null none
)
```
Note that this calls `$Enum.valueOf` even though this function is generic on the enum type.
With this PR we add another enum to the proto file and decode it in setup, so
that TFA is unable to specialize `_deocdeEnum` to one specific enum type.
New code:
```wat
(func $BuilderInfo._decodeEnum (;643;) (param $var0 (ref $BuilderInfo_214)) (param $var1 i64) (param $var2 i64) (result (ref null $ProtobufEnum))
(local $var3 (ref null $FieldInfo_229))
(local $var4 (ref null $#Closure-0-1))
(local $var5 (ref $#Closure-0-1))
local.get $var0
struct.get $BuilderInfo_214 $field4
i32.const 71
local.get $var1
struct.new $BoxedInt
call $_DefaultMap&_HashFieldBase&MapMixin&_HashBase&_OperatorEqualsAndHashCode&_LinkedHashMapMixin.[]
ref.cast null $FieldInfo_229
local.tee $var3
ref.is_null
if (result (ref null $#Closure-0-1))
ref.null none
else
local.get $var3
struct.get $FieldInfo_229 $field9
end
local.tee $var4
ref.is_null
i32.eqz
if
local.get $var4
ref.as_non_null
local.tee $var5
struct.get $#Closure-0-1 $field2
i32.const 71
local.get $var2
struct.new $BoxedInt
local.get $var5
struct.get $#Closure-0-1 $field3
struct.get $#Vtable-0-1 $field1
call_ref $type39
ref.cast null $ProtobufEnum
return
end
ref.null none
)
```
Wasm benchmark results:
```
// Before
protobuf_PackedEnumDecoding(RunTimeRaw): 41120.0 us.
// After
protobuf_PackedEnumDecoding(RunTimeRaw): 52750.0 us.
```
VM benchmark results:
```
// Before
protobuf_PackedEnumDecoding(RunTimeRaw): 45051.520000000004 us.
// After
protobuf_PackedEnumDecoding(RunTimeRaw): 54661.125 us.
```
0 commit comments