All checks were successful
joule-moq-remote host agent / joule-moq-remote · does this change touch it (pull_request) Successful in 6s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 7s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
wai-app and Create / wai-app · does this change touch it (pull_request) Successful in 6s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 6s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 6s
WAI operation catalogue / does this change touch it (pull_request) Successful in 6s
WAI conformance / does this change touch it (pull_request) Successful in 6s
WAI energy receipts / does this change touch it (pull_request) Successful in 5s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 6s
wai-fleet service / does this change touch it (pull_request) Successful in 6s
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Successful in 7s
wai-ledger service / does this change touch it (pull_request) Successful in 6s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (pull_request) Successful in 1m25s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 6s
wai-quantum for JavaScript / does this change touch it (pull_request) Successful in 6s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 6s
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 6s
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 6s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 1m57s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m7s
WAI Studio / does this change touch it (pull_request) Successful in 6s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 6s
wai-web wasm32 / does this change touch it (pull_request) Successful in 6s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (pull_request) Successful in 29s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 2m1s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 2m59s
wai-audit collector and player integration / collector · linux (pull_request) Successful in 1m1s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 26s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 4m19s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 16s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m4s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Successful in 1m15s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Successful in 5m15s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 6m19s
wai-fleet service / service · macos (pull_request) Successful in 1m2s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Successful in 2m46s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 1m43s
wai-ledger service / service · macos (pull_request) Successful in 1m24s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m2s
WAI operation catalogue / the catalogue and every door · linux (pull_request) Successful in 4m18s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 9m19s
wai-pack / wai-pack · macos (pull_request) Successful in 3m8s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 30s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 7m49s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 3m23s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m39s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m9s
wai-fleet service / service · linux (pull_request) Successful in 2m5s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 3m28s
wai-ledger service / service · linux (pull_request) Successful in 1m43s
wai-pack / wai-pack · linux (pull_request) Successful in 1m55s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 3m0s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 1m10s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 16m12s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 11m32s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 4m51s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 13m12s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 15m2s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 4m3s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 16m34s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m40s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 17m22s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m44s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m46s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 34s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 17s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 9m28s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m7s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 14m49s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m34s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m16s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 11m4s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 13m6s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 5m58s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 10m55s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 9m51s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 10m15s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 9m21s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 30m14s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h4m7s
Every change to WAI added an entry at the head of wai/CHANGELOG.md, and every new module appended to the hand-kept lists of .github/workflows/wai-conformance.yml. So any two branches conflicted on those lines and had to merge one after another. This moves both into files a change adds. - Changelog entries: a change adds wai/changes/<yyyy-mm-dd>-<slug>.md holding the entry text. scripts/changelog-assemble.py renders the entries into CHANGELOG.md's Unreleased section for a release, in a stable order. scripts/check-changelog-fragment.py, run by repo-checks on every pull request, fails a pull request that changes wai/ and adds or edits no entry file directly in wai/changes/ (a release passes, and so does a commit with the trailer line "Changelog: none"). A pull request opened before the check reached main passes as it is; one opened after it that adds its entry to the head of Unreleased fails and is told where the entry goes. wai breaking reads breaking changes from entry files too. - The conformance workflow: each per-module verifier step is a file in .github/wai-conformance/verifiers/, each corpus a file in corpora/, and the integer-kernel tests carry a tag line. scripts/wai-conformance-lists.py derives every list the workflow kept by hand (WAI_FEATURES, the union --bin and --test lists, the features-alone lists, the kernel and corpus steps) from those files when the workflow runs. Its `selftest --exact` holds the derived lists to the hand lists of the commit before this one, and its dry-run prints every command each job runs: the dry-runs before and after this change differ only in the gate's path list, which gains the two paths this change adds. - What stays shared, and how to insert there, is written in wai/CONTRIBUTING.md and wai/changes/README.md: wai-rs Cargo.toml features and [[test]] entries, lib.rs, registry rows, wai/.gitattributes and the live corpus table take an insert beside the related entry, never at the end. Co-Authored-By: Claude Opus 5.5 <[email protected]>
109 lines
6.3 KiB
Rust
109 lines
6.3 KiB
Rust
// wai-conformance: int-kernels
|
|
//! What `wai.world.model`'s integer renderer holds, through the integer operator set,
|
|
//! against the direct renderer it replaced (`int_world::legacy`, feature `legacy_int`),
|
|
//! measured with a global allocator that tracks the bytes live and their peak.
|
|
//!
|
|
//! The renderer declares no cost: it has no payload (`extensions/integer-operators.md`
|
|
//! §13.5, informative). So what it holds is held to the direct renderer: with the set
|
|
//! loaded beforehand (`int_world::load`, once per clip or per session, as the browser's
|
|
//! `WorldModel` holds it), a clip through the operator set holds at least its frames and
|
|
//! no more than the direct renderer holds for the same clip, both on the reference
|
|
//! kernels; and so does each step and each frame of the live path.
|
|
//!
|
|
//! Its own test binary with a single test, so that no other test's allocations land in
|
|
//! the window it measures.
|
|
#![cfg(all(feature = "world_int", feature = "legacy_int"))]
|
|
|
|
use std::alloc::{GlobalAlloc, Layout, System};
|
|
use std::path::PathBuf;
|
|
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
|
|
|
use serde_json::Value;
|
|
use wai::int_hyper_synth::IntModel;
|
|
use wai::int_kernels::{with_policy, Policy};
|
|
use wai::int_world::{self, legacy, ACTIONS};
|
|
|
|
/// The system allocator, tracking the bytes live and the most live at once.
|
|
struct Live;
|
|
static CUR: AtomicUsize = AtomicUsize::new(0);
|
|
static PEAK: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
unsafe impl GlobalAlloc for Live {
|
|
unsafe fn alloc(&self, l: Layout) -> *mut u8 {
|
|
PEAK.fetch_max(CUR.fetch_add(l.size(), Relaxed) + l.size(), Relaxed);
|
|
unsafe { System.alloc(l) }
|
|
}
|
|
unsafe fn alloc_zeroed(&self, l: Layout) -> *mut u8 {
|
|
PEAK.fetch_max(CUR.fetch_add(l.size(), Relaxed) + l.size(), Relaxed);
|
|
unsafe { System.alloc_zeroed(l) }
|
|
}
|
|
unsafe fn realloc(&self, p: *mut u8, l: Layout, new: usize) -> *mut u8 {
|
|
if new >= l.size() {
|
|
PEAK.fetch_max(CUR.fetch_add(new - l.size(), Relaxed) + (new - l.size()), Relaxed);
|
|
} else {
|
|
CUR.fetch_sub(l.size() - new, Relaxed);
|
|
}
|
|
unsafe { System.realloc(p, l, new) }
|
|
}
|
|
unsafe fn dealloc(&self, p: *mut u8, l: Layout) {
|
|
CUR.fetch_sub(l.size(), Relaxed);
|
|
unsafe { System.dealloc(p, l) }
|
|
}
|
|
}
|
|
|
|
#[global_allocator]
|
|
static ALLOC: Live = Live;
|
|
|
|
/// The most bytes `f` holds at once beyond what was live when it started, and its result
|
|
/// (still held when the measure is taken).
|
|
fn peak_during<R>(f: impl FnOnce() -> R) -> (R, u64) {
|
|
let base = CUR.load(Relaxed);
|
|
PEAK.store(base, Relaxed);
|
|
let r = f();
|
|
(r, (PEAK.load(Relaxed) - base) as u64)
|
|
}
|
|
|
|
fn read(rel: &str) -> Vec<u8> {
|
|
let p = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/vectors").join(rel);
|
|
std::fs::read(&p).unwrap_or_else(|e| panic!("{}: {e}", p.display()))
|
|
}
|
|
|
|
#[test]
|
|
fn the_renderer_holds_no_more_than_the_direct_renderer() {
|
|
for (d, js, t, g) in [("int_world", "world.json", "world_T.bin", "world_gs.bin"), ("int_world2", "world2.json", "world2_T.bin", "world2_gs.bin")] {
|
|
let j: Value = serde_json::from_slice(&read(&format!("{d}/{js}"))).unwrap();
|
|
let (c, lat, afrac) = (j["c"].as_u64().unwrap() as usize, j["lat"].as_u64().unwrap() as usize, j["afrac"].as_u64().unwrap() as u32);
|
|
let z0: Vec<i64> = j["z0"].as_array().unwrap().iter().map(|v| v.as_i64().unwrap()).collect();
|
|
let mv = |a: &Value| ACTIONS[a.as_u64().unwrap() as usize];
|
|
let rows: Vec<Vec<i64>> = match j.get("pairs") {
|
|
Some(p) => p.as_array().unwrap().iter().map(|p| {
|
|
let ((xa, ya), (xb, yb)) = (mv(&p[0]), mv(&p[1]));
|
|
[xa, ya, xb, yb].iter().map(|v| v << afrac).collect()
|
|
}).collect(),
|
|
None => j["actions"].as_array().unwrap().iter().map(|a| {
|
|
let (x, y) = mv(a);
|
|
vec![x << afrac, y << afrac, 0]
|
|
}).collect(),
|
|
};
|
|
let (tm, gm) = (IntModel::from_bytes(&read(&format!("{d}/{t}"))).unwrap(), IntModel::from_bytes(&read(&format!("{d}/{g}"))).unwrap());
|
|
// A clip: the direct renderer, then the renderer with its set loaded beforehand.
|
|
let (want, direct) = with_policy(Policy::reference(), || peak_during(|| legacy::decode_planes(&tm, &gm, &z0, &rows, c, lat)));
|
|
let (world, set) = peak_during(|| int_world::load(&tm, &gm, c).unwrap());
|
|
let (got, held) = with_policy(Policy::reference(), || peak_during(|| world.decode_planes(&z0, &rows, lat).unwrap()));
|
|
assert!(got.frames == want.frames, "{d}: the frames through the lowering are the direct renderer's");
|
|
let frames: u64 = got.frames.iter().map(|f| f.len() as u64).sum();
|
|
assert!(held >= frames && held <= direct, "{d}, set loaded: held {held}; the direct renderer held {direct}; the frames are {frames}");
|
|
// The whole call, which loads the set first.
|
|
let (r, whole) = with_policy(Policy::reference(), || peak_during(|| int_world::decode_planes(&tm, &gm, &z0, &rows, c, lat)));
|
|
drop(r.unwrap());
|
|
assert!(whole <= set + direct, "{d}: the call that loads the set held {whole}, over the set loaded ({set}) and the direct renderer's {direct}");
|
|
// The live path: one transition, then one frame, against the direct renderer's.
|
|
let (zd, step_direct) = with_policy(Policy::reference(), || peak_during(|| legacy::step_planes(&tm, &z0, &rows[0], c, lat)));
|
|
let (zo, step_held) = with_policy(Policy::reference(), || peak_during(|| world.step(&z0, &rows[0], lat).unwrap()));
|
|
assert!(zo == zd && step_held <= step_direct, "{d}: one step held {step_held}; the direct step held {step_direct}");
|
|
let (fd, frame_direct) = with_policy(Policy::reference(), || peak_during(|| legacy::decode_planes(&tm, &gm, &zd, &[], c, lat).frames));
|
|
let (fo, frame_held) = with_policy(Policy::reference(), || peak_during(|| world.render(&zo, lat).unwrap().0));
|
|
assert!(fo == fd[0] && frame_held <= frame_direct, "{d}: one frame held {frame_held}; the direct frame held {frame_direct}");
|
|
println!("{d}: a clip of {} frames, set loaded beforehand, held {held}; the direct renderer held {direct}; loading the set held {set}; the call that loads it held {whole}; one step held {step_held} (direct {step_direct}); one frame {frame_held} (direct {frame_direct})", got.frames.len());
|
|
}
|
|
}
|