large_data_retention_benchmark/
large_data_retention_benchmark.rs1use std::time::Instant;
2
3use zirium::{
4 dialect::DialectRegistry,
5 parser::ParsedFile,
6 semantic::{LoweringMode, RetentionProfile, lower_with_dialect_registry_and_retention},
7};
8
9fn source(elements: usize) -> Vec<u8> {
10 let mut dense = String::from("dense<[");
11 for index in 0..elements {
12 if index != 0 {
13 dense.push_str(", ");
14 }
15 dense.push_str(&(index % 10).to_string());
16 }
17 dense.push_str("]> : tensor<");
18 dense.push_str(&elements.to_string());
19 dense.push_str("xi8>");
20
21 let mut sparse_indices = String::from("[");
22 let mut sparse_values = String::from("[");
23 for index in 0..elements {
24 if index != 0 {
25 sparse_indices.push_str(", ");
26 sparse_values.push_str(", ");
27 }
28 sparse_indices.push_str(&format!("[{index}, 0]"));
29 sparse_values.push_str(&(index % 10).to_string());
30 }
31 sparse_indices.push(']');
32 sparse_values.push(']');
33
34 let opaque = "#vendor.attr<{ note = \"body\" }>";
35 format!(
36 "\"bench.payload\"() {{dense_value = {dense}, sparse_value = sparse<{sparse_indices}, {sparse_values}> : tensor<{elements}x1xi8>, resource_value = dense_resource<resource_handle> : tensor<1xi8>, wide_value = 0x1234567890abcdef : i128, opaque_value = {opaque} }} : () -> ()\n"
37 )
38 .into_bytes()
39}
40
41#[derive(Debug)]
42struct Measurement {
43 source_bytes: usize,
44 semantic_attributes: usize,
45 payload_bytes: usize,
46 payload_blobs: usize,
47 cst_nodes: usize,
48 mappings: usize,
49 direct_owned_bytes: usize,
50 document_index_bytes: usize,
51 retained_cst_bytes: usize,
52 source_shared: bool,
53 cst_shared: bool,
54 lower_us: u128,
55}
56
57fn measure(elements: usize, profile: RetentionProfile) -> Measurement {
58 let bytes = source(elements);
59 let source_len = bytes.len();
60 let parsed = ParsedFile::parse(bytes).expect("benchmark input parses");
61 let started = Instant::now();
62 let result = lower_with_dialect_registry_and_retention(
63 &parsed,
64 LoweringMode::Strict,
65 profile,
66 &DialectRegistry::EMPTY,
67 );
68 assert!(result.diagnostics.is_empty(), "{:?}", result.diagnostics);
69 let document = result.document.expect("benchmark input lowers");
70 document.validate().expect("benchmark document validates");
71 let stats = document.statistics();
72 assert_eq!(document.retention_profile(), profile);
73 assert_eq!(
74 stats.retained_source_bytes,
75 match profile {
76 RetentionProfile::SemanticOnly => 0,
77 RetentionProfile::SyntaxOnly | RetentionProfile::Hybrid => source_len,
78 }
79 );
80 assert_eq!(
81 stats.retained_cst_nodes > 0,
82 profile != RetentionProfile::SemanticOnly
83 );
84 assert_eq!(
85 stats.retained_mapping_entries,
86 match profile {
87 RetentionProfile::Hybrid => 1,
88 RetentionProfile::SyntaxOnly | RetentionProfile::SemanticOnly => 0,
89 }
90 );
91 Measurement {
92 source_bytes: source_len,
93 semantic_attributes: stats.local_attributes,
94 payload_bytes: stats.payload_blob_bytes,
95 payload_blobs: stats.payload_blobs,
96 cst_nodes: stats.retained_cst_nodes,
97 mappings: stats.retained_mapping_entries,
98 direct_owned_bytes: stats.direct_owned_bytes,
99 document_index_bytes: stats.document_index_bytes,
100 retained_cst_bytes: stats.retained_cst_bytes,
101 source_shared: stats.source_storage_shared,
102 cst_shared: stats.cst_storage_shared,
103 lower_us: started.elapsed().as_micros(),
104 }
105}
106
107fn main() {
108 let small = [
109 measure(100, RetentionProfile::SyntaxOnly),
110 measure(100, RetentionProfile::SemanticOnly),
111 measure(100, RetentionProfile::Hybrid),
112 ];
113 let large = [
114 measure(10_000, RetentionProfile::SyntaxOnly),
115 measure(10_000, RetentionProfile::SemanticOnly),
116 measure(10_000, RetentionProfile::Hybrid),
117 ];
118 for (small, large) in small.iter().zip(large.iter()) {
119 assert_eq!(small.semantic_attributes, large.semantic_attributes);
120 assert_eq!(small.payload_blobs, large.payload_blobs);
121 assert!(large.payload_bytes > small.payload_bytes * 50);
122 }
123 assert_eq!(small[0].cst_nodes, large[0].cst_nodes);
124 assert_eq!(small[2].mappings, 1);
125 assert_eq!(large[2].mappings, 1);
126
127 println!(
128 "elements,profile,source_bytes,semantic_attributes,payload_blobs,payload_bytes,cst_nodes,mappings,direct_owned_bytes,document_index_bytes,retained_cst_bytes,source_shared,cst_shared,lower_us"
129 );
130 for (elements, measurements) in [(100, &small), (10_000, &large)] {
131 for (profile, measurement) in [
132 ("SyntaxOnly", &measurements[0]),
133 ("SemanticOnly", &measurements[1]),
134 ("Hybrid", &measurements[2]),
135 ] {
136 println!(
137 "{elements},{profile},{},{},{},{},{},{},{},{},{},{},{},{}",
138 measurement.source_bytes,
139 measurement.semantic_attributes,
140 measurement.payload_blobs,
141 measurement.payload_bytes,
142 measurement.cst_nodes,
143 measurement.mappings,
144 measurement.direct_owned_bytes,
145 measurement.document_index_bytes,
146 measurement.retained_cst_bytes,
147 measurement.source_shared,
148 measurement.cst_shared,
149 measurement.lower_us
150 );
151 }
152 }
153}