///|
pub struct WorkloadCounters {
mut scenes : Int
mut pixels : Int
mut boxes : Int
mut mask_pixels : Int
mut flow_vectors : Int
mut image_checksum : UInt
mut annotation_checksum : UInt
} derive(Debug, Eq)
///|
pub fn WorkloadCounters::empty() -> WorkloadCounters {
{
scenes: 0,
pixels: 0,
boxes: 0,
mask_pixels: 0,
flow_vectors: 0,
image_checksum: 2166136261,
annotation_checksum: 2166136261,
}
}
///|
pub fn WorkloadCounters::add_scene(
self : WorkloadCounters,
scene : SceneOutput,
) -> Unit {
self.scenes += 1
self.pixels += scene.image.width * scene.image.height
self.boxes += scene.boxes.length()
self.mask_pixels += scene.mask.count(1)
self.flow_vectors += scene.flow.length()
self.image_checksum = (self.image_checksum ^ image_checksum(scene.image)) *
16777619
self.annotation_checksum = (
self.annotation_checksum ^ mask_checksum(scene.mask)
) *
16777619
for box in scene.boxes {
self.annotation_checksum = (
self.annotation_checksum ^ box.rect.x.reinterpret_as_uint()
) *
16777619
self.annotation_checksum = (
self.annotation_checksum ^ box.rect.y.reinterpret_as_uint()
) *
16777619
}
}
///|
pub fn WorkloadCounters::add(
self : WorkloadCounters,
other : WorkloadCounters,
) -> Unit {
self.scenes += other.scenes
self.pixels += other.pixels
self.boxes += other.boxes
self.mask_pixels += other.mask_pixels
self.flow_vectors += other.flow_vectors
self.image_checksum = (self.image_checksum ^ other.image_checksum) * 16777619
self.annotation_checksum = (
self.annotation_checksum ^ other.annotation_checksum
) *
16777619
}
///|
pub fn measure_workload(scenes : Array[SceneOutput]) -> WorkloadCounters {
let counters = WorkloadCounters::empty()
for scene in scenes {
counters.add_scene(scene)
}
counters
}
///|
pub fn measure_plan_workload(plans : Array[ScenePlan]) -> WorkloadCounters {
measure_workload(render_suite(plans))
}
///|
pub fn WorkloadCounters::mean_pixels(self : WorkloadCounters) -> Int {
self.pixels / max_i(1, self.scenes)
}
///|
pub fn WorkloadCounters::annotation_density_per_1000(
self : WorkloadCounters,
) -> Int {
self.boxes * 1000 / max_i(1, self.scenes)
}
///|
pub fn WorkloadCounters::to_json(self : WorkloadCounters) -> String {
"{\"scenes\":\{self.scenes},\"pixels\":\{self.pixels},\"boxes\":\{self.boxes},\"mask_pixels\":\{self.mask_pixels},\"flow_vectors\":\{self.flow_vectors},\"image_checksum\":\{self.image_checksum},\"annotation_checksum\":\{self.annotation_checksum},\"mean_pixels\":\{self.mean_pixels()}}"
}
///|
pub struct BenchmarkSnapshot {
name : String
counters : WorkloadCounters
stable : Bool
} derive(Debug, Eq)
///|
pub fn BenchmarkSnapshot::capture(
name~ : String,
plans : Array[ScenePlan],
) -> BenchmarkSnapshot {
let first = measure_plan_workload(plans)
let second = measure_plan_workload(plans)
{ name, counters: first, stable: first == second }
}
///|
pub fn BenchmarkSnapshot::to_json(self : BenchmarkSnapshot) -> String {
"{\"name\":\"\{escape_json(self.name)}\",\"stable\":\{self.stable},\"counters\":{self.counters.to_json()}}"
}
///|
pub fn compare_workloads(
before : WorkloadCounters,
after : WorkloadCounters,
) -> String {
"{\"scene_delta\":\{after.scenes - before.scenes},\"pixel_delta\":\{after.pixels - before.pixels},\"box_delta\":\{after.boxes - before.boxes},\"flow_delta\":\{after.flow_vectors - before.flow_vectors},\"checksum_changed\":\{before.image_checksum != after.image_checksum}}"
}
///|
pub fn validate_workload(counters : WorkloadCounters) -> ValidationReport {
let report = ValidationReport::new()
if counters.scenes < 0 || counters.pixels < 0 {
report.error("benchmark counters cannot be negative")
}
if counters.boxes < 0 || counters.flow_vectors < 0 {
report.error("annotation counters cannot be negative")
}
if counters.pixels > 0 && counters.scenes == 0 {
report.error("pixel count requires at least one scene")
}
report
}
///|
pub fn suite_benchmark_json(plans : Array[ScenePlan], name : String) -> String {
BenchmarkSnapshot::capture(name~, plans).to_json()
}
///|
pub fn benchmark_checksum(plans : Array[ScenePlan]) -> UInt {
let counters = measure_plan_workload(plans)
counters.image_checksum ^ counters.annotation_checksum
}