diff --git a/Cargo.lock b/Cargo.lock index a258fab5f6..ad77b2bdfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1870,6 +1870,7 @@ dependencies = [ "serde_json", "serde_with", "signal-hook", + "svg_fmt", "tar", "tempfile", "thiserror", @@ -3058,6 +3059,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "svg_fmt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" + [[package]] name = "symbolic-common" version = "8.8.0" diff --git a/pageserver/Cargo.toml b/pageserver/Cargo.toml index 11d2d94906..aa7ed507dd 100644 --- a/pageserver/Cargo.toml +++ b/pageserver/Cargo.toml @@ -63,6 +63,7 @@ remote_storage = { path = "../libs/remote_storage" } workspace_hack = { version = "0.1", path = "../workspace_hack" } close_fds = "0.3.2" walkdir = "2.3.2" +svg_fmt = "0.4.1" [dev-dependencies] hex-literal = "0.3" diff --git a/pageserver/src/bin/draw_trace.rs b/pageserver/src/bin/draw_trace.rs index 3ea5b27a90..0e0453a4a3 100644 --- a/pageserver/src/bin/draw_trace.rs +++ b/pageserver/src/bin/draw_trace.rs @@ -1,13 +1,16 @@ use clap::{App, Arg}; -use pageserver::page_service::PagestreamFeMessage; +use pageserver::{page_service::PagestreamFeMessage, repository::Key}; +use std::io::Write; use std::{ fs::{read_dir, File}, io::BufReader, path::PathBuf, str::FromStr, }; +use svg_fmt::*; use utils::{ id::{TenantId, TimelineId}, + lsn::Lsn, pq_proto::{BeMessage, FeMessage}, }; @@ -22,31 +25,96 @@ fn main() -> anyhow::Result<()> { ) .get_matches(); + // (blkno, lsn) + let mut dots = Vec::<(u32, Lsn)>::new(); + + println!("scanning trace ..."); let traces_dir = PathBuf::from(arg_matches.value_of("traces_dir").unwrap()); for tenant_dir in read_dir(traces_dir)? { let entry = tenant_dir?; let path = entry.path(); - let _tenant_id = TenantId::from_str(path.file_name().unwrap().to_str().unwrap())?; + // let tenant_id = TenantId::from_str(path.file_name().unwrap().to_str().unwrap())?; + // println!("tenant: {tenant_id}"); + println!("opening {path:?}"); for timeline_dir in read_dir(path)? { let entry = timeline_dir?; let path = entry.path(); - let _timeline_id = TimelineId::from_str(path.file_name().unwrap().to_str().unwrap())?; + // let timeline_id = TimelineId::from_str(path.file_name().unwrap().to_str().unwrap())?; + // println!("hi"); + // println!("timeline: {timeline_id}"); + println!("opening {path:?}"); for trace_dir in read_dir(path)? { let entry = trace_dir?; let path = entry.path(); - let _conn_id = TimelineId::from_str(path.file_name().unwrap().to_str().unwrap())?; + // let _conn_id = TimelineId::from_str(path.file_name().unwrap().to_str().unwrap())?; + println!("opening {path:?}"); let file = File::open(path.clone())?; let mut reader = BufReader::new(file); while let Ok(msg) = PagestreamFeMessage::parse(&mut reader) { - println!("Parsed message {:?}", msg); - // TODO add to svg + // println!("Parsed message {:?}", msg); + match msg { + PagestreamFeMessage::Exists(_) => {} + PagestreamFeMessage::Nblocks(_) => {} + PagestreamFeMessage::GetPage(req) => dots.push((req.blkno, req.lsn)), + PagestreamFeMessage::DbSize(_) => {} + }; + + // HACK + if dots.len() > 100 { + break; + } } } } } + // Analyze + let blkno_max = (&dots).into_iter().map(|(blkno, _)| blkno).max().unwrap(); + let blkno_min = (&dots).into_iter().map(|(blkno, _)| blkno).min().unwrap(); + let lsn_max = (&dots).into_iter().map(|(_, lsn)| lsn).max().unwrap(); + let lsn_min = (&dots).into_iter().map(|(_, lsn)| lsn).min().unwrap(); + + // Draw + println!("drawing trace ..."); + let mut svg_file = File::create("out.svg").expect("can't make file"); + writeln!( + &mut svg_file, + "{}", + BeginSvg { + w: (blkno_max - blkno_min + 1) as f32, + h: (lsn_max.0 - lsn_min.0 + 1) as f32, + } + )?; + for dot in &dots { + writeln!( + &mut svg_file, + " {}", + rectangle( + (dot.0 - blkno_min) as f32, + (dot.1 .0 - lsn_min.0) as f32, + 1.0, + 1.0 + ) + .fill(Fill::Color(red())) + .stroke(Stroke::Color(black(), 0.0)) + .border_radius(0.5) + )?; + // println!(" {}", + // rectangle(key_start as f32 + stretch * margin, + // stretch * (lsn_max as f32 - 1.0 - (lsn_start as f32 + margin - lsn_offset)), + // key_diff as f32 - stretch * 2.0 * margin, + // stretch * (lsn_diff - 2.0 * margin)) + // // .fill(rgb(200, 200, 200)) + // .fill(fill) + // .stroke(Stroke::Color(rgb(200, 200, 200), 0.1)) + // .border_radius(0.4) + // ); + } + + writeln!(&mut svg_file, "{}", EndSvg)?; + Ok(()) } diff --git a/pageserver/src/page_service.rs b/pageserver/src/page_service.rs index be9dc28ed0..cbb13d3cc4 100644 --- a/pageserver/src/page_service.rs +++ b/pageserver/src/page_service.rs @@ -87,9 +87,9 @@ pub struct PagestreamNblocksRequest { #[derive(Debug)] pub struct PagestreamGetPageRequest { latest: bool, - lsn: Lsn, + pub lsn: Lsn, rel: RelTag, - blkno: u32, + pub blkno: u32, } #[derive(Debug)]