Skip to content

feat: add GoJS wasm_exec.js host - #3030

Merged
cpunion merged 4 commits into
xgo-dev:mainfrom
visualfc:feat/gojs-wasm-exec-loader
Nov 11, 2026
Merged

cpunion merged 4 commits into
xgo-dev:mainfrom
visualfc:feat/gojs-wasm-exec-loader

Conversation

@visualfc

@visualfc visualfc commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Add a Go-compatible wasm_exec.js host for standalone GOOS=js GOARCH=wasm builds.
  • Concatenate the Emscripten factory into wasm_exec.js so new Go() works immediately after the script loads, matching official Go.
  • Keep wasm_exec.js for the first program. If another wasm already owns that file, emit stem_wasm_exec.js. Artifact reporting lists only the host this program owns.
  • Register each published host from the lexical LLGoModule (so Node require works) by bare wasm name and resolved URL. new Go() uses the last factory; new Go({ wasm: "app.wasm" }) selects one when unambiguous; a path or URL selects among same-named files in different directories. A later host script only registers its factory and does not redefine Go.
  • Keep -target emscripten, llgo run/test, and explicit -o *.mjs on the existing Emscripten module factory.
  • Provide browser fs, process, and path fallbacks consistent with Go's loader.
  • Route Emscripten print/printErr through fs.writeSync, so callers can hook globalThis.fs.

Validation

  • go test ./internal/build -run 'TestGoJSLoader|TestPublishGoJS|TestCombineGoJS|TestCollectArtifactsGoJS|TestExecuteMainLinkPublishesGoJS|TestGoJSWasmMarker'
  • Node: require("./wasm_exec.js"), new Go(), new Go({ wasm }), WebAssembly.instantiate, go.run(instance)
  • Chrome: syscall/js and browser filesystem ENOSYS

@codecov

codecov Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.71975% with 13 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/build/gojs_loader.go 91.21% 13 Missing ⚠️

📢 Thoughts on this report? Let us know!

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review: GoJS wasm_exec loader

This cleanly splits the GoJS WebAssembly host into a stable checked-in loader (targets/wasm_exec.js) and the emcc-emitted implementation (wasm_exec_app.js), moving the browser fs/process/path fallbacks out of host.c. The needsGoJSLoader predicate is well-guarded and thoroughly table-tested, the crosscompile LDFLAGS are clearly justified, and docs/comments are accurate. Security and documentation passes found no issues.

A few points below are worth addressing before merge. The most important is that the post-link rename of the driver output breaks artifact reporting for GoJS builds.

Artifact reporting is not aware of the GoJS rename (important — out of diff)

publishGoJSLoader renames the emcc driver output (*.mjs) to wasm_exec_app.js, then copies in wasm_exec.js. But CollectArtifacts runs after executeMainLink and still looks for the original .mjs:

  • internal/build/artifact_report.go:109-117 stats emscriptenDriverOutput(conf, out.Out) (the .mjs). For a GoJS -o app.wasm build that .mjs has been renamed away, so os.Stat hits the IsNotExist branch and the glue is silently dropped — and the two sidecars the user actually needs to deploy (wasm_exec_app.js, wasm_exec.js) are never reported.
  • For a GoJS -o app.mjs build, out.Out itself is the renamed-away .mjs, so the primary add(...) at internal/build/artifact_report.go:103 would os.Stat a missing file and return a hard stat ... artifact error when artifact/size reporting is active.

The Emscripten browser-host sidecar already has explicit report wiring (artifact_report.go:128-134); the new GoJS loader/implementation sidecars need equivalent handling so the rename doesn't drop or mis-report deployment artifacts. Please add a focused test for the GoJS reporting path once fixed.

Test coverage of the publish behavior

The three new tests only assert on static wasm_exec.js string contents and the pure path/predicate helpers. None exercise publishGoJSLoader's actual side effects (rename *.mjs → wasm_exec_app.js, copy the loader, no-op when needsGoJSLoader is false, missing LLGO_ROOT error). The sibling publishEmscriptenBrowserHostFrom threads root string as a parameter precisely so the copy is unit-testable without mutating the process environment — extracting an equivalent publishGoJSLoaderFrom(..., root string) seam (see the inline note at gojs_loader.go:51) would let a table test cover these paths, which CLAUDE.md's "features MUST include tests" expects.

Minor

  • targets/wasm_exec.js:95 — loadSidecar uses document.write, which is ignored (or re-parses the document) when wasm_exec.js is loaded async/defer or injected after parse. It's a one-time startup path and document.currentScript is checked, so this is low severity, but a document.head-appended <script> with an onload gate, or at least a comment that wasm_exec.js must be a parser-blocking classic script, would be more robust.

No separate inline comment is duplicated here; see the inline notes for the remaining points.

Comment thread internal/build/gojs_loader.go Resolved
Comment thread internal/build/gojs_loader.go Resolved
Comment thread targets/wasm_exec.js Resolved
@visualfc
visualfc force-pushed the feat/gojs-wasm-exec-loader branch 3 times, most recently from 6805e2f to a756192 Compare November 9, 2026 12:32
@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

LLGo WebAssembly build benchmarks

17b1ae20bca0 | workflow run | long-term charts

WebAssembly output sizes
Example, profile and compiler Wasm module vs base Generated JS glue vs base
cprintf/j32-emscripten/LLGo 155901 B 0 B / +0.0% 88932 B 0 B / +0.0%
cprintf/j32-goos-js/LLGo 154988 B 0 B / +0.0% 72985 B 0 B / +0.0%
cprintf/j64-emscripten-memory64/LLGo 142547 B 0 B / +0.0% 92103 B 0 B / +0.0%
cprintf/w32-goos-wasip1/LLGo 15937 B 0 B / +0.0% 0 B 0 B / 0.0%
cprintf/w32-wasi/LLGo 15937 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/j32-emscripten/LLGo 1634058 B 0 B / +0.0% 119298 B 0 B / +0.0%
fmtprintf/j32-goos-js/Go 2526852 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/j32-goos-js/LLGo 1699156 B 0 B / +0.0% 89510 B +94 B / +0.1% (worse)
fmtprintf/j64-emscripten-memory64/LLGo 1514999 B 0 B / +0.0% 122540 B 0 B / +0.0%
fmtprintf/w32-goos-wasip1/Go 2500019 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/w32-goos-wasip1/LLGo 1075471 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/w32-wasi/LLGo 1076761 B 0 B / +0.0% 0 B 0 B / 0.0%
j32-emscripten/LLGo 155091 B 0 B / +0.0% 88932 B 0 B / +0.0%
j32-goos-js/Go 1895533 B 0 B / +0.0% 0 B 0 B / 0.0%
j32-goos-js/LLGo 154384 B 0 B / +0.0% 72985 B 0 B / +0.0%
j64-emscripten-memory64/LLGo 141748 B 0 B / +0.0% 92103 B 0 B / +0.0%
reflectcall/j32-emscripten/LLGo 1372642 B 0 B / +0.0% 95650 B 0 B / +0.0%
reflectcall/j32-goos-js/Go 2191221 B 0 B / +0.0% 0 B 0 B / 0.0%
reflectcall/j32-goos-js/LLGo 1385471 B 0 B / +0.0% 79699 B 0 B / +0.0%
reflectcall/j64-emscripten-memory64/LLGo 1256911 B 0 B / +0.0% 99450 B 0 B / +0.0%
reflectcall/w32-goos-wasip1/Go 2205707 B 0 B / +0.0% 0 B 0 B / 0.0%
reflectcall/w32-goos-wasip1/LLGo 1042193 B 0 B / +0.0% 0 B 0 B / 0.0%
reflectcall/w32-wasi/LLGo 1043349 B 0 B / +0.0% 0 B 0 B / 0.0%
w32-goos-wasip1/Go 1909947 B 0 B / +0.0% 0 B 0 B / 0.0%
w32-goos-wasip1/LLGo 18855 B 0 B / +0.0% 0 B 0 B / 0.0%
w32-wasi/LLGo 18855 B 0 B / +0.0% 0 B 0 B / 0.0%
LLGo WebAssembly build measurements
Example and profile Build vs base
j32-emscripten 8.123 s +125.1 ms / +1.6% (worse)
j32-goos-js 8.439 s +537 ms / +6.8% (worse)
j64-emscripten-memory64 7.384 s +113.6 ms / +1.6% (worse)
reflectcall/w32-wasi 27.209 s -408.2 ms / -1.5% (better)
w32-goos-wasip1 4.088 s +160.7 ms / +4.1% (worse)
w32-wasi 3.850 s +152.3 ms / +4.1% (worse)

Compared with e2cca2cb8786 measured in the same runner job.

@visualfc
visualfc force-pushed the feat/gojs-wasm-exec-loader branch from a756192 to c43506d Compare November 10, 2026 02:59
@visualfc

Copy link
Copy Markdown
Collaborator Author

@fennoai

@fennoai

fennoai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

All confirmed. This is managed mode, so I return the re-review as my final Markdown message (the platform publishes it). I will not create a PR review or GitHub comment, and I'll keep a clean final summary without a spinner, job link, or completion marker.

Re-review: PR #3030 — GoJS wasm_exec loader

I re-reviewed the updated PR (head c43506d, base 717fbe4) across code quality, performance, security, and documentation. The frontendCache/frontendOpaque churn visible in build.go's history is base-branch movement, not part of this PR — the PR's own build.go diff is just 4 lines.

All three findings from my previous review are addressed and the threads are resolved:

  • Same-file collision guard → publishGoJSLoaderFrom now runs checkGoJSCollision over the driver output, the real .wasm module, the explicit -o file, and the loader source before copying.
  • Testability seam → the logic is now publishGoJSLoaderFrom(..., root string), matching the emscripten_html.go sibling, with real tests for the publish/collision/failure paths.
  • Slow per-decode copy → both wasm_exec.js and host.c now gate a single .slice() copy on growable memory; verified no redundant data copy is reintroduced.

