growth_main/
growth_main.rs1use std::collections::BTreeMap;
17use std::io::{self, Read};
18use std::process::ExitCode;
19
20use subms::{SubMsGrowthClass, SubMsGrowthRecipe, grow, growth_to_json};
21use subms_block_cache::BlockCache;
22
23const VALUE_BYTES: usize = 256;
24const ENTRY_BYTES: u64 = (VALUE_BYTES + 8 + 32) as u64;
26
27struct CacheChurn {
28 cache: BlockCache<u64, Vec<u8>>,
29 capacity: usize,
30 rounds: usize,
31 inserts_per_round: usize,
32 value: Vec<u8>,
33 next: u64,
34}
35
36impl SubMsGrowthRecipe for CacheChurn {
37 fn name(&self) -> &str {
38 "subms-block-cache"
39 }
40 fn op_name(&self) -> &str {
41 "put"
42 }
43 fn rounds(&self) -> usize {
44 self.rounds
45 }
46 fn ops_per_round(&self) -> usize {
47 self.inserts_per_round
48 }
49 fn op(&mut self, _round: usize, _i: usize) {
50 self.cache.put(self.next, self.value.clone());
53 self.next += 1;
54 }
55 fn memory_bytes(&mut self) -> u64 {
56 self.cache.len() as u64 * ENTRY_BYTES
57 }
58 fn live_bytes(&mut self) -> u64 {
59 self.cache.len() as u64 * ENTRY_BYTES
62 }
63 fn structures(&mut self) -> Vec<(String, u64)> {
64 vec![("entries".to_string(), self.cache.len() as u64)]
65 }
66 fn expected(&self) -> (SubMsGrowthClass, f64) {
67 (
70 SubMsGrowthClass::Bounded,
71 (self.capacity as u64 * ENTRY_BYTES) as f64 * 1.05,
72 )
73 }
74}
75
76fn parse_usize(map: &BTreeMap<String, String>, key: &str, default: usize) -> usize {
77 map.get(key)
78 .and_then(|v| v.trim().parse().ok())
79 .unwrap_or(default)
80}
81
82fn main() -> ExitCode {
83 let mut raw = String::new();
84 if io::stdin().read_to_string(&mut raw).is_err() {
85 eprintln!("growth_main: failed to read stdin");
86 return ExitCode::FAILURE;
87 }
88 let mut map = BTreeMap::new();
89 for line in raw.lines() {
90 let line = line.trim();
91 if line.is_empty() || line.starts_with('#') {
92 continue;
93 }
94 if let Some((k, v)) = line.split_once('=') {
95 map.insert(k.trim().to_string(), v.trim().to_string());
96 }
97 }
98 let rounds = parse_usize(&map, "rounds", 50);
99 let capacity = parse_usize(&map, "capacity", 1024);
100 let inserts_per_round = parse_usize(&map, "inserts_per_round", 20_000);
101
102 let mut recipe = CacheChurn {
103 cache: BlockCache::with_capacity(capacity),
104 capacity,
105 rounds,
106 inserts_per_round,
107 value: vec![0u8; VALUE_BYTES],
108 next: 0,
109 };
110 let report = grow(&mut recipe, "rust");
111
112 if growth_to_json(&report, &mut io::stdout().lock()).is_err() {
113 eprintln!("growth_main: failed to write json");
114 return ExitCode::FAILURE;
115 }
116 ExitCode::SUCCESS
117}