assets/art_throughput_measurements.json
{
"_note": "THE MEASURED ART-LANE THROUGHPUT RECORD. Every s/plate and MB/plate figure in docs/CONCEPT_ART_PRODUCTION_PROGRAM.md section 3 comes from this file, and this file comes from a real run on the real box -- never from a published benchmark, never from arithmetic over a parameter count. Re-measure with `python harness/art_throughput.py --measure`, which overwrites this file and re-emits the plan. A figure that cannot be re-measured is not allowed to size a schedule.",
"schema_version": "1.0.0",
"measured_at": "2026-08-02T19:05:00-04:00",
"machine": {
"gpu": "NVIDIA GeForce RTX 5090",
"vram_total_mib": 32607,
"ram_total_bytes": 134943383552,
"cpu_class": "AMD Ryzen 9 9950X3D",
"art_scratch_drive": "D:",
"art_root_drive": "E:",
"provenance": "docs/5090_SETUP_RUNBOOK.md line 1276 -- the Windows-native ART instance at 127.0.0.1:8189 is the only ComfyUI instance that exists on this box"
},
"stack": {
"host": "ComfyUI 0.29.0",
"host_argv": "main.py --listen 127.0.0.1 --port 8189 --output-directory D:\\ComfyUI\\output",
"torch": "2.9.0+cu128",
"python": "3.12.10",
"model_file": "z_image_turbo_bf16.safetensors",
"model_id": "Tongyi-MAI/Z-Image-Turbo",
"model_licence": "Apache-2.0",
"licence_class": "shippable",
"licence_provenance": "docs/pipeline_review/tech_research/PIPE_ART_2026-07-29.md section 1 Tier SHIPPABLE -- 'T2I fast-iteration / 4th wildcard option ... Apache-2.0'",
"text_encoder": "qwen_3_4b.safetensors",
"vae": "ae.safetensors",
"sampler": "res_multistep",
"scheduler": "simple",
"cfg": 1.0,
"model_sampling_shift": 3.0
},
"caveat": {
"installed_is_not_the_ruled_primary": "PIPE_ART section 1 rules HiDream-O1-Image-Dev (MIT, 28 steps, up to 2048 squared) as the T2I PRIMARY and Qwen-Image-2512 (Apache-2.0) as co-primary. NEITHER IS INSTALLED on this box; `models/diffusion_models/` holds z_image_turbo_bf16 only. Every number below is therefore MEASURED for Z-Image-Turbo and is a FLOOR-ON-COST / CEILING-ON-SPEED for the eventual primary: HiDream at its published 28 steps costs about 3.5x the sampling of an 8-step Z-Image pass at equal resolution. The schedule in the production program is stated at BOTH ends so nothing rests on the fast model staying the pick.",
"scaling_rule_for_the_primary": "steps_ratio = 28/8 = 3.5. Apply to the sampling term only; the fixed per-prompt overhead (text encode + VAE decode + queue) is measured below as `fixed_overhead_s` and does not scale with steps."
},
"configs": [
{
"tier": "ITERATION",
"label": "1024x1024 s8 b1",
"width": 1024,
"height": 1024,
"steps": 8,
"batch": 1,
"runs": 5,
"min_s": 2.78,
"median_s": 2.78,
"max_s": 3.03,
"s_per_plate": 2.78,
"plates_per_hour": 1295.5,
"peak_vram_mib": 20653,
"bytes_mean_mib": 1.53,
"bytes_max_mib": 1.7,
"bytes_samples": 5
},
{
"tier": "ITERATION_BATCHED",
"label": "1024x1024 s8 b4",
"width": 1024,
"height": 1024,
"steps": 8,
"batch": 4,
"runs": 2,
"min_s": 10.81,
"median_s": 11.63,
"max_s": 11.63,
"s_per_plate": 2.91,
"plates_per_hour": 1238.6,
"peak_vram_mib": 20623,
"bytes_mean_mib": 1.64,
"bytes_max_mib": 1.68,
"bytes_samples": 8,
"finding": "BATCHING IS NOT A LEVER. 2.91 s/plate at batch 4 is SLOWER per plate than 2.78 at batch 1. The queue is compute-bound, not per-prompt-overhead-bound, so no scheduling cleverness buys throughput here -- only resolution and step count do. Recorded because the obvious optimisation is the wrong one and someone will otherwise spend a day on it."
},
{
"tier": "REVIEW",
"label": "1344x1344 s8 b1",
"width": 1344,
"height": 1344,
"steps": 8,
"batch": 1,
"runs": 3,
"min_s": 5.3,
"median_s": 5.35,
"max_s": 5.8,
"s_per_plate": 5.35,
"plates_per_hour": 672.7,
"peak_vram_mib": 20623,
"bytes_mean_mib": 2.75,
"bytes_max_mib": 3.0,
"bytes_samples": 3
},
{
"tier": "HERO_FAST",
"label": "2048x2048 s8 b1",
"width": 2048,
"height": 2048,
"steps": 8,
"batch": 1,
"runs": 3,
"min_s": 14.8,
"median_s": 15.04,
"max_s": 15.1,
"s_per_plate": 15.04,
"plates_per_hour": 239.4,
"peak_vram_mib": 20623,
"bytes_mean_mib": 6.64,
"bytes_max_mib": 7.14,
"bytes_samples": 3
},
{
"tier": "HERO",
"label": "2048x2048 s20 b1",
"width": 2048,
"height": 2048,
"steps": 20,
"batch": 1,
"runs": 3,
"min_s": 34.29,
"median_s": 34.38,
"max_s": 34.76,
"s_per_plate": 34.38,
"plates_per_hour": 104.7,
"peak_vram_mib": 20344,
"bytes_mean_mib": 6.67,
"bytes_max_mib": 7.07,
"bytes_samples": 3
}
],
"derived_overhead": {
"_method": "Two 2048-squared points at 8 and 20 steps isolate the fixed term: (34.38 - 15.04) / (20 - 8) = 1.6117 s/step at 2048 squared; fixed = 15.04 - 8*1.6117 = 2.147 s.",
"s_per_step_at_2048": 1.6117,
"fixed_overhead_s": 2.147
},
"vram_law": {
"art_lane_peak_mib": 20653,
"headroom_mib": 11954,
"rule": "docs/5090_SETUP_RUNBOOK.md line 1572 (D-11b): 'keep 04:00 as the serialized nightly reservation; never overlap asset-gen on VRAM'. The ART lane's measured 20,653 MiB leaves 11,954 MiB, which is NOT enough to hold a UE 5.8 editor session with a loaded landscape beside it with any margin. The serialization is therefore a measurement, not only a ruling.",
"night_window_hours": 8.0,
"night_window_note": "20:00 -> 04:00. The 04:00 soak is the standing reservation; the queue drains before it and does not resume until the soak reports."
}
}