///|
pub(all) struct PeakBuffer {
id : String
bytes : Int64
offset : Int64
} derive(Eq, Debug, ToJson)
///|
pub(all) struct PeakExplanation {
bank : String
capacity : Int64
highwater : Int64
peak_live_bytes : Int64
peak_step : Int32
layout_over_budget_by : Int64
live_over_budget_by : Int64
highwater_minus_peak : Int64
live_buffers : Array[PeakBuffer]
} derive(Eq, Debug, ToJson)
///|
/// Explain the earliest live-byte peak for each assigned bank.
/// Excess live bytes apply to this bank assignment, not every possible assignment.
pub fn explain(
problem : Problem,
layout : Layout,
) -> Array[PeakExplanation] raise PlanError {
let summaries = summarize(problem, layout)
let by_id : Map[String, Buffer] = Map([])
for b in problem.buffers {
by_id[b.id] = b
}
summaries.map(fn(usage) {
let live_buffers : Array[PeakBuffer] = []
for p in layout.placements {
let b = by_id[p.id]
if p.bank == usage.bank &&
b.first <= usage.peak_step &&
usage.peak_step <= b.last {
live_buffers.push({ id: b.id, bytes: b.bytes, offset: p.offset, })
}
}
live_buffers.sort_by(fn(a, b) {
if a.bytes != b.bytes {
b.bytes.compare(a.bytes)
} else {
id_compare(a.id, b.id)
}
})
{
bank: usage.bank,
capacity: usage.capacity,
highwater: usage.highwater,
peak_live_bytes: usage.peak_live_bytes,
peak_step: usage.peak_step,
layout_over_budget_by: if usage.highwater > usage.capacity {
usage.highwater - usage.capacity
} else {
0L
},
live_over_budget_by: if usage.peak_live_bytes > usage.capacity {
usage.peak_live_bytes - usage.capacity
} else {
0L
},
highwater_minus_peak: usage.highwater - usage.peak_live_bytes,
live_buffers,
}
})
}
///|
pub extend PeakBuffer with Eq::{equal, not_equal}
///|
pub extend PeakBuffer with @debug.Debug::{to_repr}
///|
pub extend PeakBuffer with ToJson::{to_json}
///|
pub extend PeakExplanation with Eq::{equal, not_equal}
///|
pub extend PeakExplanation with @debug.Debug::{to_repr}
///|
pub extend PeakExplanation with ToJson::{to_json}