From 2b906f22f1dace88f164ec8bfc95629a03acb3f9 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Wed, 17 Sep 2025 08:17:18 +0800 Subject: [PATCH] eth/tracers/js: avoid compiling js bigint when not needed #30640 (#1497) While looking at some mem profiles from `evm` runs, I noticed that `goja` compilation of the bigint library was present. The bigint library compilation happens in a package `init`, whenever the package `eth/tracers/js` is loaded. This PR changes it to load lazily when needed. It becomes slightly faster with this change, and slightly less alloc:y. Non-scientific benchmark with 100 executions: ``` time for i in {1..100}; do ./evm --code 6040 run; done; ``` current `master`: ``` real 0m6.634s user 0m5.213s sys 0m2.277s ``` Without compiling bigint ``` real 0m5.802s user 0m4.191s sys 0m1.965s ``` Co-authored-by: Martin HS --- eth/tracers/js/goja.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index a7db4d127a..e96a672244 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -22,6 +22,7 @@ import ( "fmt" "math/big" "slices" + "sync" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/hexutil" @@ -57,9 +58,17 @@ func init() { tracers.DefaultDirectory.RegisterJSEval(newJsTracer) } -// bigIntProgram is compiled once and the exported function mostly invoked to convert -// hex strings into big ints. -var bigIntProgram = goja.MustCompile("bigInt", bigIntegerJS, false) +var compiledBigInt *goja.Program +var compileOnce sync.Once + +// getBigIntProgram compiles the bigint library, if needed, and returns the compiled +// goja program. +func getBigIntProgram() *goja.Program { + compileOnce.Do(func() { + compiledBigInt = goja.MustCompile("bigInt", bigIntegerJS, false) + }) + return compiledBigInt +} type toBigFn = func(vm *goja.Runtime, val string) (goja.Value, error) type toBufFn = func(vm *goja.Runtime, val []byte) (goja.Value, error) @@ -563,7 +572,7 @@ func (t *jsTracer) setBuiltinFunctions() { func (t *jsTracer) setTypeConverters() error { // Inject bigint logic. // TODO: To be replaced after goja adds support for native JS bigint. - toBigCode, err := t.vm.RunProgram(bigIntProgram) + toBigCode, err := t.vm.RunProgram(getBigIntProgram()) if err != nil { return err }