Align GenAI perf metrics schema - #1307
Merged
Qiong Wu (qiowu) (DingmaomaoBJTU) merged 2 commits intoAug 13, 2026
Merged
Conversation
Qiong Wu (qiowu) (DingmaomaoBJTU)
requested a review
from a team
as a code owner
August 13, 2026 02:58
xieofxie
reviewed
Aug 13, 2026
xieofxie
approved these changes
Aug 13, 2026
xieofxie
left a comment
Contributor
There was a problem hiding this comment.
Reviewed the latest revision; prior findings are addressed and no new issues remain.
Qiong Wu (qiowu) (DingmaomaoBJTU)
deleted the
align-genai-perf-metrics-schema
branch
August 13, 2026 06:51
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
winml perf --runtime winml-genaiwas reporting LLM timing as a small set of aggregate fields, while classicwinml perfused a different report surface. That made it hard to answer basic questions consistently across runtimes:This PR makes GenAI perf emit a canonical phase-based schema and aligns the shared metadata/memory surfaces with classic perf, while keeping Ollama/OpenVINO-style projections out of the benchmark core.
What changed
GenAI report schema
Adds a canonical top-level GenAI JSON shape:
schema_versionbenchmark_infoloadrequestsaggregatememoryhw_monitorThe old GenAI-only
accuracyplaceholder is removed. Accuracy/eval belongs in eval/reporting flows, not raw perf output.Load/startup metrics
GenAI load now records a breakdown around the
onnxruntime-genaiload path:session_load_duration_ms: end-to-endGenaiSession.load()wall timeep_registration_duration_ms: WinML EP plugin registration time when requiredbundle_prepare_duration_ms: derived bundle preparation / compile-or-rewrite timenative_load_duration_ms: nativeog.Config+og.Model+og.Tokenizercreation timeconfig_create_duration_ms:og.Config(...)creation timemodel_create_duration_ms:og.Model(...)creation timetokenizer_create_duration_ms:og.Tokenizer(...)creation timeweight_upload_duration_ms: currentlynullbecause ORT GenAI does not expose exact native weight upload telemetryweight_upload_estimate_duration_ms: currently usesmodel_create_duration_msweight_upload_estimate_source: documents the estimate source explicitlyThis avoids reporting a misleading exact weight-upload number while still exposing the closest observable boundary.
Per-request GenAI timing
Each warmup and timed generation is preserved under
requests, withkindandindex, so consumers can inspect raw request-level behavior. The aggregate block excludes warmup requests.Per request, timing is split into:
Derived request metrics include:
request_ttft_duration_ms: template + tokenization + generator creation + prefill + first tokenmodel_ttft_duration_ms: prefill + first tokenresponse_eval_duration_ms: first token + decode token stepsmodel_compute_duration_ms: prefill + response evalrequest_duration_ms: full request wall-clock boundary covered by the measured sub-phasesprefill_tokens_per_secondsteady_state_decode_tokens_per_secondresponse_eval_tokens_per_secondsteady_state_tpot_msAggregates
aggregatereports warmup-excluded statistics for the timed requests, including mean/min/max/percentiles/stddev where applicable, plus:warmup_excludedwarmup_request_counttimed_request_countcold_start_ttft_duration_mscold_start_total_duration_msMonitor and memory route correctness
GenAI now resolves the effective bundle route before monitor and memory sampling are initialized. This avoids using requested CLI values like
device=configor a no-op EP override to select unrelated hardware.hw_monitoruses the proven effective accelerator route when one exists; otherwise it records CPU/RAM only.hw_monitor["adapter"]over aggregatehw_monitor["gpu"], matching classic perf behavior on multi-GPU systems.Classic / GenAI alignment
Shared report surfaces are aligned where the concepts are common:
schema_version: 2.benchmark_info.runtime: "winml".benchmark_infonow includesmodel_idandrunning_model_path.hw_monitor, matching classic perf naming.Checkpoint maxima are named explicitly as checkpoint maxima, not continuous peaks:
rss_checkpoint_peak_mbvram_local_checkpoint_peak_mbvram_shared_checkpoint_peak_mbThese are the maximum of baseline / after-compile / after-inference samples. They do not claim to be continuously sampled memory peaks.
Intentional non-goals
weight_upload_duration_msis invented without native telemetry.accuracyblock is emitted from perf.load/requests/aggregateblocks instead of forcing classiclatency_ms/throughputfields into the core schema.Validation
uv run --no-sync pytest tests\unit\commands\test_perf_cli.py tests\unit\commands\test_perf_genai.py tests\unit\session\test_genai_session.py -q— 364 passeduv run --no-sync ruff check src\winml\modelkit\commands\perf.py src\winml\modelkit\commands\_perf_genai.py src\winml\modelkit\session\genai_session.py tests\unit\commands\test_perf_cli.py tests\unit\commands\test_perf_genai.py tests\unit\session\test_genai_session.py— passed