[Subtyping Generator] Switch to static-types for runtime subtype checking
⚠️ DO NOT MERGE: While this improves the performance of the VM, as a side effect, it degrades the performance of the interpreter. So we should only merge/deploy this once we fully switched to the VM. Unfortunately it's not trivial to put these changes behind a feature flag.
Closes #3691
Description
- Use the generated static-type based subtyping check for the
IsSubType()function (instead of the subtyping check based on sema-type) - Remove usages of
MustConvertStaticToSemaTypein VM, and rely on static-types. - Migrate all stdlib functions (except for a one or two that strictly needs composite type) to only use static-types (replace the usages of sema-type).
Results:
Vs VM in last released version (v1.8.3)
goos: darwin
goarch: arm64
pkg: github.com/onflow/cadence/runtime
cpu: Apple M1 Pro
│ v1.8.3.txt │ after.txt │
│ sec/op │ sec/op vs base │
RuntimeFungibleTokenTransferVM-8 291.3µ ± 9% 273.0µ ± 4% -6.27% (p=0.002 n=10)
│ v1.8.3.txt │ after.txt │
│ B/op │ B/op vs base │
RuntimeFungibleTokenTransferVM-8 171.9Ki ± 0% 160.0Ki ± 0% -6.92% (p=0.000 n=10)
│ v1.8.3.txt │ after.txt │
│ allocs/op │ allocs/op vs base │
RuntimeFungibleTokenTransferVM-8 3.082k ± 0% 2.753k ± 0% -10.67% (p=0.000 n=10)
Vs VM before switching to static-types (master)
goos: darwin
goarch: arm64
pkg: github.com/onflow/cadence/runtime
cpu: Apple M1 Pro
│ before.txt │ after.txt │
│ sec/op │ sec/op vs base │
RuntimeFungibleTokenTransferVM-8 285.6µ ± 9% 273.0µ ± 4% -4.40% (p=0.011 n=10)
│ before.txt │ after.txt │
│ B/op │ B/op vs base │
RuntimeFungibleTokenTransferVM-8 170.6Ki ± 0% 160.0Ki ± 0% -6.21% (p=0.000 n=10)
│ before.txt │ after.txt │
│ allocs/op │ allocs/op vs base │
RuntimeFungibleTokenTransferVM-8 3.000k ± 0% 2.753k ± 0% -8.23% (p=0.000 n=10)
**Note: The master branch also contains some optimizations that was ported over. So the above comparison only includes the improvement we get from switching to static-types only.
Vs Interpreter (master)
goos: darwin
goarch: arm64
pkg: github.com/onflow/cadence/runtime
cpu: Apple M1 Pro
│ interpreter.txt │ after.txt │
│ sec/op │ sec/op vs base │
RuntimeFungibleTokenTransfer-8 272.8µ ± 2% 273.0µ ± 4% ~ (p=0.796 n=10)
│ interpreter.txt │ after.txt │
│ B/op │ B/op vs base │
RuntimeFungibleTokenTransfer-8 157.3Ki ± 0% 160.0Ki ± 0% +1.70% (p=0.000 n=10)
│ interpreter.txt │ after.txt │
│ allocs/op │ allocs/op vs base │
RuntimeFungibleTokenTransfer-8 2.980k ± 0% 2.753k ± 0% -7.62% (p=0.000 n=10)
Future work:
- Event emitting still need the sema types (hence the conversion exist). Should try to replace those as well.
- Generated subtype check for static-types still converts to sema types in certain cases (for e.g: conformance information is not available in static-types, so need to convert to sema-type to get these information)
- [x] Targeted PR against
masterbranch - [x] Linked to Github issue with discussion and accepted design OR link to spec that describes this work
- [x] Code follows the standards mentioned here
- [x] Updated relevant documentation
- [x] Re-reviewed
Files changedin the Github PR explorer - [x] Added appropriate labels
Benchstat comparison
- Base branch: onflow:master
- Base commit: ba29a406ffec57c3db8b4723344413f894fc242a
Results
| old.txt | new.txt | |||
|---|---|---|---|---|
| time/op | delta | |||
| pkg:github.com/onflow/cadence/bbq/compiler goos:linux goarch:amd64 | ||||
| CompileFungibleTokenTransferTransaction-4 | 110µs ± 0% | 110µs ± 0% | ~ | (p=1.000 n=1+1) |
| CompileTime-4 | 30.1µs ± 0% | 30.9µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| ContractFunctionInvocation-4 | 376µs ± 0% | 384µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| ContractImport-4 | 179µs ± 0% | 176µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| Emit-4 | 4.37ms ± 0% | 5.31ms ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| ExportType/composite_type-4 | 305ns ± 0% | 300ns ± 0% | ~ | (p=1.000 n=1+1) |
| ExportType/simple_type-4 | 66.0ns ± 0% | 67.4ns ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| FTTransfer-4 | 115µs ± 0% | 104µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| ImperativeFib-4 | 21.6µs ± 0% | 26.3µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| ImperativeFib-4 | 14.2µs ± 0% | 12.1µs ± 0% | ~ | (p=1.000 n=1+1) |
| ImperativeFibNewCompilerNewVM-4 | 33.8µs ± 0% | 32.3µs ± 0% | ~ | (p=1.000 n=1+1) |
| ImperativeFibNewVM-4 | 16.2µs ± 0% | 13.6µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| InterpretRecursionFib-4 | 2.19ms ± 0% | 2.65ms ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| InterpreterFTTransfer-4 | 103µs ± 0% | 126µs ± 0% | ~ | (p=1.000 n=1+1) |
| InterpreterImperativeFib-4 | 21.0µs ± 0% | 25.8µs ± 0% | ~ | (p=1.000 n=1+1) |
| InterpreterNewStruct-4 | 63.0µs ± 0% | 71.7µs ± 0% | ~ | (p=1.000 n=1+1) |
| MethodCall/concrete_type_method_call-4 | 27.6µs ± 0% | 26.3µs ± 0% | ~ | (p=1.000 n=1+1) |
| MethodCall/interface_method_call-4 | 49.0µs ± 0% | 45.2µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| NewInterpreter/new_interpreter-4 | 910ns ± 0% | 857ns ± 0% | ~ | (p=1.000 n=1+1) |
| NewInterpreter/new_sub-interpreter-4 | 326ns ± 0% | 325ns ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| NewResource-4 | 78.6µs ± 0% | 81.1µs ± 0% | ~ | (p=1.000 n=1+1) |
| NewStruct-4 | 33.5µs ± 0% | 31.9µs ± 0% | ~ | (p=1.000 n=1+1) |
| NewStructRaw-4 | 4.14µs ± 0% | 3.88µs ± 0% | ~ | (p=1.000 n=1+1) |
| RecursionFib-4 | 821µs ± 0% | 691µs ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeFungibleTokenTransfer-4 | 724µs ± 0% | 825µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| RuntimeFungibleTokenTransferInterpreter-4 | 592µs ± 0% | 653µs ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeFungibleTokenTransferVM-4 | 631µs ± 0% | 622µs ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeResourceDictionaryValues-4 | 2.71ms ± 0% | 2.77ms ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeResourceTracking-4 | 12.6ms ± 0% | 12.1ms ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeScriptNoop-4 | 14.8µs ± 0% | 14.1µs ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeVMInvokeContractImperativeFib-4 | 26.8µs ± 0% | 23.1µs ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| ValueIsSubtypeOfSemaType-4 | 54.6ns ± 0% | 54.0ns ± 0% | ~ | (p=1.000 n=1+1) |
| alloc/op | delta | |||
| pkg:github.com/onflow/cadence/bbq/compiler goos:linux goarch:amd64 | ||||
| CompileFungibleTokenTransferTransaction-4 | 79.3kB ± 0% | 79.3kB ± 0% | ~ | (all equal) |
| CompileTime-4 | 16.3kB ± 0% | 16.3kB ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| ContractFunctionInvocation-4 | 152kB ± 0% | 155kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| ContractImport-4 | 73.9kB ± 0% | 73.7kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| Emit-4 | 1.47MB ± 0% | 1.49MB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| ExportType/composite_type-4 | 120B ± 0% | 120B ± 0% | ~ | (all equal) |
| ExportType/simple_type-4 | 0.00B | 0.00B | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| FTTransfer-4 | 39.2kB ± 0% | 34.3kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| ImperativeFib-4 | 8.30kB ± 0% | 8.30kB ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| ImperativeFib-4 | 1.94kB ± 0% | 1.94kB ± 0% | ~ | (all equal) |
| ImperativeFibNewCompilerNewVM-4 | 21.9kB ± 0% | 21.6kB ± 0% | ~ | (p=1.000 n=1+1) |
| ImperativeFibNewVM-4 | 4.70kB ± 0% | 4.36kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| InterpretRecursionFib-4 | 1.19MB ± 0% | 1.19MB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| InterpreterFTTransfer-4 | 39.6kB ± 0% | 49.2kB ± 0% | ~ | (p=1.000 n=1+1) |
| InterpreterImperativeFib-4 | 8.29kB ± 0% | 8.29kB ± 0% | ~ | (all equal) |
| InterpreterNewStruct-4 | 24.4kB ± 0% | 26.2kB ± 0% | ~ | (p=1.000 n=1+1) |
| MethodCall/concrete_type_method_call-4 | 7.00kB ± 0% | 6.97kB ± 0% | ~ | (p=1.000 n=1+1) |
| MethodCall/interface_method_call-4 | 14.4kB ± 0% | 14.4kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| NewInterpreter/new_interpreter-4 | 976B ± 0% | 976B ± 0% | ~ | (all equal) |
| NewInterpreter/new_sub-interpreter-4 | 232B ± 0% | 232B ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| NewResource-4 | 40.4kB ± 0% | 40.1kB ± 0% | ~ | (p=1.000 n=1+1) |
| NewStruct-4 | 10.4kB ± 0% | 10.3kB ± 0% | ~ | (p=1.000 n=1+1) |
| NewStructRaw-4 | 2.58kB ± 0% | 2.59kB ± 0% | ~ | (p=1.000 n=1+1) |
| RecursionFib-4 | 88.1kB ± 0% | 88.1kB ± 0% | ~ | (all equal) |
| RuntimeFungibleTokenTransfer-4 | 234kB ± 0% | 266kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| RuntimeFungibleTokenTransferInterpreter-4 | 158kB ± 0% | 185kB ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeFungibleTokenTransferVM-4 | 173kB ± 0% | 162kB ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeResourceDictionaryValues-4 | 1.76MB ± 0% | 1.77MB ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeResourceTracking-4 | 9.27MB ± 0% | 9.26MB ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeScriptNoop-4 | 7.99kB ± 0% | 7.98kB ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeVMInvokeContractImperativeFib-4 | 9.80kB ± 0% | 9.32kB ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| ValueIsSubtypeOfSemaType-4 | 32.0B ± 0% | 32.0B ± 0% | ~ | (all equal) |
| allocs/op | delta | |||
| pkg:github.com/onflow/cadence/bbq/compiler goos:linux goarch:amd64 | ||||
| CompileFungibleTokenTransferTransaction-4 | 424 ± 0% | 424 ± 0% | ~ | (all equal) |
| CompileTime-4 | 182 ± 0% | 182 ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| ContractFunctionInvocation-4 | 2.46k ± 0% | 2.53k ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| ContractImport-4 | 938 ± 0% | 936 ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| Emit-4 | 39.0k ± 0% | 40.0k ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| ExportType/composite_type-4 | 3.00 ± 0% | 3.00 ± 0% | ~ | (all equal) |
| ExportType/simple_type-4 | 0.00 | 0.00 | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| FTTransfer-4 | 1.00k ± 0% | 0.85k ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| ImperativeFib-4 | 176 ± 0% | 176 ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| ImperativeFib-4 | 49.0 ± 0% | 49.0 ± 0% | ~ | (all equal) |
| ImperativeFibNewCompilerNewVM-4 | 214 ± 0% | 212 ± 0% | ~ | (p=1.000 n=1+1) |
| ImperativeFibNewVM-4 | 86.0 ± 0% | 84.0 ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| InterpretRecursionFib-4 | 17.7k ± 0% | 17.7k ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| InterpreterFTTransfer-4 | 833 ± 0% | 1044 ± 0% | ~ | (p=1.000 n=1+1) |
| InterpreterImperativeFib-4 | 175 ± 0% | 175 ± 0% | ~ | (all equal) |
| InterpreterNewStruct-4 | 418 ± 0% | 448 ± 0% | ~ | (p=1.000 n=1+1) |
| MethodCall/concrete_type_method_call-4 | 135 ± 0% | 135 ± 0% | ~ | (all equal) |
| MethodCall/interface_method_call-4 | 285 ± 0% | 285 ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| NewInterpreter/new_interpreter-4 | 15.0 ± 0% | 15.0 ± 0% | ~ | (all equal) |
| NewInterpreter/new_sub-interpreter-4 | 4.00 ± 0% | 4.00 ± 0% | ~ | (all equal) |
| pkg:github.com/onflow/cadence/bbq/vm/test goos:linux goarch:amd64 | ||||
| NewResource-4 | 730 ± 0% | 728 ± 0% | ~ | (p=1.000 n=1+1) |
| NewStruct-4 | 219 ± 0% | 219 ± 0% | ~ | (all equal) |
| NewStructRaw-4 | 38.0 ± 0% | 38.0 ± 0% | ~ | (all equal) |
| RecursionFib-4 | 3.65k ± 0% | 3.65k ± 0% | ~ | (all equal) |
| RuntimeFungibleTokenTransfer-4 | 3.99k ± 0% | 4.82k ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/runtime goos:linux goarch:amd64 | ||||
| RuntimeFungibleTokenTransferInterpreter-4 | 2.98k ± 0% | 3.65k ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeFungibleTokenTransferVM-4 | 3.04k ± 0% | 2.79k ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeResourceDictionaryValues-4 | 36.7k ± 0% | 36.7k ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeResourceTracking-4 | 159k ± 0% | 159k ± 0% | ~ | (p=1.000 n=1+1) |
| RuntimeScriptNoop-4 | 113 ± 0% | 113 ± 0% | ~ | (all equal) |
| RuntimeVMInvokeContractImperativeFib-4 | 197 ± 0% | 191 ± 0% | ~ | (p=1.000 n=1+1) |
| pkg:github.com/onflow/cadence/interpreter goos:linux goarch:amd64 | ||||
| ValueIsSubtypeOfSemaType-4 | 1.00 ± 0% | 1.00 ± 0% | ~ | (all equal) |
Dependency Review
✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned Files
None
Codecov Report
:x: Patch coverage is 90.22222% with 44 lines in your changes missing coverage. Please review.
:loudspeaker: Thoughts on this report? Let us know!
[...] it degrades the performance of the interpreter.
I missed this before. Is this because in the interpreter we get sema types from the elaboration, and now have to convert them to static types?