Skip to content

Annotation Form Performance Baseline

This benchmark records the v1 annotation-form baseline before AF2 and its Angular 22 comparison point after Track 0 and Phase 1. Phase 3 uses the Angular 22 measurement as its before/after reference.

Results

Date Commit Machine Initial render Study navigation Keystroke-to-paint p95 Tab switch
2026-08-04 72f38768c local dev 4461 ms 93 ms 388 ms
2026-08-06 4c1af0a20 GitHub Actions ubuntu-latest / Angular 22 8210 ms 2665 ms 111.3 ms 3679 ms

Seeded shape

The Playwright scenario creates one study and 100 textbox annotation questions: 60 Study questions and 40 Cohort questions. The cohort set has 20 root questions and 20 child questions whose Target.ParentId values each point to a root. It then creates 15 cohort units through the annotation UI before sampling keystroke-to-paint and tab-switch latency.

Invocation

From e2e/, with the local E2E infrastructure and .NET services running:

pnpm test:perf

The test attaches the four metrics as perf JSON to the Playwright result and also prints them with console.table.

Angular 22 re-measure (2026-08-06)

The repository's isolated full-E2E workflow measured the Angular 22 platform on PR #2702, run 31059742925. The scenario passed on its second retry after two study-navigation timeouts; the successful attempt emitted the values above. Runner and retry variability mean these are a comparison baseline rather than a product service-level objective. Phase 3 must run the same isolated scenario and report its delta against this row.

AF2 Phase 3.5 performance gate

The AF2 benchmark is a separate Playwright scenario so the v1 history above remains unchanged. It overrides only the browser response for appConfig.env.json, setting annotationFormV2 to "true" for that test; no committed runtime configuration or default feature flag is changed.

The scenario creates one ordinary, non-extraction review stage with 1,000 supported textbox questions split evenly between Study and Cohort. AF2 has one synthetic Study unit in this shape; Cohort deliberately has no extraction units, which makes switching to its empty unit workspace a visible transition without broadening the Phase 3 non-experiment seed model.

Date Commit Machine AF2 host-to-first interactive Route-to-first interactive (diagnostic) Edit-to-microtask-settle p95 Edit-to-paint p95 (diagnostic) Category switch Mounted controls / units Forced-GC heap plateau spread Route-to-first-interactive delta vs Angular 22 v1
2026-08-10 17cc57e28 GitHub Actions ubuntu-24.04 / Angular 22 662.7 ms 8135 ms 14 ms 16.3 ms 66.5 ms 6 / 1 229,016 B −75 ms (0.9% faster)

A second ordinary, non-extraction scenario persists 200 Cohort label annotations through the authenticated review-session API. The normal AF2 load path then projects those labels into units and reconciles four supported child questions per unit, giving a representative repeated question graph while exercising the twenty-page bounded workspace without timing setup dialogs.

Date Commit Machine Session seed (diagnostic) Page-turn p95 Mounted controls / units / cards Forced-GC heap plateau spread
2026-08-10 17cc57e28 GitHub Actions ubuntu-24.04 / Angular 22 62.2 ms 173.4 ms 40 / 10 / 10 1,626,948 B (1.55 MiB)

The first-interactive budget combines host mount to the first painted, enabled Open all action with that action's click to the first painted, usable control. Both segments are recorded inside the browser so Playwright protocol and actionability waits between them are excluded, while blocked main-thread and rendering work remains counted. The separate route diagnostics include API latency and application startup outside the form so the cold-navigation result remains comparable with the v1 baseline.

The hard budgets are: AF2 host-to-first interactive under 1,500 ms, application edit-to-microtask-settle p95 under 16 ms, visible category switching under 250 ms, no more than 20 mounted controls or 10 mounted units, and no more than 8 MiB spread across four forced-GC samples after warm-up. The one-frame paint sample is diagnostic because frame scheduling is not the application-processing time. The 200-unit workload additionally requires page-turn p95 under 250 ms, at most 40 mounted controls and 10 mounted units/cards, and the same 8 MiB heap plateau.

These measurements were attached by the normal run:e2e-full execution on PR #2710, run 31387747461. All 18 Playwright scenarios passed (one unrelated bulk-update scenario passed on its normal retry). The run was marked unsuccessful only after the tests, when the workflow invoked teardown a second time while the Playwright web server still occupied its configured port. That shared teardown defect was fixed and merged in PR #2722; the next exact-head run supplies the final clean workflow gate. It does not change these browser measurements from commit 17cc57e28.