diff --git a/pageserver/src/bin/draw_layer-trace.rs b/pageserver/src/bin/draw_layer-trace.rs index ac4cf83431..2df7ce1082 100644 --- a/pageserver/src/bin/draw_layer-trace.rs +++ b/pageserver/src/bin/draw_layer-trace.rs @@ -15,15 +15,30 @@ project_git_version!(GIT_VERSION); // Map values to their compressed coordinate - the index the value // would have in a sorted and deduplicated list of all values. -fn build_coordinate_compression_map(coords: Vec) -> BTreeMap { - let set: BTreeSet = coords.into_iter().collect(); +struct CoordinateMap { + map: BTreeMap, + stretch: f32 +} - let mut map: BTreeMap = BTreeMap::new(); - for (i, e) in set.iter().enumerate() { - map.insert(*e, i); +impl CoordinateMap { + fn new(coords: Vec, stretch: f32) -> Self { + let set: BTreeSet = coords.into_iter().collect(); + + let mut map: BTreeMap = BTreeMap::new(); + for (i, e) in set.iter().enumerate() { + map.insert(*e, i); + } + + Self { map, stretch } } - map + fn map(&self, val: T) -> f32 { + *self.map.get(&val).unwrap() as f32 * self.stretch + } + + fn max(&self) -> f32 { + self.map.len() as f32 * self.stretch + } } fn parse_filename(name: &str) -> (Range, Range) { @@ -166,8 +181,9 @@ fn main() -> Result<()> { } // Analyze - let key_map = build_coordinate_compression_map(keys); - let lsn_map = build_coordinate_compression_map(lsns); + let key_map = CoordinateMap::new(keys, 2.0); + // Stretch out vertically for better visibility + let lsn_map = CoordinateMap::new(lsns, 3.0); // Initialize stats let mut num_deltas = 0; @@ -176,15 +192,14 @@ fn main() -> Result<()> { let mut svg = String::new(); // Draw - let stretch = 3.0; // Stretch out vertically for better visibility writeln!(svg, "{}", BeginSvg { - w: key_map.len() as f32, - h: stretch * lsn_map.len() as f32 + w: key_map.max(), + h: lsn_map.max(), } )?; - let lsn_max = lsn_map.len(); + let lsn_max = lsn_map.max(); // Sort the files by LSN, but so that image layers go after all delta layers // The SVG is painted in the order the elements appear, and we want to draw @@ -201,16 +216,16 @@ fn main() -> Result<()> { }); for f in files_sorted { - let key_start = *key_map.get(&f.key_range.start).unwrap(); - let key_end = *key_map.get(&f.key_range.end).unwrap(); + let key_start = key_map.map(f.key_range.start); + let key_end = key_map.map(f.key_range.end); let key_diff = key_end - key_start; if key_start >= key_end { panic!("Invalid key range {}-{}", key_start, key_end); } - let lsn_start = *lsn_map.get(&f.lsn_range.start).unwrap(); - let lsn_end = *lsn_map.get(&f.lsn_range.end).unwrap(); + let lsn_start = lsn_map.map(f.lsn_range.start); + let lsn_end = lsn_map.map(f.lsn_range.end); // Fill in and thicken rectangle if it's an // image layer so that we can see it. @@ -218,13 +233,13 @@ fn main() -> Result<()> { style.fill = Fill::Color(rgb(0x80, 0x80, 0x80)); style.stroke = Stroke::Color(rgb(0, 0, 0), 0.5); - let y_start = stretch * (lsn_max - lsn_start) as f32; - let y_end = stretch * (lsn_max - lsn_end) as f32; + let y_start = (lsn_max - lsn_start) as f32; + let y_end = (lsn_max - lsn_end) as f32; let x_margin = 0.25; let y_margin = 0.5; - match lsn_start.cmp(&lsn_end) { + match f.lsn_range.start.cmp(&f.lsn_range.end) { Ordering::Less => { num_deltas += 1; write!(svg, @@ -264,19 +279,19 @@ fn main() -> Result<()> { } for (idx, gc) in gc_events.iter().enumerate() { - let cutoff_lsn = *lsn_map.get(&gc.cutoff).unwrap(); + let cutoff_lsn = lsn_map.map(gc.cutoff); let mut style = Style::default(); style.fill = Fill::None; style.stroke = Stroke::Color(rgb(0xff, 0, 0), 0.5); - let y = stretch * (lsn_max as f32 - (cutoff_lsn as f32)); + let y = lsn_max - cutoff_lsn; writeln!(svg, r#" "#, idx, 0, y, - key_map.len() as f32, + key_map.max(), y, style.to_string(), )?; @@ -345,12 +360,44 @@ fn main() -> Result<()> { - +