返回 CodeWhale
zz_perf_probe.rs
根目录 / crates / tui / examples / zz_perf_probe.rs
1 #[path = "../src/session_tree.rs"]
2 #[allow(dead_code)] // The probe intentionally exercises only the journal hot paths.
3 mod session_tree;
4
5 use codewhale_models::Message;
6 use serde::{Deserialize, Serialize};
7 use session_tree::SessionJournal;
8 use std::io::Write;
9 use std::time::Instant;
10
11 #[derive(Debug, Clone, Serialize, Deserialize)]
12 struct Probe {
13 #[serde(default)]
14 schema_version: u32,
15 metadata: serde_json::Value,
16 messages: Vec<Message>,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
18 journal: Option<SessionJournal>,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 leaf_id: Option<String>,
21 #[serde(default)]
22 system_prompt: Option<String>,
23 #[serde(flatten)]
24 rest: serde_json::Map<String, serde_json::Value>,
25 }
26
27 fn main() {
28 let path = std::env::args().nth(1).expect("path");
29 let raw = std::fs::read_to_string(&path).unwrap();
30 println!("file bytes: {}", raw.len());
31
32 let t = Instant::now();
33 let s: Probe = serde_json::from_str(&raw).unwrap();
34 println!("typed parse: {:?}", t.elapsed());
35 println!(
36 "messages: {} journal entries: {}",
37 s.messages.len(),
38 s.journal.as_ref().map(|j| j.entries.len()).unwrap_or(0)
39 );
40
41 for _ in 0..3 {
42 let t = Instant::now();
43 let out = serde_json::to_string_pretty(&s).unwrap();
44 println!(
45 "to_string_pretty FULL: {:?} ({} bytes)",
46 t.elapsed(),
47 out.len()
48 );
49 }
50 let mut dedup = s.clone();
51 dedup.messages = Vec::new();
52 for _ in 0..3 {
53 let t = Instant::now();
54 let out = serde_json::to_string_pretty(&dedup).unwrap();
55 println!(
56 "to_string_pretty JOURNAL-ONLY: {:?} ({} bytes)",
57 t.elapsed(),
58 out.len()
59 );
60 }
61 for _ in 0..3 {
62 let t = Instant::now();
63 let c = s.clone();
64 println!(
65 "Probe::clone (== SavedSession::clone): {:?} ({} msgs)",
66 t.elapsed(),
67 c.messages.len()
68 );
69 }
70 let j = s.journal.as_ref().unwrap();
71 for _ in 0..3 {
72 let t = Instant::now();
73 let m = j.to_messages();
74 println!(
75 "journal.to_messages (deep clone): {:?} ({} msgs)",
76 t.elapsed(),
77 m.len()
78 );
79 }
80 for _ in 0..3 {
81 let t = Instant::now();
82 let jj = SessionJournal::from_messages(s.messages.clone(), 0);
83 println!(
84 "from_messages(messages.to_vec()) [UI-thread snapshot build]: {:?} ({} entries)",
85 t.elapsed(),
86 jj.entries.len()
87 );
88 }
89 for _ in 0..3 {
90 let t = Instant::now();
91 let eq = s.messages == j.to_messages();
92 println!(
93 "storage_compatible_copy compare: {:?} (eq={})",
94 t.elapsed(),
95 eq
96 );
97 }
98 let content = serde_json::to_string_pretty(&s).unwrap();
99 let dir = std::env::temp_dir();
100 for _ in 0..3 {
101 let t = Instant::now();
102 let mut f = tempfile::NamedTempFile::new_in(&dir).unwrap();
103 f.write_all(content.as_bytes()).unwrap();
104 f.as_file().sync_all().unwrap();
105 let p = dir.join("zz_perf_probe_out.json");
106 f.persist(&p).unwrap();
107 println!(
108 "atomic write+fsync {} bytes: {:?}",
109 content.len(),
110 t.elapsed()
111 );
112 }
113 let dc = serde_json::to_string_pretty(&dedup).unwrap();
114 for _ in 0..3 {
115 let t = Instant::now();
116 let mut f = tempfile::NamedTempFile::new_in(&dir).unwrap();
117 f.write_all(dc.as_bytes()).unwrap();
118 f.as_file().sync_all().unwrap();
119 let p = dir.join("zz_perf_probe_out2.json");
120 f.persist(&p).unwrap();
121 println!(
122 "atomic write+fsync DEDUP {} bytes: {:?}",
123 dc.len(),
124 t.elapsed()
125 );
126 }
127 }
128
128 lines RUST