scale_audit/
scale_audit.rs1use std::time::Instant;
19
20use nichlink_run_method::{
21 FrameworkId, NodeId, OwnedAdmission, OwnedFlowContract, OwnedLocalizedText,
22 OwnedObjectContract, OwnedRegistrationRule, OwnedSourceLocation, RegistrationSnapshot,
23 Registry, root_node_id,
24};
25
26fn ceiling(name: &str, default: u128) -> u128 {
30 std::env::var(name)
31 .ok()
32 .and_then(|value| value.parse().ok())
33 .unwrap_or(default)
34}
35
36fn snapshot(namespace: &str, index: usize, parent: NodeId) -> RegistrationSnapshot {
37 let kind = format!("Face{index}");
38 RegistrationSnapshot {
39 namespace: namespace.to_owned(),
40 id: NodeId::from_namespaced_path(namespace, &format!("scale/{index}.rs"), &kind),
41 parent,
42 kind: kind.clone(),
43 preset: "default".to_owned(),
44 parts: String::new(),
45 params: String::new(),
46 handle: kind.clone(),
47 stable_name: None,
48 name: OwnedLocalizedText {
49 zh: kind.clone(),
50 en: kind.clone(),
51 },
52 summary: OwnedLocalizedText {
53 zh: String::new(),
54 en: String::new(),
55 },
56 exports: Vec::new(),
57 needs_registry: false,
58 registry_name: format!("face-{index}"),
59 getting_from_other_registry: None,
60 registry_rule_path: "<scale-audit>".to_owned(),
61 registry_rule: OwnedRegistrationRule {
62 required_preset: None,
63 required_parts: Vec::new(),
64 required_exports: Vec::new(),
65 required_handle_traits: Vec::new(),
66 required_part_traits: Vec::new(),
67 },
68 admission: OwnedAdmission {
69 allowed_paths: Vec::new(),
70 denied_paths: Vec::new(),
71 },
72 requires: Vec::new(),
73 provides: Vec::new(),
74 contract: OwnedObjectContract {
75 required_parts: Vec::new(),
76 provided_parts: Vec::new(),
77 },
78 flow: OwnedFlowContract::none(),
79 flow_provider: None,
80 handle_traits: Vec::new(),
81 part_traits: Vec::new(),
82 runtime_checks: Vec::new(),
83 plugin: None,
84 source: OwnedSourceLocation {
85 file: format!("scale/{index}.rs"),
86 line: 1,
87 column: 1,
88 function: kind,
89 },
90 }
91}
92
93fn main() {
94 let sizes = std::env::args()
95 .skip(1)
96 .map(|value| value.parse::<usize>().expect("size must be an integer"))
97 .collect::<Vec<_>>();
98 let sizes = if sizes.is_empty() {
99 vec![10_000, 100_000]
100 } else {
101 sizes
102 };
103 println!(
104 "nodes\tregister_ms\tregister_budget_ms\tindex_ms\tindex_budget_ms\tentries\tpages\tstatic_face_bytes"
105 );
106 let register_ceiling = ceiling("NICHLINK_SCALE_REGISTER_US", 40);
110 let index_ceiling = ceiling("NICHLINK_SCALE_INDEX_US", 20);
111 for size in sizes {
112 let namespace = format!("scale-{size}");
113 let root = Registry::root_for_namespace(FrameworkId::new("nichlink.scale"), &namespace);
114 let parent = root_node_id(&namespace);
115 let submissions = (0..size)
116 .map(|index| snapshot(&namespace, index, parent))
117 .collect::<Vec<_>>();
118 let mut registry = root;
119 let register_start = Instant::now();
120 registry
121 .register_snapshot_batch(submissions)
122 .expect("generated scale batch must register");
123 let register_ms = register_start.elapsed().as_millis();
124 let index_start = Instant::now();
125 let index = registry.index();
126 let index_ms = index_start.elapsed().as_millis();
127 let stats = registry.storage_stats();
128 let register_budget_ms = register_ceiling * size as u128 / 1000;
129 let index_budget_ms = index_ceiling * size as u128 / 1000;
130 println!(
131 "{size}\t{register_ms}\t{register_budget_ms}\t{index_ms}\t{index_budget_ms}\t{}\t{}\t{}",
132 index.len(),
133 stats.pages,
134 size * std::mem::size_of::<nichlink::StaticFace>()
135 );
136 assert!(
137 register_ms <= register_budget_ms,
138 "registering {size} nodes took {register_ms} ms, over the {register_budget_ms} ms budget ({register_ceiling} µs per node); raise NICHLINK_SCALE_REGISTER_US if this machine is simply slower, and update docs/performance-baseline.md if the baseline moved"
139 );
140 assert!(
141 index_ms <= index_budget_ms,
142 "indexing {size} nodes took {index_ms} ms, over the {index_budget_ms} ms budget ({index_ceiling} µs per node); raise NICHLINK_SCALE_INDEX_US if this machine is simply slower, and update docs/performance-baseline.md if the baseline moved"
143 );
144 let extra = snapshot(&namespace, size, parent);
145 registry
146 .register_snapshot_batch([extra])
147 .expect("incremental transaction must register");
148 assert_eq!(registry.index().len(), size + 2);
149 }
150}