Skip to content

perf: fix BenchmarkParseWorkflow regression — ~31% faster, ~40% fewer allocations#28407

Merged
pelikhan merged 4 commits intomainfrom
copilot/fix-performance-regression-parseworkflow
Apr 25, 2026
Merged

perf: fix BenchmarkParseWorkflow regression — ~31% faster, ~40% fewer allocations#28407
pelikhan merged 4 commits intomainfrom
copilot/fix-performance-regression-parseworkflow

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 25, 2026

BenchmarkParseWorkflow regressed +191.6% (361µs → 1053µs on CI). CPU profiling identified three redundant operations in the hot path, all paid on every ParseWorkflowFile call.

Root causes

  • Double YAML parse for imported filesprocessIncludedFileWithVisited already held a parsed *FrontmatterResult, but called extractToolsFromContent(string(content)) which re-parsed the raw bytes again to extract tools/mcp-servers. Accounted for ~2.1s of ~13.7s total profile time.
  • Schema validation on immutable builtins — Builtin virtual files (@builtin:engines/claude.md, etc.) are embedded binary assets that never change at runtime, yet ValidateIncludedFileFrontmatterWithSchemaAndLocation ran full JSON-schema validation on every import.
  • Unconditional extractPermissions callsetupEngineAndImports marshaled the permissions YAML section on every call to validate against merged import permissions, even when importsResult.MergedPermissions == "" (the common case).

Changes

  • pkg/parser/content_extractor.go — New extractToolsFromFrontmatter(frontmatter map[string]any) that extracts tools/mcp-servers from an already-parsed map, replacing the re-parse path.
  • pkg/parser/include_processor.go — Use extractToolsFromFrontmatter instead of extractToolsFromContent; skip schema validation entirely for paths with BuiltinPathPrefix.
  • pkg/workflow/compiler_orchestrator_engine.go — Move extractPermissions inside the importsResult.MergedPermissions != "" guard so YAML marshaling is only done when actually needed.

Results

Metric Before After Δ
ns/op 270,118 185,052 −31.5%
B/op 145,257 103,542 −28.7%
allocs/op 2,077 1,252 −39.7%