The copy-then-remove ordering (keep the linked artifact until both sidecars succeed) and the artifact-report wiring for the GoJS sidecars both look correct. Security and documentation passes found no issues — the new sync-XHR+eval fallback is not an injection vector (the sidecar name is a module-private constant resolved to a same-origin URL, equivalent to a <script> include of the page's own build artifact), and all comments/headers are accurate.

A few minor, non-blocking polish items remain:

  1. Report vs. publish use different predicates — internal/build/artifact_report.go:135 reports sidecars via needsRawGoJSLoader (no provider check), while publishGoJSLoader keys on needsGoJSLoader (which also requires WasmProvider == GoJS). This is safe today only by coincidence: when conf.Target == "" and GOOS=js, crosscompile always infers WasmProviderGoJS, so the predicates agree. But the comment at artifact_report.go:128 ("same ownership rule as publication") isn't literally true, and if a future change ever let a non-GoJS provider pair with an untargeted GOOS=js build, CollectArtifacts would os.Stat sidecars that publish never created and hard-fail the build. Consider routing report and publish through one shared predicate so the ownership rule can't drift.

  2. Verbose log can misreport a no-op — internal/build/gojs_loader.go:107 always prints copy src -> loader, but if the build output dir happens to be $LLGO_ROOT/targets then src == loader and copyFileAtomic short-circuits to a no-op (the on-disk result is still correct). Pathological, cosmetic only.

  3. "app.mjs" magic sentinel — internal/build/gojs_link.go:24 passes a literal "app.mjs" to needsGoJSLoader solely to satisfy the .mjs ext check, deferring the real decision to the conf.OutFile guard. A named constant or a one-line comment ("any .mjs sentinel works; the OutFile ext guard is the real gate") would make the intent robust.

  4. Redundant nil check — needsRawGoJSLoader checks conf != nil twice (gojs_loader.go:39 and :45); a single early if conf == nil { return false } would read cleaner and match the sibling style in needsEmscriptenBrowserHost.

  5. Sync-XHR fallback is startup-only but blocking — targets/wasm_exec.js:113-119 uses deprecated synchronous XMLHttpRequest + eval when document.write isn't viable (async/defer script or post-parse injection). It's necessary to preserve the synchronous new Go() contract and runs at most once, but on a cold cache it stalls the main thread for the glue download. A doc note steering consumers toward a classic in-parse <script> (the fast document.write branch) would help.

Note: I couldn't execute the test suite — this review environment lacks the LLVM/Emscripten toolchain internal/build needs to compile. Findings are grounded in direct code-path tracing (confirmed the predicate-inference that makes #1 safe today, and the copy/remove/report ordering).

Nice work on the revision — the collision handling and failure-ordering are notably more robust than the first pass. None of the above blocks merge.

View task

@visualfc
visualfc force-pushed the feat/gojs-wasm-exec-loader branch 2 times, most recently from b2a9ae3 to bad0466 Compare November 10, 2026 03:40

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

基于 bad0466 的 diff 和实际 Wasm 执行复核:以下 4 个问题均已复现,其中固定 sidecar 覆盖是本轮补充发现。相关 Go 单元测试通过,但目前缺少这些端到端行为的断言。

Comment thread targets/wasm_exec.js Outdated
Comment on lines +188 to +190
this._module = await this._factoryPromise;
this._module.callMain(this.argv.slice(1));
return 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 等待 Go 程序真正退出后再完成 run()

callMain() 在 Asyncify 遇到 time.Sleep、定时器或异步 JS 回调时会先返回,不能用它的首次返回作为程序结束信号。使用实际构建的 Wasm,在 Node 和 Chrome 中运行 println("started"); time.Sleep(100*time.Millisecond); println("finished"),观察到 started → await go.run(instance) 返回 → finished;官方 Go 则在 finished 后才完成 run()。这会让调用方提前释放资源或开始下一轮执行。请将 run() 的 Promise 接到真实退出通知,并增加包含异步挂起的执行测试;仅把这里改成 await callMain(...) 也无法等待 Asyncify 的后续恢复。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。run() 在 callMain 返回后若 Asyncify 仍挂起会等到 currData 清空,再完成 Promise。TestGoJSLoaderJavaScript 里加了模拟 Sleep 的执行测试。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 652e6d458。使用最新编译器生成真实 Wasm,Node 和 Chrome 均观察到 started → finished → exit(0) → await go.run 完成,此项已修复。Asyncify/stackAlloc 也确实由当前 EXPORT_ALL 配置暴露。

Comment thread targets/wasm_exec.js
Comment on lines +166 to 168
onExit: code => {
this.exit(code);
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 补齐 main 正常返回时的 go.exit(0) 通知

这里仅转发 Emscripten 的 onExit,但默认生成的 glue 中 noExitRuntime=true,正常返回的 main 不会触发该钩子;run() 的成功路径也没有调用 this.exit(0)。独立于异步提前返回问题,用一个完全同步、只打印 os.Args 后返回的程序,在 Node/Chrome 中设置 go.exit = code => records.push(code),执行完后 records 仍为空,官方 Go 会收到一次 0。依赖此回调收集退出状态或释放资源的宿主因此无法正常收尾。请覆盖同步正常返回、异步正常结束和显式 os.Exit,确保每条路径恰好通知一次。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。同步正常返回、Asyncify 结束后的正常返回,以及 ExitStatus(os.Exit)都走 _notifyExit,每种路径只通知一次 go.exit。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 652e6d458。真实产物的同步正常返回、Sleep 后正常结束、Sleep 后 os.Exit(7)、Sleep 后 panic 分别收到一次退出回调,退出码为 0/0/7/2,此项已修复。

Comment thread targets/wasm_exec.js Outdated
if (this.exited) {
this._resolveExitPromise();
this._module = await this._factoryPromise;
this._module.callMain(this.argv.slice(1));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 保留调用方设置的 argv[0]

this.argv.slice(1) 会丢掉调用方指定的程序名,而 Emscripten 的 callMain() 会自行在前面补入默认 thisProgram。实测在 new Go() 后设置 go.argv = ["custom-name", "hello"],Go 中读到的 os.Args 是 ["./this.program", "hello"],而不是官方 Go 的 ["custom-name", "hello"]。这会影响基于 os.Args[0] 的命令分发和程序名解析。请同时将首参数传递给 Emscripten 的程序名配置,并补一个实际执行的参数传递测试。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。改为用 _main(argc, argv) 传入完整 go.argv,不再丢掉 argv[0]。TestGoJSLoaderJavaScript 覆盖了 ["custom-name","hello"]。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 652e6d458。真实 Wasm 在 Node 和 Chrome 中均将 ["custom-name", "hello"] 完整传递到 os.Args,此项已修复。

Comment thread internal/build/gojs_loader.go Outdated
Comment on lines +83 to +84
func goJSImplementationSidecar(output string) string {
return filepath.Join(filepath.Dir(output), goJSImplementationScriptName)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 避免不同 Wasm 程序覆盖同一个实现 sidecar

实现文件只取输出目录,所有程序都会发布到同一个 wasm_exec_app.js,但这份 glue 包含各自 Wasm 专用的 import/export 映射,不能像官方 wasm_exec.js 一样共用。实测依次构建 -o dist/first.wasm(读取 os.Args 的程序)和 -o dist/second.wasm(含 time.Sleep 的程序),两个构建都成功,但第二次会覆盖第一份 glue;随后用该目录的加载器实例化 first.wasm,直接得到 LinkError: Import #24 "a" "y": function import requires a callable。恢复第一份 glue 后同一 Wasm 又能正常运行。请给每个程序保留对应的实现文件并让加载器选择,或在确实只能一目录一程序时明确检测并拒绝跨程序覆盖;目前会静默破坏此前成功构建的产物,多 main 包输出到同一目录时也存在同样问题。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。单程序只写带 // llgo-wasm: 标记的 wasm_exec_app.js。同名重编覆盖该文件;同目录第二份程序不覆盖,改为写 stem.exec.js。加载第二份程序时请显式指定 glue,例如 new Go({ glue: "other.exec.js" }) 或先 <script src="other.exec.js">。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 652e6d458,同目录顺序构建两个新程序后,第一份 shared glue 得以保留,第二份 second.exec.js 预加载后通过 new Go() 可以运行。另在新版代码上提交了两条具体反馈,分别涉及无标记旧产物的原地重编仍默认选错 glue,以及显式 new Go({ glue }) 在预加载完成后仍无条件抛错。

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

继续检查延迟加载分支,补充一个已在真实 Chrome 中验证的 CSP 兼容性问题。

Comment thread targets/wasm_exec.js Outdated
if (xhr.status !== 0 && (xhr.status < 200 || xhr.status >= 300)) {
throw new Error(`LLGo: failed to load ${name}: HTTP ${xhr.status}`);
}
(0, eval)(xhr.responseText);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 延迟加载不要依赖 CSP 禁止的字符串 eval

使用 defer/async 或解析后注入加载器时,这个分支会对配套脚本执行间接 eval,因此常见的 CSP script-src 'self' 'wasm-unsafe-eval' 仍会阻止初始化:wasm-unsafe-eval 只允许 Wasm 编译,不允许 JS 字符串执行。已在真实 Chrome 中复现:同源 <script defer src="wasm_exec.js"> 抛出 EvalError,后续 Go 构造器没有注册;相同产物不设 CSP 时能启动,使用普通解析期 script 标签时也能在同一 CSP 下启动。官方 Go 加载器不要求放开 'unsafe-eval'。请通过外部 script 的加载完成信号衔接初始化(或提供明确的预加载 API),避免让本 PR 新增的延迟加载路径要求放宽站点 CSP,并增加实际浏览器的 CSP 用例。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。动态加载改为插入经典 <script>,不再 eval。解析后注入 wasm_exec.js 时请先 await Go.ready 再 new Go()。测试断言加载器源码不含 eval(。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 652e6d458。真实 Chrome 中使用 defer 加载、await Go.ready 和 script-src 'self' 'wasm-unsafe-eval' 可以启动并正常退出,eval 导致的 CSP 问题已修复。

@github-actions

Copy link
Copy Markdown

LLGo baseline benchmarks

652e6d458ce5 | workflow run | long-term charts

String equality benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkStringEquality/bytes/equal/1024/Go 25.800 ns/op -0.01 ns/op / -0.03874% (better)
Linux BenchmarkStringEquality/bytes/equal/1024/LLGo 62.620 ns/op +0.08 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/bytes/equal/128/Go 9.223 ns/op +0.289 ns/op / +3.2% (worse)
Linux BenchmarkStringEquality/bytes/equal/128/LLGo 11.930 ns/op 0 ns/op / +0.0%
Linux BenchmarkStringEquality/bytes/equal/8/Go 5.851 ns/op +0.03 ns/op / +0.5% (worse)
Linux BenchmarkStringEquality/bytes/equal/8/LLGo 7.032 ns/op +2.76 ns/op / +64.6% (worse)
Linux BenchmarkStringEquality/bytes/first/1024/Go 6.621 ns/op +0.02 ns/op / +0.3% (worse)
Linux BenchmarkStringEquality/bytes/first/1024/LLGo 2.741 ns/op -0.015 ns/op / -0.5% (better)
Linux BenchmarkStringEquality/bytes/first/128/Go 6.640 ns/op +0.012 ns/op / +0.2% (worse)
Linux BenchmarkStringEquality/bytes/first/128/LLGo 2.727 ns/op +0.004 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/bytes/first/8/Go 5.836 ns/op +0.014 ns/op / +0.2% (worse)
Linux BenchmarkStringEquality/bytes/first/8/LLGo 2.725 ns/op +0.004 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/bytes/last/1024/Go 25.120 ns/op +0.03 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/bytes/last/1024/LLGo 62.570 ns/op -0.09 ns/op / -0.1% (better)
Linux BenchmarkStringEquality/bytes/last/128/Go 8.151 ns/op -0.003 ns/op / -0.03679% (better)
Linux BenchmarkStringEquality/bytes/last/128/LLGo 11.840 ns/op +0.02 ns/op / +0.2% (worse)
Linux BenchmarkStringEquality/bytes/last/8/Go 5.969 ns/op +0.15 ns/op / +2.6% (worse)
Linux BenchmarkStringEquality/bytes/last/8/LLGo 3.520 ns/op +0.021 ns/op / +0.6% (worse)
Linux BenchmarkStringEquality/strings/equal/1024/Go 23.220 ns/op -23.63 ns/op / -50.4% (better)
Linux BenchmarkStringEquality/strings/equal/1024/LLGo 55.120 ns/op +0.34 ns/op / +0.6% (worse)
Linux BenchmarkStringEquality/strings/equal/128/Go 8.239 ns/op -1.03 ns/op / -11.1% (better)
Linux BenchmarkStringEquality/strings/equal/128/LLGo 11.200 ns/op -0.04 ns/op / -0.4% (better)
Linux BenchmarkStringEquality/strings/equal/8/Go 5.839 ns/op +0.009 ns/op / +0.2% (worse)
Linux BenchmarkStringEquality/strings/equal/8/LLGo 4.383 ns/op +0.11 ns/op / +2.6% (worse)
Linux BenchmarkStringEquality/strings/first/1024/Go 6.606 ns/op +0.006 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/strings/first/1024/LLGo 3.497 ns/op +0.01 ns/op / +0.3% (worse)
Linux BenchmarkStringEquality/strings/first/128/Go 6.621 ns/op +0.002 ns/op / +0.03022% (worse)
Linux BenchmarkStringEquality/strings/first/128/LLGo 3.508 ns/op +0.003 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/strings/first/8/Go 5.833 ns/op +0.015 ns/op / +0.3% (worse)
Linux BenchmarkStringEquality/strings/first/8/LLGo 5.129 ns/op +1.63 ns/op / +46.6% (worse)
Linux BenchmarkStringEquality/strings/last/1024/Go 22.740 ns/op +0.12 ns/op / +0.5% (worse)
Linux BenchmarkStringEquality/strings/last/1024/LLGo 54.610 ns/op +0.07 ns/op / +0.1% (worse)
Linux BenchmarkStringEquality/strings/last/128/Go 8.157 ns/op -0.014 ns/op / -0.2% (better)
Linux BenchmarkStringEquality/strings/last/128/LLGo 11.050 ns/op -0.08 ns/op / -0.7% (better)
Linux BenchmarkStringEquality/strings/last/8/Go 5.832 ns/op +0.017 ns/op / +0.3% (worse)
Linux BenchmarkStringEquality/strings/last/8/LLGo 4.288 ns/op -0.238 ns/op / -5.3% (better)
macOS BenchmarkStringEquality/bytes/equal/1024/Go 24.450 ns/op -9.43 ns/op / -27.8% (better)
macOS BenchmarkStringEquality/bytes/equal/1024/LLGo 24.600 ns/op -4.36 ns/op / -15.1% (better)
macOS BenchmarkStringEquality/bytes/equal/128/Go 6.031 ns/op -0.258 ns/op / -4.1% (better)
macOS BenchmarkStringEquality/bytes/equal/128/LLGo 5.151 ns/op -3.579 ns/op / -41.0% (better)
macOS BenchmarkStringEquality/bytes/equal/8/Go 3.506 ns/op -0.111 ns/op / -3.1% (better)
macOS BenchmarkStringEquality/bytes/equal/8/LLGo 2.724 ns/op -0.518 ns/op / -16.0% (better)
macOS BenchmarkStringEquality/bytes/first/1024/Go 4.175 ns/op -0.449 ns/op / -9.7% (better)
macOS BenchmarkStringEquality/bytes/first/1024/LLGo 1.782 ns/op -0.053 ns/op / -2.9% (better)
macOS BenchmarkStringEquality/bytes/first/128/Go 3.870 ns/op -0.339 ns/op / -8.1% (better)
macOS BenchmarkStringEquality/bytes/first/128/LLGo 1.794 ns/op -0.013 ns/op / -0.7% (better)
macOS BenchmarkStringEquality/bytes/first/8/Go 3.521 ns/op +0.053 ns/op / +1.5% (worse)
macOS BenchmarkStringEquality/bytes/first/8/LLGo 1.694 ns/op -0.268 ns/op / -13.7% (better)
macOS BenchmarkStringEquality/bytes/last/1024/Go 25.310 ns/op -5.79 ns/op / -18.6% (better)
macOS BenchmarkStringEquality/bytes/last/1024/LLGo 24.010 ns/op -3.47 ns/op / -12.6% (better)
macOS BenchmarkStringEquality/bytes/last/128/Go 5.111 ns/op -0.694 ns/op / -12.0% (better)
macOS BenchmarkStringEquality/bytes/last/128/LLGo 4.188 ns/op -0.294 ns/op / -6.6% (better)
macOS BenchmarkStringEquality/bytes/last/8/Go 3.704 ns/op -0.164 ns/op / -4.2% (better)
macOS BenchmarkStringEquality/bytes/last/8/LLGo 2.473 ns/op -0.273 ns/op / -9.9% (better)
macOS BenchmarkStringEquality/strings/equal/1024/Go 24.870 ns/op -4.67 ns/op / -15.8% (better)
macOS BenchmarkStringEquality/strings/equal/1024/LLGo 24.150 ns/op -3.93 ns/op / -14.0% (better)
macOS BenchmarkStringEquality/strings/equal/128/Go 5.911 ns/op -0.059 ns/op / -1.0% (better)
macOS BenchmarkStringEquality/strings/equal/128/LLGo 5.134 ns/op +0.308 ns/op / +6.4% (worse)
macOS BenchmarkStringEquality/strings/equal/8/Go 3.574 ns/op +0.006 ns/op / +0.2% (worse)
macOS BenchmarkStringEquality/strings/equal/8/LLGo 2.765 ns/op -0.252 ns/op / -8.4% (better)
macOS BenchmarkStringEquality/strings/first/1024/Go 3.837 ns/op -0.39 ns/op / -9.2% (better)
macOS BenchmarkStringEquality/strings/first/1024/LLGo 1.797 ns/op -0.143 ns/op / -7.4% (better)
macOS BenchmarkStringEquality/strings/first/128/Go 3.965 ns/op -0.191 ns/op / -4.6% (better)
macOS BenchmarkStringEquality/strings/first/128/LLGo 1.648 ns/op -0.257 ns/op / -13.5% (better)
macOS BenchmarkStringEquality/strings/first/8/Go 3.500 ns/op -0.062 ns/op / -1.7% (better)
macOS BenchmarkStringEquality/strings/first/8/LLGo 1.718 ns/op -0.125 ns/op / -6.8% (better)
macOS BenchmarkStringEquality/strings/last/1024/Go 24.220 ns/op -3.2 ns/op / -11.7% (better)
macOS BenchmarkStringEquality/strings/last/1024/LLGo 23.750 ns/op -1.79 ns/op / -7.0% (better)
macOS BenchmarkStringEquality/strings/last/128/Go 5.319 ns/op -0.432 ns/op / -7.5% (better)
macOS BenchmarkStringEquality/strings/last/128/LLGo 3.922 ns/op -0.551 ns/op / -12.3% (better)
macOS BenchmarkStringEquality/strings/last/8/Go 3.643 ns/op -0.587 ns/op / -13.9% (better)
macOS BenchmarkStringEquality/strings/last/8/LLGo 2.377 ns/op -0.23 ns/op / -8.8% (better)
Windows MinGW BenchmarkStringEquality/bytes/equal/1024/Go 20.490 ns/op -2.08 ns/op / -9.2% (better)
Windows MinGW BenchmarkStringEquality/bytes/equal/1024/LLGo 36.570 ns/op -0.5 ns/op / -1.3% (better)
Windows MinGW BenchmarkStringEquality/bytes/equal/128/Go 7.131 ns/op -0.402 ns/op / -5.3% (better)
Windows MinGW BenchmarkStringEquality/bytes/equal/128/LLGo 8.052 ns/op -0.14 ns/op / -1.7% (better)
Windows MinGW BenchmarkStringEquality/bytes/equal/8/Go 5.815 ns/op +0.442 ns/op / +8.2% (worse)
Windows MinGW BenchmarkStringEquality/bytes/equal/8/LLGo 4.225 ns/op -0.05 ns/op / -1.2% (better)
Windows MinGW BenchmarkStringEquality/bytes/first/1024/Go 5.471 ns/op -0.04 ns/op / -0.7% (better)
Windows MinGW BenchmarkStringEquality/bytes/first/1024/LLGo 2.942 ns/op +0.005 ns/op / +0.2% (worse)
Windows MinGW BenchmarkStringEquality/bytes/first/128/Go 5.272 ns/op -0.263 ns/op / -4.8% (better)
Windows MinGW BenchmarkStringEquality/bytes/first/128/LLGo 2.949 ns/op -0.033 ns/op / -1.1% (better)
Windows MinGW BenchmarkStringEquality/bytes/first/8/Go 5.032 ns/op -0.41 ns/op / -7.5% (better)
Windows MinGW BenchmarkStringEquality/bytes/first/8/LLGo 3.005 ns/op +0.095 ns/op / +3.3% (worse)
Windows MinGW BenchmarkStringEquality/bytes/last/1024/Go 20.170 ns/op -0.38 ns/op / -1.8% (better)
Windows MinGW BenchmarkStringEquality/bytes/last/1024/LLGo 36.870 ns/op +0.25 ns/op / +0.7% (worse)
Windows MinGW BenchmarkStringEquality/bytes/last/128/Go 6.262 ns/op -0.124 ns/op / -1.9% (better)
Windows MinGW BenchmarkStringEquality/bytes/last/128/LLGo 7.734 ns/op -0.006 ns/op / -0.1% (better)
Windows MinGW BenchmarkStringEquality/bytes/last/8/Go 5.076 ns/op -0.249 ns/op / -4.7% (better)
Windows MinGW BenchmarkStringEquality/bytes/last/8/LLGo 3.637 ns/op -0.914 ns/op / -20.1% (better)
Windows MinGW BenchmarkStringEquality/strings/equal/1024/Go 16.530 ns/op -0.07 ns/op / -0.4% (better)
Windows MinGW BenchmarkStringEquality/strings/equal/1024/LLGo 32.380 ns/op -0.04 ns/op / -0.1% (better)
Windows MinGW BenchmarkStringEquality/strings/equal/128/Go 7.252 ns/op -0.177 ns/op / -2.4% (better)
Windows MinGW BenchmarkStringEquality/strings/equal/128/LLGo 6.945 ns/op +0.03 ns/op / +0.4% (worse)
Windows MinGW BenchmarkStringEquality/strings/equal/8/Go 5.228 ns/op -0.186 ns/op / -3.4% (better)
Windows MinGW BenchmarkStringEquality/strings/equal/8/LLGo 3.659 ns/op 0 ns/op / +0.0%
Windows MinGW BenchmarkStringEquality/strings/first/1024/Go 5.238 ns/op -1.01 ns/op / -16.2% (better)
Windows MinGW BenchmarkStringEquality/strings/first/1024/LLGo 2.293 ns/op +0.019 ns/op / +0.8% (worse)
Windows MinGW BenchmarkStringEquality/strings/first/128/Go 5.289 ns/op -0.171 ns/op / -3.1% (better)
Windows MinGW BenchmarkStringEquality/strings/first/128/LLGo 2.346 ns/op +0.023 ns/op / +1.0% (worse)
Windows MinGW BenchmarkStringEquality/strings/first/8/Go 5.315 ns/op -0.086 ns/op / -1.6% (better)
Windows MinGW BenchmarkStringEquality/strings/first/8/LLGo 2.337 ns/op +0.068 ns/op / +3.0% (worse)
Windows MinGW BenchmarkStringEquality/strings/last/1024/Go 15.790 ns/op +0.04 ns/op / +0.3% (worse)
Windows MinGW BenchmarkStringEquality/strings/last/1024/LLGo 32.040 ns/op +0.11 ns/op / +0.3% (worse)
Windows MinGW BenchmarkStringEquality/strings/last/128/Go 6.626 ns/op -0.146 ns/op / -2.2% (better)
Windows MinGW BenchmarkStringEquality/strings/last/128/LLGo 6.836 ns/op +0.177 ns/op / +2.7% (worse)
Windows MinGW BenchmarkStringEquality/strings/last/8/Go 5.281 ns/op -0.258 ns/op / -4.7% (better)
Windows MinGW BenchmarkStringEquality/strings/last/8/LLGo 3.009 ns/op +0.061 ns/op / +2.1% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/equal/1024/Go 31.540 ns/op -0.15 ns/op / -0.5% (better)
Windows MinGW 386 BenchmarkStringEquality/bytes/equal/1024/LLGo 40.240 ns/op -0.05 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkStringEquality/bytes/equal/128/Go 10.030 ns/op -0.01 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkStringEquality/bytes/equal/128/LLGo 9.239 ns/op -0.003 ns/op / -0.03246% (better)
Windows MinGW 386 BenchmarkStringEquality/bytes/equal/8/Go 7.196 ns/op +0.049 ns/op / +0.7% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/equal/8/LLGo 4.574 ns/op +0.148 ns/op / +3.3% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/first/1024/Go 7.758 ns/op -0.611 ns/op / -7.3% (better)
Windows MinGW 386 BenchmarkStringEquality/bytes/first/1024/LLGo 3.495 ns/op +0.007 ns/op / +0.2% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/first/128/Go 7.782 ns/op +0.314 ns/op / +4.2% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/first/128/LLGo 3.491 ns/op +0.001 ns/op / +0.02865% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/first/8/Go 5.726 ns/op +0.001 ns/op / +0.01747% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/first/8/LLGo 3.489 ns/op 0 ns/op / +0.0%
Windows MinGW 386 BenchmarkStringEquality/bytes/last/1024/Go 31.810 ns/op -0.09 ns/op / -0.3% (better)
Windows MinGW 386 BenchmarkStringEquality/bytes/last/1024/LLGo 39.580 ns/op +0.05 ns/op / +0.1% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/last/128/Go 9.072 ns/op +0.253 ns/op / +2.9% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/last/128/LLGo 8.679 ns/op +0.004 ns/op / +0.04611% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/last/8/Go 7.357 ns/op +0.329 ns/op / +4.7% (worse)
Windows MinGW 386 BenchmarkStringEquality/bytes/last/8/LLGo 4.772 ns/op -0.417 ns/op / -8.0% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/equal/1024/Go 27.820 ns/op -0.31 ns/op / -1.1% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/equal/1024/LLGo 37.220 ns/op +0.08 ns/op / +0.2% (worse)
Windows MinGW 386 BenchmarkStringEquality/strings/equal/128/Go 9.832 ns/op -0.015 ns/op / -0.2% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/equal/128/LLGo 9.223 ns/op -1.707 ns/op / -15.6% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/equal/8/Go 7.729 ns/op -0.14 ns/op / -1.8% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/equal/8/LLGo 4.482 ns/op +0.03 ns/op / +0.7% (worse)
Windows MinGW 386 BenchmarkStringEquality/strings/first/1024/Go 6.818 ns/op -0.23 ns/op / -3.3% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/first/1024/LLGo 3.805 ns/op +0.188 ns/op / +5.2% (worse)
Windows MinGW 386 BenchmarkStringEquality/strings/first/128/Go 6.777 ns/op -0.219 ns/op / -3.1% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/first/128/LLGo 3.603 ns/op 0 ns/op / +0.0%
Windows MinGW 386 BenchmarkStringEquality/strings/first/8/Go 5.463 ns/op +0.025 ns/op / +0.5% (worse)
Windows MinGW 386 BenchmarkStringEquality/strings/first/8/LLGo 3.607 ns/op -0.008 ns/op / -0.2% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/last/1024/Go 25.760 ns/op -0.54 ns/op / -2.1% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/last/1024/LLGo 36.530 ns/op -0.02 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/last/128/Go 8.504 ns/op -0.178 ns/op / -2.1% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/last/128/LLGo 8.347 ns/op -0.009 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/last/8/Go 7.391 ns/op -0.115 ns/op / -1.5% (better)
Windows MinGW 386 BenchmarkStringEquality/strings/last/8/LLGo 4.463 ns/op +0.082 ns/op / +1.9% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/equal/1024/Go 31.110 ns/op -0.53 ns/op / -1.7% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/equal/1024/LLGo 38.900 ns/op -0.14 ns/op / -0.4% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/equal/128/Go 6.658 ns/op -0.02 ns/op / -0.3% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/equal/128/LLGo 7.103 ns/op +0.008 ns/op / +0.1% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/equal/8/Go 3.715 ns/op -0.012 ns/op / -0.3% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/equal/8/LLGo 2.480 ns/op -0.006 ns/op / -0.2% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/first/1024/Go 4.732 ns/op -0.044 ns/op / -0.9% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/first/1024/LLGo 1.603 ns/op +0.03 ns/op / +1.9% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/first/128/Go 4.775 ns/op -0.027 ns/op / -0.6% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/first/128/LLGo 1.592 ns/op 0 ns/op / +0.0%
Windows MinGW ARM64 BenchmarkStringEquality/bytes/first/8/Go 3.545 ns/op +0.139 ns/op / +4.1% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/first/8/LLGo 1.541 ns/op -0.005 ns/op / -0.3% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/last/1024/Go 31.090 ns/op +0.05 ns/op / +0.2% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/last/1024/LLGo 39.390 ns/op -0.09 ns/op / -0.2% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/last/128/Go 6.736 ns/op +0.088 ns/op / +1.3% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/last/128/LLGo 6.835 ns/op +0.001 ns/op / +0.01463% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/last/8/Go 3.447 ns/op -0.107 ns/op / -3.0% (better)
Windows MinGW ARM64 BenchmarkStringEquality/bytes/last/8/LLGo 2.200 ns/op +0.021 ns/op / +1.0% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/equal/1024/Go 27.420 ns/op -0.04 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/equal/1024/LLGo 35.840 ns/op -0.03 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/equal/128/Go 6.160 ns/op +0.079 ns/op / +1.3% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/equal/128/LLGo 5.959 ns/op +0.254 ns/op / +4.5% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/equal/8/Go 3.880 ns/op -0.056 ns/op / -1.4% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/equal/8/LLGo 2.713 ns/op +0.056 ns/op / +2.1% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/first/1024/Go 4.504 ns/op -0.071 ns/op / -1.6% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/first/1024/LLGo 1.594 ns/op +0.022 ns/op / +1.4% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/first/128/Go 4.539 ns/op -0.003 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/first/128/LLGo 1.616 ns/op -0.059 ns/op / -3.5% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/first/8/Go 3.880 ns/op -0.032 ns/op / -0.8% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/first/8/LLGo 1.662 ns/op +0.036 ns/op / +2.2% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/last/1024/Go 27.140 ns/op -0.04 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/last/1024/LLGo 35.620 ns/op -0.07 ns/op / -0.2% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/last/128/Go 5.940 ns/op +0.036 ns/op / +0.6% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/last/128/LLGo 5.483 ns/op +0.01 ns/op / +0.2% (worse)
Windows MinGW ARM64 BenchmarkStringEquality/strings/last/8/Go 3.884 ns/op -0.012 ns/op / -0.3% (better)
Windows MinGW ARM64 BenchmarkStringEquality/strings/last/8/LLGo 1.948 ns/op -0.162 ns/op / -7.7% (better)
Windows MSVC BenchmarkStringEquality/bytes/equal/1024/Go 20 ns/op -0.21 ns/op / -1.0% (better)
Windows MSVC BenchmarkStringEquality/bytes/equal/1024/LLGo 45.590 ns/op +2.47 ns/op / +5.7% (worse)
Windows MSVC BenchmarkStringEquality/bytes/equal/128/Go 7.503 ns/op -0.069 ns/op / -0.9% (better)
Windows MSVC BenchmarkStringEquality/bytes/equal/128/LLGo 11.610 ns/op -0.08 ns/op / -0.7% (better)
Windows MSVC BenchmarkStringEquality/bytes/equal/8/Go 5.924 ns/op +0.006 ns/op / +0.1% (worse)
Windows MSVC BenchmarkStringEquality/bytes/equal/8/LLGo 4.990 ns/op +0.036 ns/op / +0.7% (worse)
Windows MSVC BenchmarkStringEquality/bytes/first/1024/Go 5.913 ns/op -0.271 ns/op / -4.4% (better)
Windows MSVC BenchmarkStringEquality/bytes/first/1024/LLGo 3.776 ns/op +0.069 ns/op / +1.9% (worse)
Windows MSVC BenchmarkStringEquality/bytes/first/128/Go 5.935 ns/op -0.068 ns/op / -1.1% (better)
Windows MSVC BenchmarkStringEquality/bytes/first/128/LLGo 3.706 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkStringEquality/bytes/first/8/Go 5.959 ns/op -0.109 ns/op / -1.8% (better)
Windows MSVC BenchmarkStringEquality/bytes/first/8/LLGo 3.708 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkStringEquality/bytes/last/1024/Go 19.490 ns/op -0.03 ns/op / -0.2% (better)
Windows MSVC BenchmarkStringEquality/bytes/last/1024/LLGo 41 ns/op +0.03 ns/op / +0.1% (worse)
Windows MSVC BenchmarkStringEquality/bytes/last/128/Go 6.548 ns/op +0.024 ns/op / +0.4% (worse)
Windows MSVC BenchmarkStringEquality/bytes/last/128/LLGo 11.770 ns/op -0.1 ns/op / -0.8% (better)
Windows MSVC BenchmarkStringEquality/bytes/last/8/Go 5.929 ns/op +0.063 ns/op / +1.1% (worse)
Windows MSVC BenchmarkStringEquality/bytes/last/8/LLGo 4.326 ns/op -0.017 ns/op / -0.4% (better)
Windows MSVC BenchmarkStringEquality/strings/equal/1024/Go 20.160 ns/op +0.04 ns/op / +0.2% (worse)
Windows MSVC BenchmarkStringEquality/strings/equal/1024/LLGo 37.760 ns/op -0.09 ns/op / -0.2% (better)
Windows MSVC BenchmarkStringEquality/strings/equal/128/Go 7.566 ns/op +0.085 ns/op / +1.1% (worse)
Windows MSVC BenchmarkStringEquality/strings/equal/128/LLGo 7.024 ns/op +0.093 ns/op / +1.3% (worse)
Windows MSVC BenchmarkStringEquality/strings/equal/8/Go 6.309 ns/op -0.315 ns/op / -4.8% (better)
Windows MSVC BenchmarkStringEquality/strings/equal/8/LLGo 3.709 ns/op -0.132 ns/op / -3.4% (better)
Windows MSVC BenchmarkStringEquality/strings/first/1024/Go 6.004 ns/op -0.004 ns/op / -0.1% (better)
Windows MSVC BenchmarkStringEquality/strings/first/1024/LLGo 2.467 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkStringEquality/strings/first/128/Go 6.015 ns/op -0.076 ns/op / -1.2% (better)
Windows MSVC BenchmarkStringEquality/strings/first/128/LLGo 2.468 ns/op -0.042 ns/op / -1.7% (better)
Windows MSVC BenchmarkStringEquality/strings/first/8/Go 5.953 ns/op +0.005 ns/op / +0.1% (worse)
Windows MSVC BenchmarkStringEquality/strings/first/8/LLGo 2.469 ns/op -0.009 ns/op / -0.4% (better)
Windows MSVC BenchmarkStringEquality/strings/last/1024/Go 19.580 ns/op +0.16 ns/op / +0.8% (worse)
Windows MSVC BenchmarkStringEquality/strings/last/1024/LLGo 36.900 ns/op +0.04 ns/op / +0.1% (worse)
Windows MSVC BenchmarkStringEquality/strings/last/128/Go 6.554 ns/op -0.056 ns/op / -0.8% (better)
Windows MSVC BenchmarkStringEquality/strings/last/128/LLGo 6.824 ns/op -0.057 ns/op / -0.8% (better)
Windows MSVC BenchmarkStringEquality/strings/last/8/Go 5.906 ns/op -0.019 ns/op / -0.3% (better)
Windows MSVC BenchmarkStringEquality/strings/last/8/LLGo 3.088 ns/op +0.001 ns/op / +0.03239% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/equal/1024/Go 26.460 ns/op +0.04 ns/op / +0.2% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/equal/1024/LLGo 73.070 ns/op -0.01 ns/op / -0.01368% (better)
Windows MSVC 386 BenchmarkStringEquality/bytes/equal/128/Go 8.153 ns/op -0.112 ns/op / -1.4% (better)
Windows MSVC 386 BenchmarkStringEquality/bytes/equal/128/LLGo 13.690 ns/op -0.08 ns/op / -0.6% (better)
Windows MSVC 386 BenchmarkStringEquality/bytes/equal/8/Go 6.085 ns/op -0.429 ns/op / -6.6% (better)
Windows MSVC 386 BenchmarkStringEquality/bytes/equal/8/LLGo 3.899 ns/op +0.025 ns/op / +0.6% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/first/1024/Go 6.723 ns/op +0.056 ns/op / +0.8% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/first/1024/LLGo 3.239 ns/op +0.034 ns/op / +1.1% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/first/128/Go 6.700 ns/op +0.064 ns/op / +1.0% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/first/128/LLGo 3.203 ns/op -0.005 ns/op / -0.2% (better)
Windows MSVC 386 BenchmarkStringEquality/bytes/first/8/Go 6.007 ns/op +0.048 ns/op / +0.8% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/first/8/LLGo 3.209 ns/op 0 ns/op / +0.0%
Windows MSVC 386 BenchmarkStringEquality/bytes/last/1024/Go 26.110 ns/op +0.14 ns/op / +0.5% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/last/1024/LLGo 73.120 ns/op +0.32 ns/op / +0.4% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/last/128/Go 7.926 ns/op +0.006 ns/op / +0.1% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/last/128/LLGo 13.330 ns/op -0.05 ns/op / -0.4% (better)
Windows MSVC 386 BenchmarkStringEquality/bytes/last/8/Go 6.290 ns/op +0.167 ns/op / +2.7% (worse)
Windows MSVC 386 BenchmarkStringEquality/bytes/last/8/LLGo 3.623 ns/op +0.019 ns/op / +0.5% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/equal/1024/Go 23.790 ns/op +0.11 ns/op / +0.5% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/equal/1024/LLGo 74.080 ns/op +0.08 ns/op / +0.1% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/equal/128/Go 7.730 ns/op -0.038 ns/op / -0.5% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/equal/128/LLGo 13.610 ns/op +0.1 ns/op / +0.7% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/equal/8/Go 6.195 ns/op +0.132 ns/op / +2.2% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/equal/8/LLGo 3.778 ns/op +0.005 ns/op / +0.1% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/first/1024/Go 6.348 ns/op +0.013 ns/op / +0.2% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/first/1024/LLGo 3.203 ns/op -0.001 ns/op / -0.03121% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/first/128/Go 6.354 ns/op -0.02 ns/op / -0.3% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/first/128/LLGo 3.203 ns/op -0.007 ns/op / -0.2% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/first/8/Go 5.495 ns/op -0.067 ns/op / -1.2% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/first/8/LLGo 3.203 ns/op -0.035 ns/op / -1.1% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/last/1024/Go 23.090 ns/op -0.01 ns/op / -0.04329% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/last/1024/LLGo 81.910 ns/op +8.39 ns/op / +11.4% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/last/128/Go 7.486 ns/op +0.028 ns/op / +0.4% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/last/128/LLGo 13.180 ns/op -0.18 ns/op / -1.3% (better)
Windows MSVC 386 BenchmarkStringEquality/strings/last/8/Go 6.238 ns/op +0.151 ns/op / +2.5% (worse)
Windows MSVC 386 BenchmarkStringEquality/strings/last/8/LLGo 3.586 ns/op -0.017 ns/op / -0.5% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/equal/1024/Go 31.120 ns/op -0.15 ns/op / -0.5% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/equal/1024/LLGo 40.120 ns/op +1.34 ns/op / +3.5% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/equal/128/Go 6.730 ns/op +0.004 ns/op / +0.1% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/equal/128/LLGo 7 ns/op +0.014 ns/op / +0.2% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/equal/8/Go 3.714 ns/op -0.014 ns/op / -0.4% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/equal/8/LLGo 2.722 ns/op -0.006 ns/op / -0.2% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/first/1024/Go 4.899 ns/op +0.162 ns/op / +3.4% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/first/1024/LLGo 1.609 ns/op -0.013 ns/op / -0.8% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/first/128/Go 4.785 ns/op +0.014 ns/op / +0.3% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/first/128/LLGo 1.641 ns/op +0.001 ns/op / +0.1% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/first/8/Go 3.382 ns/op -0.163 ns/op / -4.6% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/first/8/LLGo 1.603 ns/op -0.015 ns/op / -0.9% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/last/1024/Go 33.660 ns/op +2.62 ns/op / +8.4% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/last/1024/LLGo 39.870 ns/op +0.9 ns/op / +2.3% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/last/128/Go 6.623 ns/op -0.054 ns/op / -0.8% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/last/128/LLGo 6.736 ns/op -0.074 ns/op / -1.1% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/last/8/Go 3.319 ns/op -0.226 ns/op / -6.4% (better)
Windows MSVC ARM64 BenchmarkStringEquality/bytes/last/8/LLGo 2.258 ns/op +0.027 ns/op / +1.2% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/equal/1024/Go 27.520 ns/op +0.09 ns/op / +0.3% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/equal/1024/LLGo 37.300 ns/op +1.48 ns/op / +4.1% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/equal/128/Go 6.053 ns/op -0.011 ns/op / -0.2% (better)
Windows MSVC ARM64 BenchmarkStringEquality/strings/equal/128/LLGo 5.937 ns/op +0.117 ns/op / +2.0% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/equal/8/Go 3.892 ns/op -0.018 ns/op / -0.5% (better)
Windows MSVC ARM64 BenchmarkStringEquality/strings/equal/8/LLGo 2.465 ns/op +0.026 ns/op / +1.1% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/first/1024/Go 4.546 ns/op +0.04 ns/op / +0.9% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/first/1024/LLGo 1.783 ns/op +0.067 ns/op / +3.9% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/first/128/Go 4.761 ns/op +0.211 ns/op / +4.6% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/first/128/LLGo 1.743 ns/op +0.006 ns/op / +0.3% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/first/8/Go 3.867 ns/op -0.008 ns/op / -0.2% (better)
Windows MSVC ARM64 BenchmarkStringEquality/strings/first/8/LLGo 1.785 ns/op +0.065 ns/op / +3.8% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/last/1024/Go 28.320 ns/op +1.19 ns/op / +4.4% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/last/1024/LLGo 35.620 ns/op +0.3 ns/op / +0.8% (worse)
Windows MSVC ARM64 BenchmarkStringEquality/strings/last/128/Go 5.920 ns/op -0.02 ns/op / -0.3% (better)
Windows MSVC ARM64 BenchmarkStringEquality/strings/last/128/LLGo 5.496 ns/op -0.019 ns/op / -0.3% (better)
Windows MSVC ARM64 BenchmarkStringEquality/strings/last/8/Go 3.855 ns/op -0.008 ns/op / -0.2% (better)
Windows MSVC ARM64 BenchmarkStringEquality/strings/last/8/LLGo 2.213 ns/op +0.062 ns/op / +2.9% (worse)

Program measurements

Platform Workload File size vs base Text size vs base Build vs base Run vs base
Linux cprintf 8576 B 0 B / +0.0% 387 B 0 B / +0.0% 1.111 s +5.729 ms / +0.5% (worse) 1.349 ms -15.3 us / -1.1% (better)
Linux cprintf-lto 8240 B 0 B / +0.0% 368 B 0 B / +0.0% 1.114 s -19.49 ms / -1.7% (better) 1.319 ms -31.47 us / -2.3% (better)
Linux fmtprintf 1943824 B +64 B / +0.003293% (worse) 269976 B 0 B / +0.0% 6.952 s -32.72 ms / -0.5% (better) 3.262 ms -179.5 us / -5.2% (better)
Linux fmtprintf-lto 1019880 B +8 B / +0.0007844% (worse) 210891 B 0 B / +0.0% 16.847 s +1.322 s / +8.5% (worse) 3.237 ms +175.3 us / +5.7% (worse)
Linux println 260528 B -128 B / -0.04911% (better) 19172 B 0 B / +0.0% 1.131 s -69.12 ms / -5.8% (better) 1.633 ms -7.31 us / -0.4% (better)
Linux println-lto 102688 B +8 B / +0.007791% (worse) 15652 B 0 B / +0.0% 1.817 s -102.2 ms / -5.3% (better) 1.927 ms +231.3 us / +13.6% (worse)
macOS cprintf 50944 B 0 B / +0.0% 4409 B 0 B / +0.0% 1.789 s +425.5 ms / +31.2% (worse) 6.124 ms -425.2 us / -6.5% (better)
macOS cprintf-lto 50608 B 0 B / +0.0% 161 B 0 B / +0.0% 1.530 s +337.4 ms / +28.3% (worse) 3.211 ms -378.5 us / -10.5% (better)
macOS fmtprintf 1233696 B 0 B / +0.0% 676093 B 0 B / +0.0% 6.389 s -3.658 s / -36.4% (better) 4.578 ms -4.852 ms / -51.5% (better)
macOS fmtprintf-lto 871600 B 0 B / +0.0% 521789 B 0 B / +0.0% 11.475 s +1.178 s / +11.4% (worse) 6.564 ms -1.724 ms / -20.8% (better)
macOS println 100592 B 0 B / +0.0% 26375 B 0 B / +0.0% 1.535 s -16.84 ms / -1.1% (better) 7.740 ms +2.697 ms / +53.5% (worse)
macOS println-lto 85632 B 0 B / +0.0% 22491 B 0 B / +0.0% 1.751 s +181.3 ms / +11.5% (worse) 5.493 ms +2.047 ms / +59.4% (worse)
Windows MinGW cprintf 745984 B 0 B / +0.0% 4230 B 0 B / +0.0% 2.004 s -19.71 ms / -1.0% (better) 3.947 ms -260.9 us / -6.2% (better)
Windows MinGW cprintf-lto 60928 B 0 B / +0.0% 4182 B 0 B / +0.0% 2.008 s -45.19 ms / -2.2% (better) 3.990 ms +3.9 us / +0.1% (worse)
Windows MinGW fmtprintf 5156864 B 0 B / +0.0% 362134 B 0 B / +0.0% 6.665 s -4.978 ms / -0.1% (better) 10.955 ms +28.7 us / +0.3% (worse)
Windows MinGW fmtprintf-lto 2764288 B 0 B / +0.0% 308102 B 0 B / +0.0% 11.068 s +168.6 ms / +1.5% (worse) 11.934 ms +919.7 us / +8.4% (worse)
Windows MinGW println 807936 B 0 B / +0.0% 27414 B 0 B / +0.0% 1.984 s -37.53 ms / -1.9% (better) 7.266 ms -55.8 us / -0.8% (better)
Windows MinGW println-lto 233984 B 0 B / +0.0% 22598 B 0 B / +0.0% 2.299 s -57.18 ms / -2.4% (better) 7.316 ms +92.8 us / +1.3% (worse)
Windows MinGW 386 cprintf 752128 B 0 B / +0.0% 22726 B 0 B / +0.0% 2.086 s -58.33 ms / -2.7% (better) 9.790 ms -722.8 us / -6.9% (better)
Windows MinGW 386 cprintf-lto 282112 B 0 B / +0.0% 19504 B 0 B / +0.0% 2.379 s -14.86 ms / -0.6% (better) 9.833 ms -117.3 us / -1.2% (better)
Windows MinGW 386 fmtprintf 4507648 B 0 B / +0.0% 284864 B 0 B / +0.0% 7.356 s +218.8 ms / +3.1% (worse) 13.355 ms -280.6 us / -2.1% (better)
Windows MinGW 386 fmtprintf-lto 2890752 B 0 B / +0.0% 257486 B 0 B / +0.0% 11.558 s -110.1 ms / -0.9% (better) 14.133 ms +547.1 us / +4.0% (worse)
Windows MinGW 386 println 751104 B 0 B / +0.0% 22672 B 0 B / +0.0% 2.110 s +114.7 ms / +5.7% (worse) 11.586 ms +1.54 ms / +15.3% (worse)
Windows MinGW 386 println-lto 281088 B 0 B / +0.0% 19438 B 0 B / +0.0% 2.376 s +10.51 ms / +0.4% (worse) 10.024 ms -1.927 ms / -16.1% (better)
Windows MinGW ARM64 cprintf 751616 B 0 B / +0.0% 4028 B 0 B / +0.0% 2.312 s -9.739 ms / -0.4% (better) 7.043 ms -359.5 us / -4.9% (better)
Windows MinGW ARM64 cprintf-lto 60416 B 0 B / +0.0% 3984 B 0 B / +0.0% 2.372 s +18.28 ms / +0.8% (worse) 7.327 ms -27.6 us / -0.4% (better)
Windows MinGW ARM64 fmtprintf 5096448 B 0 B / +0.0% 302168 B 0 B / +0.0% 6.883 s -26.17 ms / -0.4% (better) 19.167 ms +4.472 ms / +30.4% (worse)
Windows MinGW ARM64 fmtprintf-lto 2818048 B 0 B / +0.0% 258284 B 0 B / +0.0% 10.698 s -14.51 ms / -0.1% (better) 15.893 ms +699.7 us / +4.6% (worse)
Windows MinGW ARM64 println 813056 B 0 B / +0.0% 25604 B 0 B / +0.0% 2.322 s +28.76 ms / +1.3% (worse) 12.631 ms +278 us / +2.3% (worse)
Windows MinGW ARM64 println-lto 237056 B 0 B / +0.0% 21824 B 0 B / +0.0% 2.639 s +46.48 ms / +1.8% (worse) 12.098 ms +108.6 us / +0.9% (worse)
Windows MSVC cprintf 990720 B 0 B / +0.0% 66003 B 0 B / +0.0% 2.021 s +49.72 ms / +2.5% (worse) 3.335 ms -422.7 us / -11.2% (better)
Windows MSVC cprintf-lto 308736 B 0 B / +0.0% 65971 B 0 B / +0.0% 1.965 s -20.05 ms / -1.0% (better) 3.371 ms -382.2 us / -10.2% (better)
Windows MSVC fmtprintf 5455872 B 0 B / +0.0% 458230 B 0 B / +0.0% 6.728 s +246.8 ms / +3.8% (worse) 14.432 ms +3.266 ms / +29.2% (worse)
Windows MSVC fmtprintf-lto 3087872 B 0 B / +0.0% 406662 B 0 B / +0.0% 10.383 s +54.64 ms / +0.5% (worse) 11.602 ms +391.8 us / +3.5% (worse)
Windows MSVC println 1122304 B 0 B / +0.0% 123574 B 0 B / +0.0% 1.983 s -3.268 ms / -0.2% (better) 7.371 ms +39.2 us / +0.5% (worse)
Windows MSVC println-lto 553984 B 0 B / +0.0% 119414 B 0 B / +0.0% 2.218 s -80.96 ms / -3.5% (better) 7.247 ms -973.1 us / -11.8% (better)
Windows MSVC 386 cprintf 661504 B 0 B / +0.0% 21378 B 0 B / +0.0% 1.497 s +33.17 ms / +2.3% (worse) 7.220 ms -969.5 us / -11.8% (better)
Windows MSVC 386 cprintf-lto 221184 B 0 B / +0.0% 18857 B 0 B / +0.0% 1.709 s +48.5 ms / +2.9% (worse) 7.406 ms +194.6 us / +2.7% (worse)
Windows MSVC 386 fmtprintf 4235264 B 0 B / +0.0% 268326 B 0 B / +0.0% 5.230 s +134.2 ms / +2.6% (worse) 10.476 ms +606.6 us / +6.1% (worse)
Windows MSVC 386 fmtprintf-lto 2704384 B 0 B / +0.0% 236961 B 0 B / +0.0% 8.400 s +273.5 ms / +3.4% (worse) 10.229 ms +586.5 us / +6.1% (worse)
Windows MSVC 386 println 658432 B 0 B / +0.0% 21308 B 0 B / +0.0% 1.481 s +24.97 ms / +1.7% (worse) 7.680 ms +466.2 us / +6.5% (worse)
Windows MSVC 386 println-lto 219648 B 0 B / +0.0% 18787 B 0 B / +0.0% 1.702 s +37.4 ms / +2.2% (worse) 7.144 ms -167.9 us / -2.3% (better)
Windows MSVC ARM64 cprintf 754688 B 0 B / +0.0% 4240 B 0 B / +0.0% 2.061 s -33.03 ms / -1.6% (better) 7.160 ms -494 us / -6.5% (better)
Windows MSVC ARM64 cprintf-lto 66048 B 0 B / +0.0% 4140 B 0 B / +0.0% 2.051 s -65.09 ms / -3.1% (better) 7.440 ms -560 us / -7.0% (better)
Windows MSVC ARM64 fmtprintf 5092352 B 0 B / +0.0% 302492 B 0 B / +0.0% 6.540 s +240.1 ms / +3.8% (worse) 16.430 ms +841.7 us / +5.4% (worse)
Windows MSVC ARM64 fmtprintf-lto 2826752 B 0 B / +0.0% 259232 B 0 B / +0.0% 10.189 s +281.7 ms / +2.8% (worse) 17.462 ms +1.11 ms / +6.8% (worse)
Windows MSVC ARM64 println 815616 B 0 B / +0.0% 26084 B 0 B / +0.0% 2.037 s -29.75 ms / -1.4% (better) 12.271 ms -1.21 ms / -9.0% (better)
Windows MSVC ARM64 println-lto 243200 B 0 B / +0.0% 22384 B 0 B / +0.0% 2.284 s -64.38 ms / -2.7% (better) 12.303 ms -629.6 us / -4.9% (better)
Core language and compiler benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkLookupPCRandom 14.480 ns/op +0.05 ns/op / +0.3% (worse)
Linux BenchmarkMergeCompilerFlags 210.500 ns/op -4.4 ns/op / -2.0% (better)
Linux BenchmarkMergeLinkerFlags 139 ns/op -2.3 ns/op / -1.6% (better)
Linux BenchmarkChannelBuffered 73.220 ns/op -0.15 ns/op / -0.2% (better)
Linux BenchmarkChannelHandoff 13820 ns/op -292 ns/op / -2.1% (better)
Linux BenchmarkDefer 16.810 ns/op +0.17 ns/op / +1.0% (worse)
Linux BenchmarkDirectCall 1.565 ns/op +0.003 ns/op / +0.2% (worse)
Linux BenchmarkGlobalRead 1.190 ns/op +0.005 ns/op / +0.4% (worse)
Linux BenchmarkGlobalWrite 8 ns/op +0.21 ns/op / +2.7% (worse)
Linux BenchmarkGoroutine 36525 ns/op +13521 ns/op / +58.8% (worse)
Linux BenchmarkInterfaceCall 5.259 ns/op +0.05 ns/op / +1.0% (worse)
Linux BenchmarkRuntimeGetG 2.465 ns/op -0.069 ns/op / -2.7% (better)
macOS BenchmarkLookupPCRandom 13.610 ns/op -4.99 ns/op / -26.8% (better)
macOS BenchmarkMergeCompilerFlags 114.400 ns/op -62.9 ns/op / -35.5% (better)
macOS BenchmarkMergeLinkerFlags 76.240 ns/op -55.56 ns/op / -42.2% (better)
macOS BenchmarkChannelBuffered 26.210 ns/op -9.39 ns/op / -26.4% (better)
macOS BenchmarkChannelHandoff 7353 ns/op -3635 ns/op / -33.1% (better)
macOS BenchmarkDefer 11.230 ns/op -4.33 ns/op / -27.8% (better)
macOS BenchmarkDirectCall 1.028 ns/op -0.317 ns/op / -23.6% (better)
macOS BenchmarkGlobalRead 1.026 ns/op -0.411 ns/op / -28.6% (better)
macOS BenchmarkGlobalWrite 1.026 ns/op -0.761 ns/op / -42.6% (better)
macOS BenchmarkGoroutine 70778 ns/op -1809 ns/op / -2.5% (better)
macOS BenchmarkInterfaceCall 3.767 ns/op -1.416 ns/op / -27.3% (better)
macOS BenchmarkRuntimeGetG 2.058 ns/op -0.509 ns/op / -19.8% (better)
Windows MinGW BenchmarkLookupPCRandom 11.450 ns/op -0.05 ns/op / -0.4% (better)
Windows MinGW BenchmarkMergeCompilerFlags 572.700 ns/op -5.6 ns/op / -1.0% (better)
Windows MinGW BenchmarkMergeLinkerFlags 506.100 ns/op -14.6 ns/op / -2.8% (better)
Windows MinGW BenchmarkChannelBuffered 58.300 ns/op -0.02 ns/op / -0.03429% (better)
Windows MinGW BenchmarkChannelHandoff 2761 ns/op +598 ns/op / +27.6% (worse)
Windows MinGW BenchmarkDefer 12.660 ns/op -0.06 ns/op / -0.5% (better)
Windows MinGW BenchmarkDirectCall 1.090 ns/op +0.046 ns/op / +4.4% (worse)
Windows MinGW BenchmarkGlobalRead 1.363 ns/op +0.106 ns/op / +8.4% (worse)
Windows MinGW BenchmarkGlobalWrite 8.539 ns/op -0.004 ns/op / -0.04682% (better)
Windows MinGW BenchmarkGoroutine 82517 ns/op +966 ns/op / +1.2% (worse)
Windows MinGW BenchmarkInterfaceCall 5.398 ns/op -0.047 ns/op / -0.9% (better)
Windows MinGW BenchmarkRuntimeGetG 1.391 ns/op +0.023 ns/op / +1.7% (worse)
Windows MinGW 386 BenchmarkLookupPCRandom 68.720 ns/op +0.14 ns/op / +0.2% (worse)
Windows MinGW 386 BenchmarkMergeCompilerFlags 880.300 ns/op -49.3 ns/op / -5.3% (better)
Windows MinGW 386 BenchmarkMergeLinkerFlags 827.900 ns/op -22.7 ns/op / -2.7% (better)
Windows MinGW 386 BenchmarkChannelBuffered 64.710 ns/op -0.15 ns/op / -0.2% (better)
Windows MinGW 386 BenchmarkChannelHandoff 2960 ns/op +1327 ns/op / +81.3% (worse)
Windows MinGW 386 BenchmarkDefer 17.300 ns/op +0.05 ns/op / +0.3% (worse)
Windows MinGW 386 BenchmarkDirectCall 0.866 ns/op -0.0038 ns/op / -0.4% (better)
Windows MinGW 386 BenchmarkGlobalRead 1.154 ns/op -0.002 ns/op / -0.2% (better)
Windows MinGW 386 BenchmarkGlobalWrite 16.130 ns/op -0.04 ns/op / -0.2% (better)
Windows MinGW 386 BenchmarkGoroutine 208215 ns/op +38 ns/op / +0.01825% (worse)
Windows MinGW 386 BenchmarkInterfaceCall 5.744 ns/op -0.014 ns/op / -0.2% (better)
Windows MinGW 386 BenchmarkRuntimeGetG 2.030 ns/op +0.007 ns/op / +0.3% (worse)
Windows MinGW ARM64 BenchmarkLookupPCRandom 12.150 ns/op +0.04 ns/op / +0.3% (worse)
Windows MinGW ARM64 BenchmarkMergeCompilerFlags 557.200 ns/op +5.8 ns/op / +1.1% (worse)
Windows MinGW ARM64 BenchmarkMergeLinkerFlags 528.600 ns/op +2.3 ns/op / +0.4% (worse)
Windows MinGW ARM64 BenchmarkChannelBuffered 43.040 ns/op +0.06 ns/op / +0.1% (worse)
Windows MinGW ARM64 BenchmarkChannelHandoff 1845 ns/op +16 ns/op / +0.9% (worse)
Windows MinGW ARM64 BenchmarkDefer 11.950 ns/op +0.17 ns/op / +1.4% (worse)
Windows MinGW ARM64 BenchmarkDirectCall 0.590 ns/op +0.0003 ns/op / +0.1% (worse)
Windows MinGW ARM64 BenchmarkGlobalRead 0.664 ns/op +0.0004 ns/op / +0.1% (worse)
Windows MinGW ARM64 BenchmarkGlobalWrite 0.663 ns/op -0.0002 ns/op / -0.03015% (better)
Windows MinGW ARM64 BenchmarkGoroutine 62975 ns/op -23 ns/op / -0.03651% (better)
Windows MinGW ARM64 BenchmarkInterfaceCall 3.842 ns/op -0.003 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkRuntimeGetG 1.805 ns/op +0.034 ns/op / +1.9% (worse)
Windows MSVC BenchmarkLookupPCRandom 12.920 ns/op -0.18 ns/op / -1.4% (better)
Windows MSVC BenchmarkMergeCompilerFlags 625.600 ns/op -8.7 ns/op / -1.4% (better)
Windows MSVC BenchmarkMergeLinkerFlags 543.500 ns/op -9.6 ns/op / -1.7% (better)
Windows MSVC BenchmarkChannelBuffered 33.210 ns/op +0.04 ns/op / +0.1% (worse)
Windows MSVC BenchmarkChannelHandoff 623 ns/op +1.9 ns/op / +0.3% (worse)
Windows MSVC BenchmarkDefer 14.310 ns/op -0.02 ns/op / -0.1% (better)
Windows MSVC BenchmarkDirectCall 1.549 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkGlobalRead 1.859 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkGlobalWrite 2.452 ns/op -0.002 ns/op / -0.1% (better)
Windows MSVC BenchmarkGoroutine 92140 ns/op +1178 ns/op / +1.3% (worse)
Windows MSVC BenchmarkInterfaceCall 7.746 ns/op -0.003 ns/op / -0.03871% (better)
Windows MSVC BenchmarkRuntimeGetG 2.168 ns/op 0 ns/op / +0.0%
Windows MSVC 386 BenchmarkLookupPCRandom 21.530 ns/op 0 ns/op / +0.0%
Windows MSVC 386 BenchmarkMergeCompilerFlags 557.200 ns/op -7.6 ns/op / -1.3% (better)
Windows MSVC 386 BenchmarkMergeLinkerFlags 540.900 ns/op +18.2 ns/op / +3.5% (worse)
Windows MSVC 386 BenchmarkChannelBuffered 36.630 ns/op -0.04 ns/op / -0.1% (better)
Windows MSVC 386 BenchmarkChannelHandoff 696.700 ns/op +66.9 ns/op / +10.6% (worse)
Windows MSVC 386 BenchmarkDefer 14.080 ns/op -0.02 ns/op / -0.1% (better)
Windows MSVC 386 BenchmarkDirectCall 1.357 ns/op 0 ns/op / +0.0%
Windows MSVC 386 BenchmarkGlobalRead 1.629 ns/op -0.001 ns/op / -0.1% (better)
Windows MSVC 386 BenchmarkGlobalWrite 6.983 ns/op 0 ns/op / +0.0%
Windows MSVC 386 BenchmarkGoroutine 70555 ns/op -935 ns/op / -1.3% (better)
Windows MSVC 386 BenchmarkInterfaceCall 6.518 ns/op +0.001 ns/op / +0.01534% (worse)
Windows MSVC 386 BenchmarkRuntimeGetG 1.632 ns/op 0 ns/op / +0.0%
Windows MSVC ARM64 BenchmarkLookupPCRandom 12.090 ns/op -0.04 ns/op / -0.3% (better)
Windows MSVC ARM64 BenchmarkMergeCompilerFlags 572 ns/op +22 ns/op / +4.0% (worse)
Windows MSVC ARM64 BenchmarkMergeLinkerFlags 538.900 ns/op +7.3 ns/op / +1.4% (worse)
Windows MSVC ARM64 BenchmarkChannelBuffered 46.920 ns/op -0.03 ns/op / -0.1% (better)
Windows MSVC ARM64 BenchmarkChannelHandoff 1386 ns/op +69 ns/op / +5.2% (worse)
Windows MSVC ARM64 BenchmarkDefer 11.780 ns/op -0.43 ns/op / -3.5% (better)
Windows MSVC ARM64 BenchmarkDirectCall 0.590 ns/op +0.0003 ns/op / +0.1% (worse)
Windows MSVC ARM64 BenchmarkGlobalRead 0.664 ns/op +0.0007 ns/op / +0.1% (worse)
Windows MSVC ARM64 BenchmarkGlobalWrite 3.756 ns/op -0.003 ns/op / -0.1% (better)
Windows MSVC ARM64 BenchmarkGoroutine 59737 ns/op -155 ns/op / -0.3% (better)
Windows MSVC ARM64 BenchmarkInterfaceCall 3.858 ns/op -0.003 ns/op / -0.1% (better)
Windows MSVC ARM64 BenchmarkRuntimeGetG 1.769 ns/op -0.001 ns/op / -0.1% (better)
Timer runtime benchmarks
Platform Operation and runtime ns/op vs base
Linux AfterFuncZeroDelivery/Go 975.300 ns/op +71.5 ns/op / +7.9% (worse)
Linux AfterFuncZeroDelivery/LLGo 40121 ns/op -4167 ns/op / -9.4% (better)
Linux CreateStop/Go 299.500 ns/op +4.4 ns/op / +1.5% (worse)
Linux CreateStop/LLGo 1431 ns/op +27 ns/op / +1.9% (worse)
Linux RearmStopped/Go 116.100 ns/op -1 ns/op / -0.9% (better)
Linux RearmStopped/LLGo 982.500 ns/op -30.5 ns/op / -3.0% (better)
Linux ResetActive/Go 69.230 ns/op +0.34 ns/op / +0.5% (worse)
Linux ResetActive/LLGo 656.700 ns/op +18.5 ns/op / +2.9% (worse)
Linux ResetHeap1024/Go 67.690 ns/op +0.39 ns/op / +0.6% (worse)
Linux ResetHeap1024/LLGo 133.800 ns/op +1.2 ns/op / +0.9% (worse)
macOS AfterFuncZeroDelivery/Go 423.100 ns/op -121.9 ns/op / -22.4% (better)
macOS AfterFuncZeroDelivery/LLGo 68231 ns/op +26135 ns/op / +62.1% (worse)
macOS CreateStop/Go 146.600 ns/op -29.4 ns/op / -16.7% (better)
macOS CreateStop/LLGo 394.600 ns/op +11.1 ns/op / +2.9% (worse)
macOS RearmStopped/Go 60.060 ns/op -7.03 ns/op / -10.5% (better)
macOS RearmStopped/LLGo 218 ns/op -16.1 ns/op / -6.9% (better)
macOS ResetActive/Go 46.300 ns/op -10.9 ns/op / -19.1% (better)
macOS ResetActive/LLGo 122.700 ns/op -27.6 ns/op / -18.4% (better)
macOS ResetHeap1024/Go 46.320 ns/op -2.51 ns/op / -5.1% (better)
macOS ResetHeap1024/LLGo 68.110 ns/op -11.86 ns/op / -14.8% (better)
Windows MinGW AfterFuncZeroDelivery/Go 697.300 ns/op -7.3 ns/op / -1.0% (better)
Windows MinGW AfterFuncZeroDelivery/LLGo 145501 ns/op -5014 ns/op / -3.3% (better)
Windows MinGW CreateStop/Go 186.700 ns/op -11.5 ns/op / -5.8% (better)
Windows MinGW CreateStop/LLGo 1054 ns/op +533.6 ns/op / +102.5% (worse)
Windows MinGW RearmStopped/Go 69.940 ns/op -0.56 ns/op / -0.8% (better)
Windows MinGW RearmStopped/LLGo 265.300 ns/op +20.2 ns/op / +8.2% (worse)
Windows MinGW ResetActive/Go 31 ns/op -0.3 ns/op / -1.0% (better)
Windows MinGW ResetActive/LLGo 256.800 ns/op -181.4 ns/op / -41.4% (better)
Windows MinGW ResetHeap1024/Go 31.410 ns/op -0.19 ns/op / -0.6% (better)
Windows MinGW ResetHeap1024/LLGo 101.300 ns/op +0.6 ns/op / +0.6% (worse)
Windows MinGW 386 AfterFuncZeroDelivery/Go 1130 ns/op +1 ns/op / +0.1% (worse)
Windows MinGW 386 AfterFuncZeroDelivery/LLGo 285945 ns/op -3649 ns/op / -1.3% (better)
Windows MinGW 386 CreateStop/Go 273.700 ns/op -11.9 ns/op / -4.2% (better)
Windows MinGW 386 CreateStop/LLGo 995.100 ns/op -42.9 ns/op / -4.1% (better)
Windows MinGW 386 RearmStopped/Go 92.150 ns/op -0.56 ns/op / -0.6% (better)
Windows MinGW 386 RearmStopped/LLGo 565 ns/op -145.5 ns/op / -20.5% (better)
Windows MinGW 386 ResetActive/Go 46.170 ns/op -0.38 ns/op / -0.8% (better)
Windows MinGW 386 ResetActive/LLGo 511.200 ns/op -105.2 ns/op / -17.1% (better)
Windows MinGW 386 ResetHeap1024/Go 46.410 ns/op -0.09 ns/op / -0.2% (better)
Windows MinGW 386 ResetHeap1024/LLGo 137.400 ns/op -0.4 ns/op / -0.3% (better)
Windows MinGW ARM64 AfterFuncZeroDelivery/Go 654.600 ns/op -27.1 ns/op / -4.0% (better)
Windows MinGW ARM64 AfterFuncZeroDelivery/LLGo 154480 ns/op +3237 ns/op / +2.1% (worse)
Windows MinGW ARM64 CreateStop/Go 194.500 ns/op -5.3 ns/op / -2.7% (better)
Windows MinGW ARM64 CreateStop/LLGo 344.300 ns/op -29.3 ns/op / -7.8% (better)
Windows MinGW ARM64 RearmStopped/Go 70.570 ns/op -0.01 ns/op / -0.01417% (better)
Windows MinGW ARM64 RearmStopped/LLGo 162.500 ns/op -5.7 ns/op / -3.4% (better)
Windows MinGW ARM64 ResetActive/Go 31.140 ns/op 0 ns/op / +0.0%
Windows MinGW ARM64 ResetActive/LLGo 91.830 ns/op -7.62 ns/op / -7.7% (better)
Windows MinGW ARM64 ResetHeap1024/Go 31.140 ns/op 0 ns/op / +0.0%
Windows MinGW ARM64 ResetHeap1024/LLGo 92.380 ns/op +0.49 ns/op / +0.5% (worse)
Windows MSVC AfterFuncZeroDelivery/Go 560.600 ns/op -5.5 ns/op / -1.0% (better)
Windows MSVC AfterFuncZeroDelivery/LLGo 178421 ns/op -2618 ns/op / -1.4% (better)
Windows MSVC CreateStop/Go 116.500 ns/op -1 ns/op / -0.9% (better)
Windows MSVC CreateStop/LLGo 526.200 ns/op +75 ns/op / +16.6% (worse)
Windows MSVC RearmStopped/Go 31.690 ns/op +0.31 ns/op / +1.0% (worse)
Windows MSVC RearmStopped/LLGo 315.100 ns/op +14.7 ns/op / +4.9% (worse)
Windows MSVC ResetActive/Go 20.150 ns/op +0.01 ns/op / +0.04965% (worse)
Windows MSVC ResetActive/LLGo 186.800 ns/op -38 ns/op / -16.9% (better)
Windows MSVC ResetHeap1024/Go 20.530 ns/op +0.08 ns/op / +0.4% (worse)
Windows MSVC ResetHeap1024/LLGo 102.700 ns/op -0.8 ns/op / -0.8% (better)
Windows MSVC 386 AfterFuncZeroDelivery/Go 767.700 ns/op -6.5 ns/op / -0.8% (better)
Windows MSVC 386 AfterFuncZeroDelivery/LLGo 131208 ns/op -755 ns/op / -0.6% (better)
Windows MSVC 386 CreateStop/Go 169.200 ns/op +3.3 ns/op / +2.0% (worse)
Windows MSVC 386 CreateStop/LLGo 367.200 ns/op -23.3 ns/op / -6.0% (better)
Windows MSVC 386 RearmStopped/Go 56.700 ns/op +0.12 ns/op / +0.2% (worse)
Windows MSVC 386 RearmStopped/LLGo 251.500 ns/op -74.2 ns/op / -22.8% (better)
Windows MSVC 386 ResetActive/Go 32.530 ns/op -0.09 ns/op / -0.3% (better)
Windows MSVC 386 ResetActive/LLGo 891.800 ns/op -3.8 ns/op / -0.4% (better)
Windows MSVC 386 ResetHeap1024/Go 32.820 ns/op +0.03 ns/op / +0.1% (worse)
Windows MSVC 386 ResetHeap1024/LLGo 124.200 ns/op +1.6 ns/op / +1.3% (worse)
Windows MSVC ARM64 AfterFuncZeroDelivery/Go 659.700 ns/op -0.7 ns/op / -0.1% (better)
Windows MSVC ARM64 AfterFuncZeroDelivery/LLGo 149848 ns/op +1470 ns/op / +1.0% (worse)
Windows MSVC ARM64 CreateStop/Go 201.300 ns/op +2.1 ns/op / +1.1% (worse)
Windows MSVC ARM64 CreateStop/LLGo 271.300 ns/op -21.3 ns/op / -7.3% (better)
Windows MSVC ARM64 RearmStopped/Go 70.590 ns/op +0.03 ns/op / +0.04252% (worse)
Windows MSVC ARM64 RearmStopped/LLGo 165.400 ns/op -8.8 ns/op / -5.1% (better)
Windows MSVC ARM64 ResetActive/Go 31.160 ns/op +0.04 ns/op / +0.1% (worse)
Windows MSVC ARM64 ResetActive/LLGo 95.320 ns/op +4.63 ns/op / +5.1% (worse)
Windows MSVC ARM64 ResetHeap1024/Go 31.180 ns/op +0.01 ns/op / +0.03208% (worse)
Windows MSVC ARM64 ResetHeap1024/LLGo 93.280 ns/op -0.67 ns/op / -0.7% (better)

Compared with 717fbe4429cb measured in the same runner job.

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查 652e6d4 并使用真实生成的 Wasm 在 Node/Chrome 中验证。异步等待、正常退出、argv[0] 和 CSP(await Go.ready)用例已通过,另有以下 3 个复现问题需要处理。相关 Go 单元测试通过。

Comment on lines +221 to +225
owner := goJSWasmMarker(existing)
if owner == goJSWasmModuleName(ctx, driverOutput) {
return shared, nil
}
return unique, nil

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 处理上一版无标记 glue 的原地重编路径

bad04663f 及更早版本生成的 wasm_exec_app.js 没有 // llgo-wasm: 标记,所以升级后在原目录重编同一个 app.wasm 时,这里会保留旧 shared 文件,把新 glue 写到 app.exec.js。但新版默认加载器仍请求 wasm_exec_app.js,构建成功后会把新 Wasm 和旧 glue 配对。已用上一版的真实产物复现,修改程序后用 652e6d458 重编,默认启动报 RuntimeError: function signature mismatch,手动加载新生成的 app.exec.js 后同一份 Wasm 能正常运行。请让该迁移路径使用正确的新 glue,或者在无法判断旧文件归属时给出明确诊断,避免一次正常的原地重编留下默认无法启动的产物。现有 legacy 单测只检查旧文件保留和新文件生成,没有验证默认加载入口。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。没有 // llgo-wasm: 标记的旧 wasm_exec_app.js 会按当前程序覆盖默认入口,不再把新 glue 写到默认加载器读不到的 app.exec.js。同名重编后 new Go() 使用新 glue。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 d20b56984。用上一版没有标记的真实 glue 作为旧产物原地重编,默认 wasm_exec_app.js 被更新,new Go() 能启动新 Wasm 并正常结束,此项已修复。

Comment thread targets/wasm_exec.js Outdated
Comment on lines 151 to 155
if (options && options.glue) {
const pending = loadSidecar(glue);
if (pending && typeof pending.then === "function") {
throw new Error("LLGo: preload " + glue + " before new Go({ glue })");
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 允许 glue 已预加载时成功构造 Go

传入 options.glue 后总会再次调用 loadSidecar(),而页面解析完成时它总是返回 Promise,因此这里必然抛出预加载错误,即使指定脚本已经成功加载。已在真实 Chrome 中依次执行 await Go.ready、通过 script.onload 等待 second.exec.js 加载完成、new Go({glue: "second.exec.js"}),仍得到 LLGo: preload second.exec.js before new Go({ glue })。同一页面将构造调用改成 new Go() 就能运行第二个程序。Node 中即使先将该 glue 注册为 globalThis.LLGoModule,带 options 的调用也会进入浏览器 URL 解析并报错。请记录预加载完成的 glue 或提供可等待的加载接口,让回复中新增的显式 glue 用法在预加载后能成功使用。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。会记录已加载的 glue,并检查页面上已有的 script 标签。预加载 second.exec.js 后 new Go({ glue: "second.exec.js" }) 不再抛错。另提供 Go.loadGlue(name)。Node 里若已有 LLGoModule 也不会再走浏览器 URL。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 d20b56984。真实 Chrome 中 await Go.loadGlue("second.exec.js") 后,new Go({glue: "second.exec.js"}) 能运行第二个程序,此项已修复。另补充了多程序切换与同一 glue 并发加载的独立问题。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f1fbbaaee 的 Go.loadGlue 预加载入口验证通过,但外部 script 预加载后显式 new Go({glue}) 的用例再次失败,已在最新构造器代码旁补充 inline。最新测试只覆盖 Go.loadGlue 入口,需要保留外部预加载路径的回归用例。

Comment on lines +207 to +210
if err := tmp.Close(); err != nil {
return err
}
return os.Rename(tmpName, dst)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 发布实现脚本前设置可部署的读取权限

新 helper 用 os.CreateTemp 创建的文件默认是 0600,这里直接 rename,缺少原 copyFileAtomic 中的 tmp.Chmod(0o644)。实际用 652e6d458 构建后,wasm_exec.js 为 0644,但 wasm_exec_app.js 和第二个程序的 second.exec.js 都是 0600。因此将构建目录直接交给以其他用户运行的 nginx/静态服务器,或者通过保留权限的发布工具部署时,必要的实现脚本无法被服务器读取。请在发布前设置与其他 JS 部署产物一致的权限,并在发布测试中检查文件模式。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。writeFileAtomic 在 rename 前 Chmod(0o644),发布测试会检查实现脚本权限。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 d20b56984。实际构建得到的 wasm_exec_app.js 和 second.exec.js 权限均为 0644,此项已修复。新增的权限测试存在 Windows 可移植性问题,已在对应测试行单独反馈。

@visualfc
visualfc force-pushed the feat/gojs-wasm-exec-loader branch from 652e6d4 to d20b569 Compare November 11, 2026 01:30

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查 d20b569。上一轮的无标记旧 glue 重编、已预加载的单次显式 glue 构造和 0644 文件权限均已验证修复。相关单元测试在本机通过,另补充以下问题。两个 glue 场景已在真实 Chrome 和本提交编译产物中复现,Windows 项依据 Go 标准库的平台实现审查。

Comment thread targets/wasm_exec.js Outdated
Comment on lines +124 to +127
for (let i = 0; i < scripts.length; i++) {
const src = scripts[i].src || "";
if (src === url || src.endsWith("/" + name)) {
return typeof global.LLGoModule === "function";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 为指定 glue 恢复对应的模块工厂

页面上存在某个 script 标签,只能说明该脚本曾经被加载。这里返回 true 后,构造器仍读取唯一的 globalThis.LLGoModule,它可能已被另一个程序覆盖。已用本提交真实生成的 first/second 两份 Wasm 在 Chrome 中复现,先等待默认 glue,再 await Go.loadGlue("second.exec.js"),随后 await Go.loadGlue("wasm_exec_app.js") 和 new Go({glue: "wasm_exec_app.js"}),全局工厂仍是 second 的工厂,实例化 first.wasm 报 LinkError: Import #24 "a" "y": function import requires a callable。请按 glue URL 保存和选择对应 factory,或重新执行所请求的脚本,使已经加载过多个程序后的显式选择也能匹配正确的 Wasm。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。按 glue URL 保存 LLGoModule 工厂。Go.loadGlue("second.exec.js") 后再 Go.loadGlue("wasm_exec_app.js") 会切回第一份工厂,new Go({ glue }) 使用对应模块。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 f1fbbaaee。真实 Chrome 用例中,加载 second 后再选择默认 glue,第一份工厂得到恢复,first.wasm 可正常运行,此项已修复。

Comment thread targets/wasm_exec.js Outdated
Comment on lines +134 to +137
function loadSidecar(name) {
if (glueAlreadyLoaded(name)) {
markGlueLoaded(name);
return;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 重复加载同一 glue 时等待正在进行的请求

第一次 Go.loadGlue(name) 会立即把 script 插入 DOM,第二次调用因此被 glueAlreadyLoaded() 判定为成功,并在 onload 之前返回。若默认程序的 LLGoModule 已存在,两个消费者同时请求第二份 glue 时,后一个消费者的 await 会提前完成并拿到旧工厂。已在真实 Chrome 中将 second.exec.js 的响应延迟 500ms,连续发起两个 Go.loadGlue("second.exec.js?slow=1"),等待第二次调用后第一请求仍未完成,LLGoModule 也仍是 first 的工厂。请缓存每个 URL 正在加载的 Promise,并让所有调用等待相同的成功或失败结果,只在实际执行成功后标记已加载。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。同一 glue URL 的 Go.loadGlue 共用一个 in-flight Promise,只在脚本 onload 成功后登记工厂。并发两次加载只会插入一个 script。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 f1fbbaaee。将同一 glue 响应延迟 500ms 并连续加载两次,第二次 await 会等到原请求完成,共用正确的工厂,此项已修复。

Comment thread internal/build/gojs_loader_test.go Outdated
Comment on lines +600 to +601
if perm := info.Mode().Perm(); perm != 0o644 {
t.Fatalf("mode = %o, want 644", perm)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 按平台限制 POSIX 权限断言

这个无条件的 Perm() == 0644 检查,以及 TestPublishGoJSLoaderFrom 中新增的相同检查,会导致 Windows 上的 internal/build 测试失败。Go 在 Windows 上只用 Chmod 的 0200 位控制只读属性,可写普通文件的 Stat().Mode().Perm() 返回 0666,因此即使实现正确执行 Chmod(0644),也无法满足此断言。后面的 Mkdir(0500) 不可写目录测试同样依赖 POSIX 权限,Windows 的 Mkdir 忽略该 mode,以 root 运行时也不能据此保证创建文件失败。请给这些断言加适用平台和权限条件,保留其他平台的文件内容/发布行为测试。本项已核对 Go 的 Windows 实现,当前未在 Windows 执行测试。Go Windows Mode 实现,Chmod 文档。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。Perm() == 0644 和不可写目录测试仅在非 Windows 上断言。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 f1fbbaaee,两处 0644 断言和不可写目录用例都已排除 Windows,Windows 平台断言问题已修复。本次仅作源码检查,本机相关测试通过,未在 Windows 实机运行。

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查 f1fbbaa。工厂切换与同 URL 并发加载的真实 Chrome 用例通过,Windows 权限断言也已按平台限制。相关 Go 单元测试通过,另在普通解析期 script 加载和外部 script 预加载路径发现以下两个回归,均已在 Chrome 复现。本次 JS 改动使用最新加载脚本与此前构建的真实 Wasm/glue 验证。

Comment thread targets/wasm_exec.js Outdated
Comment on lines +144 to +147
if (blocking) {
document.write(`<script src="${source}"></script>`);
if (!captureFactory(name)) {
throw new Error(`LLGo: ${name} did not register LLGoModule`);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 等待 document.write 插入的脚本执行后再捕获工厂

普通解析期 <script src="wasm_exec.js"></script> 会进入这个分支。document.write 只是把子 script 插入解析流,该脚本会在当前 wasm_exec.js 执行结束后才运行,因此紧接着的 captureFactory 还看不到 LLGoModule,并在 Go 类注册前抛错。已将本提交的加载脚本与真实 Wasm/glue 放入普通静态页面,在 Chrome 复现 LLGo: wasm_exec_app.js did not register LLGoModule,随后 typeof Go 为 undefined。相同产物改用 defer 加载并等待 Go.ready 后能启动。若已有另一个工厂,这里还可能把旧工厂登记到新 URL。请在子脚本实际执行完成后捕获工厂,并增加普通解析期 script 标签的浏览器用例,保留默认的 Go 兼容加载入口。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新合并实现 e30a1865a 已通过真实 Chrome 复核。普通解析期 script 标签加载后即可构造 new Go(),动态插入并等待 script.onload 后也能构造并运行,此前的 document.write 时序问题已解决。

Comment thread targets/wasm_exec.js Outdated
Comment on lines +207 to +211
const glue = requestedGlue(options);
const pending = loadSidecar(glue);
if (pending && typeof pending.then === "function") {
if (options && options.glue) {
throw new Error("LLGo: preload " + glue + " before new Go({ glue })");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 保留外部 script 预加载 glue 的构造路径

这次去掉页面 script 检查后,只有经过 Go.loadGlue 的模块会进入 factories 缓存。通过 <script src="second.exec.js"> 或自行插入 script 并等待 onload 预加载后,new Go({glue: "second.exec.js"}) 仍会重新注入脚本并抛出 preload 错误。已在 Chrome 中确认 second.exec.js 的外部 script 执行完成,等待 Go.ready 后显式构造仍报 LLGo: preload second.exec.js before new Go({ glue }),使用 Go.loadGlue 预加载的对应测试则通过。这使上一轮已经修复的外部预加载方式再次失效。请让外部预加载也能准确登记 URL 与工厂的对应关系,并分别覆盖 Go.loadGlue 和外部 script 两种入口。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新实现 e30a1865a 已改为每个程序的合并加载文件。真实 Chrome 中加载两份 host 后,new Go({wasm: "first.wasm"})、new Go({wasm: "second.wasm"}) 和 new Go() 均可运行,动态注入两份 host 也通过。此前 sidecar 预加载对应的代码路径已由新设计替代。

Publish a single wasm_exec.js for standalone GOOS=js GOARCH=wasm
builds by concatenating the Emscripten factory with the Go-compatible
host. new Go() works immediately after the script loads. Keep
wasm_exec.js for the first program, emit stem_wasm_exec.js when
another wasm already owns that file, and route print/printErr
through fs.writeSync.
@visualfc
visualfc force-pushed the feat/gojs-wasm-exec-loader branch from f1fbbaa to 7c7a46b Compare November 11, 2026 06:00
@visualfc visualfc changed the title feat: add GoJS wasm_exec loader feat: add GoJS wasm_exec.js host Nov 11, 2026
Register published hosts by wasm name. new Go() uses the last factory;
new Go({ wasm: "app.wasm" }) selects one, and a later host script
does not redefine Go. Trim redundant tests and update comments.

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

按新的合并实现及多 Wasm 要求复查 e30a186。真实 Chrome 中同目录不同名程序的 new Go() 默认选择、new Go({wasm}) 显式选择、后续脚本保持 Go 类身份、动态并发注入和 5 个实例并行运行均通过。参数、环境变量、退出回调和实例状态隔离也通过,CSP 下无需 eval。相关 Go 单元测试通过。以下补充 3 个实际复现问题。

Comment on lines +160 to +166
func goJSWasmModuleName(ctx *context, driverOutput string) string {
if ctx != nil && ctx.buildConf != nil {
if out := ctx.buildConf.OutFile; strings.HasSuffix(out, ".wasm") {
return filepath.Base(out)
}
}
return strings.TrimSuffix(filepath.Base(driverOutput), filepath.Ext(driverOutput)) + ".wasm"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 避免不同目录的同名 Wasm 覆盖注册项

程序身份被 filepath.Base 截成文件名,随后用同一个全局 __llgoFactories[name] 注册。一个项目若分别构建 a/app.wasm 和 b/app.wasm,再加载 a/wasm_exec.js 与 b/wasm_exec.js,第二份会静默覆盖第一份 app.wasm 的 factory。已用本提交的真实产物在 Chrome 复现,注册表只剩 app.wasm,new Go({wasm: "a/app.wasm"}) 和 b/app.wasm 都报 no factory registered,而用 app.wasm 选择后实例化 a/app.wasm 会报 WebAssembly.LinkError。这样两份产物单独可运行,放到同一项目后第一份就无法再选中。请以解析后的 Wasm URL 或另一种不会冲突的程序身份注册,并在无歧义时兼容裸文件名选择,增加不同目录同名文件的端到端用例。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。factory 同时按裸文件名和由 host 脚本解析出的 Wasm URL 注册。new Go({ wasm: "app.wasm" }) 在无歧义时仍可用;不同目录的同名文件用 URL 或相对路径(如 a/app.wasm)选择。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复核 9abd62446,a/app.wasm、b/app.wasm 和完整 URL 均能选择正确工厂,这部分已修复。但同名问题仍有裸路径分支未解决。真实 Chrome 中,在 /a/index.html 加载 a、b 两份 host 后,new Go({wasm: "app.wasm"}) 直接取被 b 覆盖的裸名注册项,而 fetch("app.wasm") 明确请求 /a/app.wasm,最终仍报 WebAssembly.LinkError。原因是 targets/wasm_exec.js:105-106 在 URL 解析之前就返回 factories[name]。请优先按调用上下文解析 URL,再在唯一时使用裸名别名,避免同名加载顺序改变显式选择的结果。当前单测反而断言裸名在冲突后返回 b,需要补充页面位于 a/ 的实际入口用例。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。先按页面 URL 解析 wasm 名,再在唯一时使用裸名。/a/index.html 上 new Go({ wasm: "app.wasm" }) 会选中 /a/app.wasm,不再被后加载的同名 factory 覆盖。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 17b1ae2 验证本条及后续页面 URL 优先级问题已修复:页面位于 a/ 时,new Go({wasm:"app.wasm"}) 能选中 a/app.wasm,不会被后加载的 b/app.wasm 覆盖;从上级页面传入 a/app.wasm、b/app.wasm 或完整 URL 也均可正确运行。页面目录没有对应目标而裸文件名存在歧义时,会明确报错。浏览器多实例并行及动态脚本加载回归通过。

Comment thread internal/build/gojs_loader.go Outdated
Comment on lines +186 to +188
func goJSRegisterFactory(wasmName string) []byte {
name, _ := json.Marshal(wasmName)
return []byte("globalThis.__llgoFactories = globalThis.__llgoFactories || {};\nif (typeof globalThis.LLGoModule === \"function\") globalThis.__llgoFactories[" + string(name) + "] = globalThis.LLGoModule;\n")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 从合并文件的实际作用域注册 factory,支持 CommonJS 加载

真实 emcc 输出使用 var LLGoModule = ...。通过 Node 的 require 加载合并脚本时,该变量属于 CommonJS 模块作用域,globalThis.LLGoModule 并不存在,所以这里不会注册任何 factory,默认构造也找不到它。已直接执行 require("./wasm_exec.js"); new Go(),得到 missing the bundled LLGoModule factory,new Go({wasm: "first.wasm"}) 则报 no factory registered。require 的返回值实际是 factory,说明合并文件中已有正确工厂,只是注册时读错作用域。浏览器经典 script 与 vm.runInThisContext 用例可以通过,因此现有 VM/mock 测试未覆盖该问题。请显式注册词法作用域中的 factory,并同步维护 new Go() 所用的默认工厂引用,补一个真实合并产物通过 require 加载的 Node 用例。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。注册改为读取词法作用域中的 LLGoModule,并写回 globalThis.LLGoModule 作为 new Go() 的默认 factory。Node 的 require("./wasm_exec.js") 后可以直接 new Go()。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 9abd62446,直接 require 两份真实合并脚本后,new Go() 和按完整文件 URL 选择的实例均可启动并正常结束,CommonJS 工厂注册问题已修复。另发现带 ./ 的 Node 相对路径选择问题,已在最新选择器代码旁补充 inline。

Comment thread internal/build/artifact_report.go Outdated
Comment on lines +135 to +142
if driverOut := emscriptenDriverOutput(conf, out.Out); needsGoJSLoader(conf, nil, driverOut) {
if err := add(ArtifactRoleDeployment, "javascript", goJSLoaderSidecar(driverOut)); err != nil {
return nil, err
}
unique := goJSUniqueLoaderSidecar(driverOut)
if _, err := os.Stat(unique); err == nil {
if err := add(ArtifactRoleDeployment, "javascript", unique); err != nil {
return nil, err

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 按当前 Wasm 的归属报告合并加载器

第二个程序已经有独立的 second_wasm_exec.js,仍无条件把 wasm_exec.js 作为必需产物加入,但后者属于第一个程序。实际依次构建 first.wasm、second.wasm 后,CollectArtifacts(second) 同时报告 first 的 wasm_exec.js(98223 字节)和 second_wasm_exec.js(91700 字节),会把另一个程序的完整 factory 算入 second 的部署体积。进一步仅复制 second.wasm 与 second_wasm_exec.js 到独立目录,浏览器可正常启动,CollectArtifacts 却因缺少该目录下的 wasm_exec.js 报错。请与 chooseGoJSLoaderDest 使用一致的 ownership 判定,只报告并验证当前程序实际拥有的加载器,并覆盖第二个程序独立部署的产物清单用例。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。CollectArtifacts 与 chooseGoJSLoaderDest 使用同一套 ownership:只报告当前程序实际拥有的 host。第二个程序只列出 second_wasm_exec.js;单独部署缺少 wasm_exec.js 时不再报错。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核 9abd62446。CollectArtifacts(second) 只报告 second.wasm 与 second_wasm_exec.js。将这两个文件复制到独立目录、没有 wasm_exec.js 时,浏览器运行和 CollectArtifacts 均成功,此项已修复。

Register factories from the lexical LLGoModule so Node require works,
and also key them by resolved wasm URL so same-named files in different
directories stay distinct. CollectArtifacts reports only the host this
program owns.

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复核 9abd624。真实产物的 Node require 注册、浏览器通过路径/完整 URL 选择不同目录同名程序、第二个程序独立部署及产物报告均通过,5 实例并行和 CSP 用例仍通过。同名裸路径优先级尚有剩余问题,已在原线程回复,另在下面补充 Node 相对路径解析问题。相关 Go 单元测试通过。

Comment thread targets/wasm_exec.js Outdated
Comment on lines +109 to +113
const base = (typeof location !== "undefined" && location.href) ||
(typeof document !== "undefined" && document.currentScript && document.currentScript.src) ||
(typeof __filename === "string" ? "file://" + String(__filename).replace(/\\/g, "/") : "") || "";
if (base) {
const url = new URL(name, base).href;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 统一 Node 相对 Wasm 路径的解析基准和规范化

Go 类只在第一份 host 中定义,因此此处的 __filename 永远属于第一份加载器。Node 中 require(project/a/wasm_exec.js) 和 require(project/b/wasm_exec.js) 后,相对路径会以 project/a/ 为基准解析,字符串 suffix 回退又没有规范化 ./,导致等价路径表现不同。已用本提交真实产物复现,在 project 目录运行时,new Go({wasm: "a/app.wasm"}) 与 b/app.wasm 都成功,但 ./a/app.wasm、./b/app.wasm 都报 no factory registered。a/app.wasm 能成功仅因为后面的 suffix 回退碰巧命中注册 URL。请明确并统一 Node 相对路径的基准,例如与 fs.readFileSync 读取 Wasm 一致的 process.cwd(),规范化后按 URL 查找,并覆盖带 ./、../ 的选择用例。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。Node 相对路径相对 process.cwd() 解析,不再使用第一份 host 闭包里的 __filename。./a/app.wasm 与 a/app.wasm 会规范成同一 URL。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 17b1ae2 用真实 Wasm 产物验证修复:以项目根目录为 cwd 时,a/app.wasm、./a/app.wasm、b/app.wasm、./b/app.wasm 均能选中对应工厂;切换 cwd 到 b/ 后,../a/app.wasm 和 ./app.wasm 也均成功。另发的含 # 目录路径编码问题在 9abd624 已存在,与本条普通相对路径用例的修复分开记录。

Look up factories against location.href or process.cwd before any
bare-name alias, and normalize ./ relative paths. Conflicting app.wasm
entries no longer follow load order when the page path selects one.

@cpunion cpunion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查 17b1ae2:上轮浏览器裸文件名优先级、Node ./ 和 ../ 路径选择均已实测修复。浏览器普通/动态脚本、严格 CSP、多 Wasm 并行实例及 Node 正常路径通过;相关 internal/build 测试通过。另确认一项 Node 原生路径转 file URL 的编码问题,见 inline。对照 9abd624 的真实产物,该问题已存在于上一版,并非本轮新引入。

Comment thread targets/wasm_exec.js
Comment on lines +99 to +102
let dir = String(process.cwd()).replace(/\\/g, "/");
if (!dir.startsWith("/")) dir = "/" + dir;
if (!dir.endsWith("/")) dir += "/";
return "file://" + dir;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 使用正确的原生路径到 file URL 转换

目录名含合法字符 # 时,直接拼接 file:// 会把后面的路径解释为 URL fragment。实际复现:在 project#tag 下加载 a/wasm_exec.js、b/wasm_exec.js(各有自己的 app.wasm),两个工厂的 URL 注册键都变成父目录的同一个 .../app.wasm;new Go({wasm:"./a/app.wasm"})、./b/app.wasm 均报 no factory registered,传入正确编码的绝对 file:///.../project%23tag/a/app.wasm 也无法选中。

这里的 cwd 转换和 internal/build/gojs_loader.go:222 的 __filename 注册都需要正确转换并编码文件路径(Node 可使用 node:url.pathToFileURL(),cwd 保留目录末尾分隔符),只修这里仍会留下损坏的注册键。建议增加含 # 目录下两个同名 Wasm 的回归用例。Node 官方文档也给出了这个字符的转换示例:https://nodejs.org/api/url.html#urlpathtofileurlpath-options

来源说明:已用上一版 9abd624 产物复现;注册端的问题在上一版已有,本提交新增的 cwd 转换沿用了同一拼接方式。这是本轮新发现的原有问题。

@cpunion
cpunion merged commit b9cfc32 into xgo-dev:main Nov 11, 2026
114 of 115 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants