cadence icon indicating copy to clipboard operation
cadence copied to clipboard

Optimize predeclared values, refactor runtime into reusable part

Open turbolent opened this issue 3 years ago • 2 comments

Closes #1822

Description

  • Optimize checker/interpreter predeclared values by refactoring redeclaration of variables in activation for each checker/interpreter instantiation to a single activation creation which can be injected and thus reused
  • Moved the majority of the standard library implementation from runtime to the stdlib package. Instead of requiring the full runtime.Interface, each value declaration depends on a separate interface. This allows standard library declarations to be declared once/reused, by making the target (runtime.Interface) switchable. It also ensures the declarations are implemented consistently and allows them to be tested individually.
  • Refactored the majority of the reusable part of the runtime into an "environment". The environment can be reused across multiple transactions/scripts. Only the interface and storage is re-targeted.
  • This change unlocks #1823: In a follow-up PR, the checker and interpreter options will get refactored into a reused configuration.

This is a large refactor. It is best reviewed commit by commit. We should have a review session to go over it together.


  • [x] Targeted PR against master branch
  • [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 changed in the Github PR explorer
  • [x] Added appropriate labels

turbolent avatar Jul 19 '22 02:07 turbolent

Codecov Report

Merging #1825 (d264d5f) into master (674324f) will increase coverage by 0.15%. The diff coverage is 86.20%.

@@            Coverage Diff             @@
##           master    #1825      +/-   ##
==========================================
+ Coverage   77.72%   77.87%   +0.15%     
==========================================
  Files         294      300       +6     
  Lines       62193    62217      +24     
==========================================
+ Hits        48340    48452     +112     
+ Misses      12129    12046      -83     
+ Partials     1724     1719       -5     
Flag Coverage Δ
unittests 77.87% <86.20%> (+0.15%) :arrow_up:

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
runtime/interpreter/interpreter_import.go 100.00% <ø> (ø)
runtime/repl.go 0.00% <0.00%> (ø)
runtime/runtime.go 87.88% <ø> (+1.70%) :arrow_up:
runtime/sema/check_import_declaration.go 91.86% <ø> (+2.10%) :arrow_up:
runtime/sema/elaboration.go 86.48% <ø> (-0.36%) :arrow_down:
runtime/sema/import.go 100.00% <ø> (+19.04%) :arrow_up:
runtime/sema/type.go 89.16% <ø> (-0.09%) :arrow_down:
runtime/stdlib/assert.go 54.54% <0.00%> (-20.46%) :arrow_down:
runtime/stdlib/bls.go 92.98% <ø> (-0.36%) :arrow_down:
runtime/stdlib/hashalgorithm.go 89.09% <ø> (-0.57%) :arrow_down:
... and 53 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

codecov[bot] avatar Jul 19 '22 03:07 codecov[bot]

Cadence Benchstat comparison

This branch with compared with the base branch onflow:master commit 674324f72f84fa87829928a3ac7a79725dd80885 The command for i in {1..N}; do go test ./... -run=XXX -bench=. -benchmem -shuffle=on; done was used. Bench tests were run a total of 7 times on each branch.

Collapsed results for better readability

old.txtnew.txt
time/opdelta
CheckContractInterfaceFungibleTokenConformance-2135µs ± 0%136µs ± 6%~(p=0.755 n=5+7)
ContractInterfaceFungibleToken-240.0µs ± 1%39.7µs ± 1%~(p=0.065 n=6+6)
InterpretRecursionFib-23.73ms ± 1%3.50ms ± 2%−6.16%(p=0.001 n=7+6)
NewInterpreter/new_interpreter-21.18µs ± 1%1.13µs ± 1%−4.48%(p=0.001 n=7+6)
NewInterpreter/new_sub-interpreter-22.52µs ± 6%2.41µs ± 2%−4.32%(p=0.004 n=7+7)
ParseArray-28.58ms ± 1%8.62ms ± 1%~(p=0.534 n=6+7)
ParseDeploy/byte_array-213.0ms ± 1%13.0ms ± 1%~(p=0.836 n=7+6)
ParseDeploy/decode_hex-21.14ms ± 2%1.15ms ± 5%~(p=0.383 n=7+7)
ParseFungibleToken/With_memory_metering-2209µs ± 2%208µs ± 3%~(p=0.535 n=7+7)
ParseFungibleToken/Without_memory_metering-2159µs ± 0%160µs ± 2%~(p=0.535 n=7+7)
ParseInfix-27.85µs ± 3%7.92µs ± 2%~(p=0.209 n=7+7)
QualifiedIdentifierCreation/One_level-22.34ns ± 0%2.34ns ± 0%~(p=0.604 n=6+7)
QualifiedIdentifierCreation/Three_levels-2142ns ± 1%138ns ± 1%−3.08%(p=0.001 n=7+6)
RuntimeFungibleTokenTransfer-2920µs ±32%718µs ±26%~(p=0.259 n=7+7)
RuntimeResourceDictionaryValues-26.33ms ± 3%5.01ms ± 1%−20.85%(p=0.001 n=7+6)
ValueIsSubtypeOfSemaType-290.8ns ± 1%100.7ns ± 1%+10.91%(p=0.001 n=6+7)
 
alloc/opdelta
CheckContractInterfaceFungibleTokenConformance-262.4kB ± 0%61.7kB ± 0%−1.18%(p=0.002 n=6+6)
ContractInterfaceFungibleToken-224.4kB ± 0%24.3kB ± 0%−0.53%(p=0.008 n=6+7)
InterpretRecursionFib-21.51MB ± 0%1.51MB ± 0%~(p=0.449 n=7+7)
NewInterpreter/new_interpreter-2928B ± 0%848B ± 0%−8.62%(p=0.001 n=7+7)
NewInterpreter/new_sub-interpreter-21.46kB ± 0%1.36kB ± 0%−6.59%(p=0.001 n=7+7)
ParseArray-22.81MB ± 2%2.79MB ± 2%~(p=0.383 n=7+7)
ParseDeploy/byte_array-24.44MB ± 3%4.42MB ± 3%~(p=0.259 n=7+7)
ParseDeploy/decode_hex-2214kB ± 0%214kB ± 0%+0.07%(p=0.002 n=6+6)
ParseFungibleToken/With_memory_metering-236.3kB ± 0%36.3kB ± 0%~(p=0.851 n=7+7)
ParseFungibleToken/Without_memory_metering-236.3kB ± 0%36.3kB ± 0%~(p=0.432 n=6+7)
ParseInfix-22.17kB ± 0%2.17kB ± 0%~(p=1.000 n=5+6)
QualifiedIdentifierCreation/One_level-20.00B 0.00B ~(all equal)
QualifiedIdentifierCreation/Three_levels-264.0B ± 0%64.0B ± 0%~(all equal)
RuntimeFungibleTokenTransfer-2185kB ± 1%119kB ± 1%−35.40%(p=0.001 n=7+7)
RuntimeResourceDictionaryValues-22.23MB ± 0%2.27MB ± 0%+2.13%(p=0.001 n=7+7)
ValueIsSubtypeOfSemaType-248.0B ± 0%48.0B ± 0%~(all equal)
 
allocs/opdelta
CheckContractInterfaceFungibleTokenConformance-21.03k ± 0%1.02k ± 0%−0.78%(p=0.001 n=7+7)
ContractInterfaceFungibleToken-2428 ± 0%426 ± 0%−0.47%(p=0.001 n=7+7)
InterpretRecursionFib-233.5k ± 0%33.5k ± 0%~(all equal)
NewInterpreter/new_interpreter-213.0 ± 0%12.0 ± 0%−7.69%(p=0.001 n=7+7)
NewInterpreter/new_sub-interpreter-242.0 ± 0%41.0 ± 0%−2.38%(p=0.001 n=7+7)
ParseArray-270.0k ± 0%70.0k ± 0%~(p=0.245 n=7+6)
ParseDeploy/byte_array-2105k ± 0%105k ± 0%~(p=0.140 n=7+6)
ParseDeploy/decode_hex-277.0 ± 0%77.0 ± 0%~(all equal)
ParseFungibleToken/With_memory_metering-21.06k ± 0%1.06k ± 0%~(all equal)
ParseFungibleToken/Without_memory_metering-21.06k ± 0%1.06k ± 0%~(all equal)
ParseInfix-266.0 ± 0%66.0 ± 0%~(all equal)
QualifiedIdentifierCreation/One_level-20.00 0.00 ~(all equal)
QualifiedIdentifierCreation/Three_levels-22.00 ± 0%2.00 ± 0%~(all equal)
RuntimeFungibleTokenTransfer-23.48k ± 0%2.38k ± 0%−31.81%(p=0.001 n=7+7)
RuntimeResourceDictionaryValues-237.1k ± 0%37.0k ± 0%−0.24%(p=0.001 n=7+7)
ValueIsSubtypeOfSemaType-21.00 ± 0%1.00 ± 0%~(all equal)
 

github-actions[bot] avatar Jul 19 '22 03:07 github-actions[bot]

CI is failing for a potentially flaky LS test. Pinged @sideninja

turbolent avatar Aug 17 '22 22:08 turbolent

@turbolent I can't seem to reproduce that flakiness locally. I've created a PR I think might help fix the test issue, but I also haven't detected that during the CI, so making these changes based on the stack from this CI: https://github.com/onflow/cadence/pull/1890

devbugging avatar Aug 18 '22 11:08 devbugging

@sideninja Thank you for investigating. 🙏 I'll re-run the job and see if it shows up again

turbolent avatar Aug 18 '22 16:08 turbolent

@sideninja Thank you for investigating. 🙏 I'll re-run the job and see if it shows up again

Now it's something else?

devbugging avatar Aug 18 '22 16:08 devbugging

@sideninja it's happening again and I can reproduce it locally, even on master. It only happens 1 out of ~5000 calls ... looked into it and can't see how this could ever produce anything else, though testify's mock library uses quite some low-level hacks, hmm.

Given that the LS uses interfaces anyway, maybe just don't use mocking and just implement the interfaces normally?

╭─bastian@bm2 ~/Documents/work/cadence/languageserver ‹master●›
╰─$ go test --count 100 --parallel 8 ./...
?   	github.com/onflow/cadence/languageserver	[no test files]
?   	github.com/onflow/cadence/languageserver/cmd/languageserver	[no test files]
?   	github.com/onflow/cadence/languageserver/conversion	[no test files]
--- FAIL: Test_DeployContract (0.00s)
    --- FAIL: Test_DeployContract/successful_deploy_contract (0.00s)
panic: assert: arguments: Cannot call Get(0) because there are 0 argument(s). [recovered]
	panic: assert: arguments: Cannot call Get(0) because there are 0 argument(s).

goroutine 442 [running]:
testing.tRunner.func1.2({0x103f2ace0, 0x140003f8de0})
	/opt/homebrew/Cellar/go/1.19/libexec/src/testing/testing.go:1396 +0x1c8
testing.tRunner.func1()
	/opt/homebrew/Cellar/go/1.19/libexec/src/testing/testing.go:1399 +0x378
panic({0x103f2ace0, 0x140003f8de0})
	/opt/homebrew/Cellar/go/1.19/libexec/src/runtime/panic.go:884 +0x204
github.com/stretchr/testify/mock.Arguments.Get(...)
	/Users/bastian/go/pkg/mod/github.com/stretchr/[email protected]/mock/mock.go:800
github.com/onflow/cadence/languageserver/integration.(*mockFlowClient).DeployContract(0x140001e9ae0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, {0x140003f2ac8, ...}, ...)
	/Users/bastian/Documents/work/cadence/languageserver/integration/mock_flow_test.go:47 +0x2f8
github.com/onflow/cadence/languageserver/integration.(*commands).deployContract(0x1400042e4e0, {0x14000085f10, 0x3, 0x140003fe540?})
	/Users/bastian/Documents/work/cadence/languageserver/integration/commands.go:241 +0x238
github.com/onflow/cadence/languageserver/integration.Test_DeployContract.func1(0x0?)
	/Users/bastian/Documents/work/cadence/languageserver/integration/commands_test.go:198 +0x3c8
testing.tRunner(0x140005061a0, 0x14000500120)
	/opt/homebrew/Cellar/go/1.19/libexec/src/testing/testing.go:1446 +0x10c
created by testing.(*T).Run
	/opt/homebrew/Cellar/go/1.19/libexec/src/testing/testing.go:1493 +0x300
FAIL	github.com/onflow/cadence/languageserver/integration	0.355s
?   	github.com/onflow/cadence/languageserver/jsonrpc2	[no test files]
ok  	github.com/onflow/cadence/languageserver/protocol	0.087s [no tests to run]
ok  	github.com/onflow/cadence/languageserver/server	3.753s
?   	github.com/onflow/cadence/languageserver/test	[no test files]
FAIL

turbolent avatar Aug 18 '22 21:08 turbolent

@dsainati1 I had another look to re-familiarize myself with that part: The check is not necessary anymore, because GlobalValues and GlobalTypes is not set anymore.

https://github.com/onflow/cadence/pull/1825/files#diff-74d0954852bf407e9259a7c9bb55e8af093f080f00f5e35689c250886c29860aL134-L135

turbolent avatar Aug 18 '22 23:08 turbolent

Can we try merging the PR I made in? I think it could be related to the fact I'm returning nils. https://github.com/onflow/cadence/pull/1890

devbugging avatar Aug 19 '22 07:08 devbugging