Skip to main content

sway_utils/
performance.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, Deserialize, Serialize)]
4pub struct CompilationPhaseMetrics {
5    pub phase: String,
6    pub elapsed: f64,
7    pub memory_usage: Option<u64>,
8}
9
10#[derive(Clone, Debug, Deserialize, Serialize)]
11pub struct ConcurrentSlabMetrics {
12    pub slab: String,
13    pub length: usize,
14    pub capacity: usize,
15    /// Approximate memory usage of the content of the slab [Vec].
16    pub memory_usage: usize,
17    /// Approximate memory usage of the total content of elements of type `T`
18    /// the slab slots point to via `Arc<T>`. **This does not
19    /// include any additional memory allocated by individual `T` elements,
20    /// just the raw size of each `T`.**
21    pub content_memory_usage: usize,
22    pub free_slots_length: usize,
23    pub free_slots_capacity: usize,
24}
25
26#[derive(Clone, Debug, Default, Deserialize, Serialize)]
27pub struct DeclEngineMetrics {
28    pub slabs: Vec<ConcurrentSlabMetrics>,
29}
30
31#[derive(Clone, Debug, Default, Deserialize, Serialize)]
32pub struct PerformanceMetrics {
33    pub bytecode_size: usize,
34    pub reused_programs: u64,
35    pub compilation_phases: Vec<CompilationPhaseMetrics>,
36    pub decl_engine: DeclEngineMetrics,
37}
38
39#[derive(serde::Serialize, Clone)]
40pub struct FunctionEntryPoint {
41    /// The original entry point function name.
42    pub fn_name: String,
43    /// The immediate instruction offset at which the entry function begins.
44    pub imm: u64,
45    /// The function selector (only `Some` for contract ABI methods).
46    pub selector: Option<[u8; 4]>,
47}
48
49#[macro_export]
50// Time the given expression and print/save the result.
51macro_rules! time_expr {
52    ($pkg_name:expr, $description:expr, $key:expr, $expression:expr, $build_config:expr, $data:expr) => {{
53        use std::io::{BufRead, Read, Write};
54        if let Some(cfg) = $build_config {
55            if cfg.profile {
56                println!("/dyno start {} {}", $pkg_name, $description);
57                let output = { $expression };
58                println!("/dyno stop {} {}", $pkg_name, $description);
59                output
60            } else if cfg.time_phases || cfg.metrics_outfile.is_some() {
61                let expr_start = std::time::Instant::now();
62                let output = { $expression };
63                let elapsed = expr_start.elapsed();
64                if cfg.time_phases {
65                    println!("  Time elapsed to {}: {:?}", $description, elapsed);
66                }
67                if cfg.metrics_outfile.is_some() {
68                    #[cfg(not(target_os = "macos"))]
69                    let memory_usage = {
70                        use sysinfo::{System, SystemExt};
71                        let mut sys = System::new();
72                        sys.refresh_system();
73                        Some(sys.used_memory())
74                    };
75                    #[cfg(target_os = "macos")]
76                    let memory_usage = None;
77
78                    $data.compilation_phases.push(CompilationPhaseMetrics {
79                        phase: $key.to_string(),
80                        elapsed: elapsed.as_secs_f64(),
81                        memory_usage,
82                    });
83                }
84                output
85            } else {
86                $expression
87            }
88        } else {
89            $expression
90        }
91    }};
92}