use std::fmt;
use std::time::Instant;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ChunkId(pub usize);
impl ChunkId {
pub const fn new(id: usize) -> Self {
ChunkId(id)
}
pub fn as_usize(&self) -> usize {
self.0
}
}
impl PartialEq<usize> for ChunkId {
fn eq(&self, other: &usize) -> bool {
self.0 == *other
}
}
impl From<ChunkId> for usize {
fn from(id: ChunkId) -> Self {
id.0
}
}
impl fmt::Display for ChunkId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SegmentId(pub usize);
impl SegmentId {
pub const fn new(id: usize) -> Self {
SegmentId(id)
}
pub fn as_usize(&self) -> usize {
self.0
}
}
impl PartialEq<usize> for SegmentId {
fn eq(&self, other: &usize) -> bool {
self.0 == *other
}
}
impl From<SegmentId> for usize {
fn from(id: SegmentId) -> Self {
id.0
}
}
impl fmt::Display for SegmentId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
pub enum StatsType {
Main,
Memory,
Opcodes,
Precompiled,
Tables,
Other,
}
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct StatsCostPerType {
pub main_cost: u64,
pub opcode_cost: u64,
pub memory_cost: u64,
pub precompile_cost: u64,
pub tables_cost: u64,
pub other_cost: u64,
}
impl StatsCostPerType {
pub fn total_cost(&self) -> u64 {
self.main_cost
+ self.opcode_cost
+ self.memory_cost
+ self.precompile_cost
+ self.tables_cost
+ self.other_cost
}
pub fn add_cost(&mut self, stats_type: StatsType, cost: u64) {
match stats_type {
StatsType::Main => self.main_cost += cost,
StatsType::Opcodes => self.opcode_cost += cost,
StatsType::Memory => self.memory_cost += cost,
StatsType::Precompiled => self.precompile_cost += cost,
StatsType::Tables => self.tables_cost += cost,
StatsType::Other => self.other_cost += cost,
}
}
}
impl fmt::Display for StatsCostPerType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let total = self.total_cost();
if total == 0 {
return write!(f, "total=0");
}
let mut parts = Vec::new();
let pct = (self.main_cost as f64 / total as f64) * 100.0;
parts.push(format!("main={} ({:.1}%)", self.main_cost, pct));
let pct = (self.opcode_cost as f64 / total as f64) * 100.0;
parts.push(format!("opcode={} ({:.1}%)", self.opcode_cost, pct));
let pct = (self.memory_cost as f64 / total as f64) * 100.0;
parts.push(format!("memory={} ({:.1}%)", self.memory_cost, pct));
let pct = (self.precompile_cost as f64 / total as f64) * 100.0;
parts.push(format!("precompile={} ({:.1}%)", self.precompile_cost, pct));
let pct = (self.tables_cost as f64 / total as f64) * 100.0;
parts.push(format!("tables={} ({:.1}%)", self.tables_cost, pct));
if self.other_cost > 0 {
let pct = (self.other_cost as f64 / total as f64) * 100.0;
parts.push(format!("other={} ({:.1}%)", self.other_cost, pct));
}
write!(f, "total={} [{}]", total, parts.join(", "))
}
}
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct ZiskExecutorTime {
pub total_duration: u64,
pub execution_duration: u64,
pub count_and_plan_duration: u64,
pub count_and_plan_mo_duration: u64,
pub asm_execution_duration: Option<AsmExecutionInfo>,
}
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct AirInstanceCount {
pub airgroup_id: usize,
pub air_id: usize,
pub count: u64,
}
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct ZiskExecutorSummary {
pub steps: u64,
pub executor_time: ZiskExecutorTime,
pub cost_per_type: StatsCostPerType,
pub plan: Vec<AirInstanceCount>,
}
impl ZiskExecutorSummary {
pub fn new(
executed_steps: u64,
execution_time: ZiskExecutorTime,
cost_per_type: StatsCostPerType,
) -> Self {
Self {
steps: executed_steps,
executor_time: execution_time,
cost_per_type,
..Default::default()
}
}
}
#[derive(Debug, Clone)]
pub struct Stats {
pub airgroup_id: usize,
pub air_id: usize,
pub collect_start_time: Instant,
pub collect_duration: u64,
pub witness_start_time: Instant,
pub witness_duration: u128,
pub num_chunks: usize,
}
impl Stats {
pub fn new_no_collection(airgroup_id: usize, air_id: usize) -> Self {
Self {
airgroup_id,
air_id,
collect_start_time: Instant::now(),
collect_duration: 0,
witness_start_time: Instant::now(),
witness_duration: 0,
num_chunks: 0,
}
}
pub fn new_pending_collection(airgroup_id: usize, air_id: usize, num_chunks: usize) -> Self {
Self {
airgroup_id,
air_id,
collect_start_time: Instant::now(),
collect_duration: 0,
witness_start_time: Instant::now(),
witness_duration: 0,
num_chunks,
}
}
pub fn new_with_collection(
airgroup_id: usize,
air_id: usize,
num_chunks: usize,
collect_start_time: Instant,
collect_duration: u64,
) -> Self {
Self {
airgroup_id,
air_id,
collect_start_time,
collect_duration,
witness_start_time: Instant::now(),
witness_duration: 0,
num_chunks,
}
}
pub fn new_main_completed(
airgroup_id: usize,
air_id: usize,
witness_start_time: Instant,
) -> Self {
Self {
airgroup_id,
air_id,
collect_start_time: Instant::now(),
collect_duration: 0,
witness_start_time,
witness_duration: witness_start_time.elapsed().as_millis(),
num_chunks: 0,
}
}
}
#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct AsmExecutionInfo {
pub time: f32,
pub mhz: f32,
}
impl fmt::Display for AsmExecutionInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:.3}s ({:.0} MHz)", self.time, self.mhz)
}
}