CI runners (~4× slower than local): ~1053µs → ~740µs.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw Initial /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw git 1/x64/bin/node git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git 1/x64/bin/node git (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name prettier --check 64/bin/go --ignore-path .prettierignore 64/bin/go go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name --show-toplevel git (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv -unreachable=false /tmp/go-build3270466242/b268/vet.cfg /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv --noprofile git /usr/bin/git --show-toplevel ache/go/1.25.8/xrev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel /opt/hostedtoolc/opt/hostedtoolcache/node/24.14.1/x64/bin/npm /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv --noprofile git /usr/bin/git --show-toplevel node /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel bash /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv --local committer.email ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git _lab�� --show-toplevel git sh tags/v4 64/pkg/tool/linurev-parse sv git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv 043934/b239/_pkg_.a git sh --show-toplevel b.com/google/pprrev-parse /usr/bin/git node js/f�� 1/x64/bin/bash H_mD/eA-LzYtNLRR_DnVdH_mD rgo/bin/bash --show-toplevel git /usr/bin/git node (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/infocmp get .cfg 64/pkg/tool/linu--show-toplevel infocmp -1 xterm-color 64/pkg/tool/linux_amd64/vet /usr/bin/git get .cfg 64/pkg/tool/linu--show-toplevel git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv get .cfg 64/pkg/tool/linux_amd64/vet commit.gpgsign (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git _har�� --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv --show-toplevel git 64/pkg/tool/linux_amd64/cgo --show-toplevel git 1/x64/bin/node 64/pkg/tool/linux_amd64/cgo rev-�� --show-toplevel | tr '\n' ':')$PATH"; [ -n "$GOROOT" ] && expo rgo/bin/bash --show-toplevel git /usr/bin/git node (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --show-toplevel (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --show-toplevel git /usr/bin/git --show-toplevel /opt/hostedtoolc/tmp/gh-aw-test-runs/20260425-061636-18749/test-patch-priority-27900�� (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git 1/x64/bin/node git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -unreachable=false /tmp/go-build3270466242/b213/vet.cfg 0466242/b324/vet.cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -unreachable=false /tmp/go-build3270466242/b051/vet.cfg 0466242/b354/vet.cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -unreachable=false /tmp/go-build3270466242/b059/vet.cfg 0466242/b347/vet.cfg (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv -unreachable=false /tmp/go-build3270466242/b037/vet.cfg 0466242/b349/vet.cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv -m owner /opt/hostedtoolcache/node/24.14.1/x64/bin/bash 0 -j ACCEPT bash --no�� --noprofile git /opt/pipx_bin/bash --show-toplevel ache/go/1.25.8/xrev-parse /usr/bin/git bash (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --noprofile -nVU91HTCb6SIGDb2QZT/-nVU91HTCb6SIGDb2QZT /snap/bin/bash go1.25.8 -c=4 -nolocalimports bash --no�� --noprofile /opt/hostedtoolcache/go/1.25.8/x64/src/cmd/internal/disasm/disasm.go /usr/local/bin/bash --show-toplevel node /usr/bin/runc bash (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv get --local 64/pkg/tool/linux_amd64/vet pull.rebase (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv -unreachable=false /tmp/go-build3270466242/b050/vet.cfg 0466242/b346/vet.cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ache/node/24.14.1/x64/bin/node heckout/git/ref/git x_amd64/vet bject.type] | @t--show-toplevel git _har�� --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv get --local 64/pkg/tool/linux_amd64/vet committer.name (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --show-toplevel git /usr/bin/git --show-toplevel x_amd64/vet /usr/bin/git git rev-�� --show-toplevel git 64/pkg/tool/linux_amd64/link --show-toplevel x_amd64/vet /usr/bin/git 64/pkg/tool/linux_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/cgo /usr/bin/git git _out�� --show-toplevel git 64/pkg/tool/linux_amd64/link --show-toplevel git /usr/bin/git 64/pkg/tool/linux_amd64/link (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv -bool -buildtags 0466242/b319/vet.cfg -errorsas -ifaceassert -nilfunc /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -uns�� heckout/git/ref/tags/v5 /tmp/go-build3270466242/b194/vet.cfg bject.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv ache/go/1.25.8/x--show-toplevel git /usr/local/.ghcup/bin/bash --show-toplevel ache/go/1.25.8/xrev-parse /usr/bin/git bash --no�� heckout/git/ref/tags/v5 git bject.type] | @tsv --show-toplevel ache/go/1.25.8/xrev-parse /usr/bin/git bash (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv --noprofile FZgL9No0HDgETfcvORai/FZgL9No0HDgETfcvORai /usr/sbin/bash go1.25.8 -c=4 -nolocalimports bash --no�� heckout/git/ref/tags/v5 /opt/hostedtoolcache/go/1.25.8/x64/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap.go bject.type] | @tsv --show-toplevel (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv _7oUKl6Du .cfg 64/pkg/tool/linux_amd64/vet committer.email (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git _cod�� --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv --show-toplevel git 1/x64/bin/bash --show-toplevel git /usr/bin/git git _out�� --show-toplevel git /opt/hostedtoolcache/node/24.14.1/x64/bin/node --show-toplevel git /usr/bin/git node (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv eFSy5PFyu .cfg 64/pkg/tool/linux_amd64/vet committer.email (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ndor/bin/bash --show-toplevel x_amd64/vet /usr/bin/git git _cod�� --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel x_amd64/vet /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv --show-toplevel git ache/node/24.14.1/x64/bin/node --show-toplevel git /usr/bin/git git _out�� --show-toplevel git bash --show-toplevel git /usr/bin/git node (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 1/test1.md GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env rity1186368335/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE tants GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name tr de_modules/.bin/sh [:upper:] infocmp /usr/bin/git git rev-�� y_with_repos_array_c2046982231/001 git cal/bin/bash --show-toplevel git x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env ithout_min-integrity1410491249/001 cfg ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuremote.origin.url env mpiledOutput2975799178/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name LsRemoteWithRealGitmaster_branch3588955154/001' 64/bin/node --show-toplevel infocmp /usr/bin/git git 1/x6�� --show-toplevel git /usr/bin/git son gh x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linumyorg env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 01/main.md GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name git 1/x64/bin/node --show-toplevel /usr/bin/git /usr/bin/git git 1/x6�� y_only_defaults_repo2071220672/001 git /usr/bin/git son infocmp x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name cut ules/.bin/sh 64/bin/go infocmp /usr/bin/git git rev-�� *.json' '!../../../pkg/workflow/js/**/*.json' ---errorsas git bin/bash --show-toplevel git x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env mpiledOutput2496426743/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/link env tants.test GO111MODULE rtcfg.link GOINSECURE GOMOD GOMODCACHE dpih3V3vyX3Ujpn0_x/hwAYtf38lH4Qlremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name LsRemoteWithRealGitcustom_branch2450045832/001' /usr/bin/git --show-toplevel /usr/bin/git /usr/bin/git git rev-�� ithout_min-integrity4194107661/001 git /usr/bin/git --show-toplevel git x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE N_/MhA652aEkSuR8NKQxPfr/feDwSjXStImIOC-NY5wN env mpiledOutput2496426743/001 GO111MODULE rtcfg.link GOINSECURE GOMOD GOMODCACHE b4L7Ikj7IChhS-MVTest User (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name git bin/sh --show-toplevel /usr/bin/git /usr/bin/git git rev-�� 3524/001/stability-test.md git ache/go/1.25.8/x64/bin/bash --show-toplevel git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env mpiledOutput2496426743/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env /workflows GO111MODULE ck GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name git h --show-toplevel /usr/bin/git /usr/bin/git git rev-�� ithout_min-integrity4194107661/001 git ache/node/24.14.1/x64/bin/bash --show-toplevel git x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path "prettier" --cheGOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE 46MaExS/rs4ruDNp-importcfg env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 GOMOD GOMODCACHE 64/pkg/tool/linuorigin env y_with_explicit_repo4085237064/0-p GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/contents/.github/workflows/shared/reporting.md
    • Triggering command: /tmp/go-build304226748/b404/cli.test /tmp/go-build304226748/b404/cli.test -test.testlogfile=/tmp/go-build304226748/b404/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE node /opt�� prettier --check 64/bin/go **/*.ts **/*.json --ignore-path go (http block)
    • Triggering command: /tmp/go-build1418849273/b404/cli.test /tmp/go-build1418849273/b404/cli.test -test.testlogfile=/tmp/go-build1418849273/b404/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true --show-toplevel ache/go/1.25.8/x-c /usr/bin/git git rev-�� --show-toplevel git ache/uv/0.11.7/x86_64/bash --show-toplevel /usr/bin/git /usr/bin/git git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv ref/tags/v1.0.0 (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv ref/tags/v1.0.0 git sv --show-toplevel /opt/hostedtoolcrev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel /opt/hostedtoolc-lh /usr/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv ref/tags/v1.0.0 /bin/sh sv git-upload-pack git git-upload-pack rev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git 1/x64/bin/node git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /home/REDACTED/.local/bin/node -unreachable=falnode /tmp/go-build327js/fuzz_sanitize_output_harness.cjs 0466242/b269/vet.cfg node /opt�� install --package-lock-only /usr/bin/git -unreachable=falbash /tmp/go-build327--norc /opt/hostedtoolc--noprofile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv /repos/actions/ai-inference/git/ref/tags/v1 --jq /usr/bin/git --noprofile git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv /tmp/go-build2485533865/b001/workflow.test -importcfg /opt/hostedtoolcache/node/24.14.1/x64/bin/bash -s -w -buildmode=exe bash --no�� on' --ignore-path ../../../.prettierignore -extld=gcc /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE LLUYjQ6/dBPQQZ1zrev-parse env le-frontmatter.md GO111MODULE 257c023254b8cf86bf0508e04fc48903-d GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv iant-645555296/.--detach GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/cgo GOINSECURE GOMOD GOMODCACHE x_amd64/cgo (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv --format=%T /sys/fs/cgroup /usr/local/.ghcup/bin/bash --show-toplevel git /usr/bin/git bash --no�� on' --ignore-path ../../../.pret.prettierignore git /opt/hostedtoolcache/uv/0.11.7/x86_64/bash --show-toplevel /opt/hostedtoolc/tmp/js-hash-test-50132848/test-hash.js /usr/bin/git bash (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /opt/hostedtoolcache/go/1.25.8/x64/bin/node -unreachable=falnode /tmp/go-build327js/fuzz_sanitize_output_harness.cjs 0466242/b272/vet.cfg node /opt�� install --package-lock-only /usr/bin/git -unreachable=falbash /tmp/go-build327--norc /opt/hostedtoolc--noprofile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv --show-toplevel bash /usr/bin/git --noprofile git /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git /usr/bin/git git (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env eutil.go eutil_test.go ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion --show-toplevel git x_amd64/vet git rev-�� 8/001/inlined-a.md x_amd64/vet nfig/composer/vendor/bin/sh ignore infocmp /usr/bin/git git (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go "prettier" --wri/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet ache/go/1.25.8/x-atomic 64/bin/go go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go tierignore ache/go/1.25.8/x-o 64/bin/go go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh workflow list --repo owner/repo --json name,path,state ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env 3625148439 GO111MODULE cfg GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name --check (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name --show-toplevel git ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile --show-toplevel git ystemd-run ache/go/1.25.8/x../../../**/*.json --no�� 7349079/b001/_pk--ignore-path git 7349079/b001=> linuxagent-logcogit /opt/hostedtoolc-C counting=yes bash (http block)
  • https://api.github.com/repos/test/repo
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 1/x64/bin/node GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch mpiledOutput644898503/001 ation_test.go /usr/bin/git --show-toplevel iptables /usr/bin/grep git rev-�� 5106-80293/test-source-field-variant-3604955824/.github/workflows grep k/node_modules/.bin/sh ^From [0-9a-f]\{gh /tmp/gh-aw/aw-ferun /usr/bin/git git (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI and others added 2 commits April 25, 2026 06:51
… allocations

Three targeted optimizations to eliminate redundant work in the hot path:

1. Add `extractToolsFromFrontmatter` (content_extractor.go) to extract tools
   from an already-parsed frontmatter map, avoiding a full YAML re-parse.

2. Use `extractToolsFromFrontmatter` in `processIncludedFileWithVisited`
   (include_processor.go) instead of `extractToolsFromContent` which was
   re-parsing the file's YAML even though the frontmatter was already parsed.
   Also skip JSON-schema validation for builtin virtual files — they are
   immutable trusted assets that can never be invalid at runtime.

3. Defer `extractPermissions` in `setupEngineAndImports`
   (compiler_orchestrator_engine.go) to only execute when
   `importsResult.MergedPermissions != ""`. Previously the YAML-marshal cost
   was paid on every call, even for workflows with no imports.

Benchmark results (AMD EPYC 7763, 10s runs):
  Before: 270,118 ns/op  145,257 B/op  2,077 allocs/op
  After:  187,313 ns/op  103,572 B/op  1,252 allocs/op
  Change:   -30.7%         -28.7%        -39.7%

On CI runners (approx. 4x slower): ~750µs vs ~1,053µs reported in the issue.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/75c52736-3bb5-43bd-bc6e-f6ac93ee9ed1

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…e review)

Replace the silent `return "{}", nil` on json.Marshal error with a proper
`fmt.Errorf(...)` so callers can see marshaling failures rather than silently
receiving an empty tools object.  Also added a comment explaining why non-map
field values are intentionally skipped (consistent with extractToolsFromContent).

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/75c52736-3bb5-43bd-bc6e-f6ac93ee9ed1

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix performance regression in ParseWorkflow perf: fix BenchmarkParseWorkflow regression — ~31% faster, ~40% fewer allocations Apr 25, 2026
Copilot AI requested a review from gh-aw-bot April 25, 2026 06:57
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for the performance work! The three optimizations (avoiding double YAML parse, skipping schema validation on immutable builtins, and gating extractPermissions behind a nil-check) are well-reasoned. A few things to address before merging:

  1. No tests or benchmarks added — the PR claims ~31% speedup and ~40% fewer allocations but includes no benchmark or unit test to lock in those gains or verify correctness of extractToolsFromFrontmatter.
  2. Silent skip of non-map tools/mcp-servers valuesmergeField silently ignores array-typed values. A comment explaining why arrays are intentionally skipped (rather than erroring) would clarify intent.
  3. Contribution process — per CONTRIBUTING.md, non-core members contribute by filing a detailed agentic plan as an issue; a core team member then creates the PR using a coding agent. Please open an issue with your plan so it can be picked up properly.

If you'd like a hand, you can assign this prompt to your coding agent:

For PR github/gh-aw#28407 (perf: fix BenchmarkParseWorkflow regression):
1. Add a benchmark test (e.g. BenchmarkParseWorkflow) that measures the before/after performance of the parsing path.
2. Add a unit test for `extractToolsFromFrontmatter` covering: valid map input, array input (verify it is skipped gracefully), and nil input.
3. Add an inline comment in `mergeField` explaining why array-typed values are intentionally skipped rather than returning an error.

Generated by Contribution Check · ● 1.4M ·

@pelikhan pelikhan marked this pull request as ready for review April 25, 2026 10:18
Copilot AI review requested due to automatic review settings April 25, 2026 10:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves ParseWorkflowFile performance by removing redundant YAML parsing/validation work from the import/include hot path.

Changes:

  • Extract tools/mcp-servers directly from already-parsed frontmatter instead of re-parsing YAML from raw content.
  • Skip schema validation for builtin virtual files (@builtin:) during include processing.
  • Avoid extractPermissions YAML marshaling unless imports actually contributed merged permissions.
Show a summary per file
File Description
pkg/parser/content_extractor.go Adds extractToolsFromFrontmatter to avoid redundant YAML re-parse when extracting tools/mcp-servers.
pkg/parser/include_processor.go Uses extractToolsFromFrontmatter and skips schema validation for builtin virtual files.
pkg/workflow/compiler_orchestrator_engine.go Moves permissions extraction under the merged-permissions guard to avoid unnecessary marshaling.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment on lines +88 to +91
extractedJSON, err := json.Marshal(extracted)
if err != nil {
return "", fmt.Errorf("failed to marshal tools to JSON: %w", err)
}
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

extractToolsFromFrontmatter changes the error-handling contract vs extractToolsFromContent: on json.Marshal failure it now returns a non-nil error, which will bubble up via processIncludedFileWithVisited(..., extractTools=true) and can fail compilation where the previous path returned "{}" and nil error (matching the comment in extractToolsFromContent). Consider returning "{}" (and nil error) on marshal failure for behavioral consistency, or ensure callers deliberately handle this new error path. Also, the error text mentions only "tools" even though the output includes both tools and mcp-servers.

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot review all comments

… object

Restore `"{}", nil` on json.Marshal failure, matching the original
`extractToolsFromContent` behavior. Propagating the error would change the
contract and could fail compilation where the previous code silently returned
an empty tools object (matching bash behavior).  The `fmt` import added in
the prior commit is also removed as it is no longer needed.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0c09d31b-441f-4b04-971a-6201eb0391af

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 25, 2026

@copilot review all comments

Addressed in 5f94abe — reverted the json.Marshal error path in extractToolsFromFrontmatter back to return "{}", nil to match extractToolsFromContent's behavior (and the "match bash behavior" convention). The stray fmt import added by the prior commit has also been removed.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv ^{commit} (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv ^{commit} (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv ^{commit} (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from pelikhan April 25, 2026 10:50
@pelikhan pelikhan merged commit e14d308 into main Apr 25, 2026
25 checks passed
@pelikhan pelikhan deleted the copilot/fix-performance-regression-parseworkflow branch April 25, 2026 11:02
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.

[performance] Regression in ParseWorkflow: +191.6% slower

4 participants