Skip to content

HF-150: advisory instruction-count workflow (prototype) - #1814

Open
marcin-kordas-hoc wants to merge 11 commits into
feat/hf-150-perf-gatefrom
feat/hf-150-instruction-count
Open

marcin-kordas-hoc wants to merge 11 commits into
feat/hf-150-perf-gatefrom
feat/hf-150-instruction-count

Conversation

@marcin-kordas-hoc

@marcin-kordas-hoc marcin-kordas-hoc commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Context

The PR adds an advisory workflow that compares base and head by the CPU instructions each performance scenario executes, instead of by time.

  • Why: on shared runners, wall-clock noise lets the timing comparison (HF-150: alternate base and head runs in the performance workflow #1805) show only regressions of about 5% or more per scenario, and it still reports false regressions. Instruction counts do not depend on the load of the runner.
  • What changed:
    • .github/workflows/performance-instructions.yml: installs valgrind, counts the instructions of every scenario for base and head (one after the other, from the same build directory), writes the comparison to the job summary and prints the raw counts into the log. Paths follow the monorepo layout.
    • The job never fails the pull request (continue-on-error) and posts no comment. performance.yml is unchanged.
    • When the paired tests branch has no performance/run-instructions.ts, the job skips the counts and the comparison with a notice instead of failing with module-not-found.
    • hyperformula/dev-docs/PERFORMANCE.md: one sentence about this workflow.
  • Result: every PR gets a per-scenario instruction-count comparison that can see changes well under 1%.
  • Role: the intended direction for the performance check, done in-house with valgrind on standard runners and without a vendor service. The wall-clock comparison stays as a temporary advisory layer, because instruction counts do not see GC pauses, memory or cache effects.

How did you test your changes?

  • Paired tests branch: feat/hf-150-instruction-count in hyperformula-tests.
  • This PR changes no engine code, so every scenario should come out at about 0%. CI runs:
Run Largest change over 13 scenarios Job time
before the monorepo merge 0.0075% 7m39s
after the monorepo merge (63b4b92) 0.00022% 10m37s
with the runner check and the scenario table (7ded1cc, tests dae23a2) 0.0056% 11m58s
  • A throwaway control PR that added a fixed loop to setCellContents moved every scenario that calls it by +0.06% to +3.97%, and every other scenario by at most 0.013%.
  • Locally, in the monorepo layout: one scenario counted end to end under valgrind.
  • The runner check, run as a script against three tests refs: develop and feat/hf-150-perf-gate (no runner) print the notice and set no output, so the three guarded steps skip; feat/hf-150-instruction-count sets present=true.

Compatibility with Excel and Google Sheets

Not applicable.

Public API changes

None.

Out of scope and follow-ups

Types of changes

  • Breaking change (existing functionality no longer works as before) – agreed with the maintainers
  • New feature or improvement (a non-breaking change that adds functionality)
  • Bug fix (a non-breaking change that fixes an issue)
  • Additional language file, or a change to an existing language file (translations)
  • Change to the documentation

CI tooling only, plus one sentence in dev-docs/.

Related issues

  1. HF-150 (internal task)

Checklist

🤖 Generated with Claude Code


Note

Low Risk
CI and dev-docs only; no engine or API changes, and the job cannot fail the pull request.

Overview
Adds a prototype GitHub Actions workflow Performance (instruction count) that runs on pull requests alongside the existing wall-clock performance job.

The new job checks out base and head, syncs the shared hyperformula-tests suite to both trees, and uses valgrind/callgrind to count CPU instructions for each performance scenario on each revision (sequentially, on the same Node 22 build). It writes a base-vs-head comparison to the job summary and logs raw JSON counts. The job is advisory only: continue-on-error: true, no PR comment, and no change to performance.yml.

If the paired tests branch lacks performance/run-instructions.ts, guarded steps are skipped with a notice instead of failing.

hyperformula/dev-docs/PERFORMANCE.md gains one sentence documenting this workflow and its prototype status.

Reviewed by Cursor Bugbot for commit 2f13c8b. Bugbot is set up for automated code reviews on this repo. Configure here.

marcin-kordas-hoc and others added 3 commits October 13, 2026 07:04
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… script

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
hyperformula-docs d0ac897 Commit Preview URL

Branch Preview URL
Nov 04 2026, 10:44 AM

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Performance comparison of head (d0ac897) vs base (b3f2f68) with the tests at 6d7003d

Scenario base median (ms) head median (ms) change threshold noise (CV base/head) verdict
Sheet A 449.1 445.1 -0.88% ±5.0% † 2.3% / 2.1% ok
Sheet B 197.4 194.8 -1.30% ±7.4% † 3.5% / 4.4% ok
Sheet T 156.6 159.3 +1.68% ±8.0% † 3.6% / 4.9% ok
Column ranges 451.0 447.6 -0.76% ±5.3% † 1.3% / 1.3% ok
Sorted lookup 11316.4 11437.4 +1.07% ±50.0% ‡ 1.3% / 1.5% ok
Sheet A: change value, add/remove row/column 132.0 172.9 +30.96% ±30.3% 22.6% / 38.0% inconclusive
Sheet B: change value, add/remove row/column 166.4 176.2 +5.90% ±13.3% † 7.4% / 5.7% ok
Column ranges - add column 147.3 148.1 +0.55% ±6.4% † 4.5% / 3.1% ok
Column ranges - without batch 389.4 404.5 +3.88% ±6.3% † 5.0% / 1.2% ok
Column ranges - batch 120.4 121.4 +0.81% ±5.1% † 3.7% / 3.5% ok
Recalculation fan-out - one edit, 10k dependents 42.7 45.8 +7.25% ±6.4% † 7.1% / 3.5% regression
Recalculation fan-out - 5 edits without batch 125.9 130.1 +3.32% ±9.0% † 5.5% / 3.6% ok
Recalculation fan-out - 5 edits in batch 43.9 45.8 +4.37% ±6.8% † 4.1% / 2.9% ok

Threshold of an unmarked scenario = max(5%, 3 x the standard error of the difference of the two medians). † = the band of changes observed on identical code in earlier runs, instead of that rule. ‡ = a fixed threshold for a scenario that guards against a change of complexity class. This check is advisory: it reports regressions but does not fail the build.

  • Scenario 'Sheet A: change value, add/remove row/column': the merged rounds of one side differ by more than 20%, so it is not judged (a slow phase of the runner, not the code, is the likely cause).

Comment on lines +72 to +79
# The runner comes with the shared tests and is started through the generic tsnode script of the engine's
# package.json, which every revision has. Each run compiles the engine of its own tree into the same build directory and measures it
# there, so the two runs must stay sequential: the count depends on the paths a process sees.
- name: (base) Count instructions
run: cd base && npm run tsnode --workspace=hyperformula test/hyperformula-tests/performance/run-instructions.ts "$GITHUB_WORKSPACE/base-instructions.json"

- name: (head) Count instructions
run: cd head && npm run tsnode --workspace=hyperformula test/hyperformula-tests/performance/run-instructions.ts "$GITHUB_WORKSPACE/head-instructions.json"

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.

Nothing checks that performance/run-instructions.ts exists in the paired tests branch. A tests branch cut before hyperformula-tests#91, or created from a develop that doesn't have the runner yet, makes this step stop with a ts-node module-not-found error and leaves the summary empty. If this PR merges before #91, every PR gets that failing job.

Could we guard it the way performance.yml guards noise-history.json, and skip with a visible notice? Add this step before the count steps:

      - name: Check for the instruction-count runner
        id: runner
        run: |
          if [ -f head/hyperformula/test/hyperformula-tests/performance/run-instructions.ts ]; then
            echo "present=true" >> "$GITHUB_OUTPUT"
          else
            echo "::notice::The paired hyperformula-tests branch predates the instruction-count runner; skipping."
          fi

Then add if: steps.runner.outputs.present == 'true' to the two count steps and to "Compare the counts".

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.

Added the "Check for the instruction-count runner" step; the two count steps and "Compare the counts" now run only when it sets present=true (7ded1cc). #1852 has the same check in the instruction-count job of performance.yml (e36fd13).

A paired hyperformula-tests branch without performance/run-instructions.ts
made the count steps stop with a module-not-found error. The job now checks
for the runner and, when it is missing, skips the counts and the comparison
with a notice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (feat/hf-150-perf-gate@b3f2f68). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@                   Coverage Diff                    @@
##             feat/hf-150-perf-gate    #1814   +/-   ##
========================================================
  Coverage                         ?   97.36%           
========================================================
  Files                            ?      209           
  Lines                            ?    16524           
  Branches                         ?     3670           
========================================================
  Hits                             ?    16089           
  Misses                           ?      427           
  Partials                         ?        8           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This branch has not been deployed

No deployments
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