LCOV - code coverage report
Current view: top level - pageserver/src/tenant/timeline - analysis.rs (source / functions) Coverage Total Hit
Test: 465a86b0c1fda0069b3e0f6c1c126e6b635a1f72.info Lines: 0.0 % 66 0
Test Date: 2024-06-25 15:47:26 Functions: 0.0 % 8 0

            Line data    Source code
       1              : use std::{collections::BTreeSet, ops::Range};
       2              : 
       3              : use utils::lsn::Lsn;
       4              : 
       5              : use super::Timeline;
       6              : 
       7              : #[derive(serde::Serialize)]
       8              : pub(crate) struct RangeAnalysis {
       9              :     start: String,
      10              :     end: String,
      11              :     has_image: bool,
      12              :     num_of_deltas_above_image: usize,
      13              :     total_num_of_deltas: usize,
      14              : }
      15              : 
      16              : impl Timeline {
      17            0 :     pub(crate) async fn perf_info(&self) -> Vec<RangeAnalysis> {
      18            0 :         // First, collect all split points of the layers.
      19            0 :         let mut split_points = BTreeSet::new();
      20            0 :         let mut delta_ranges = Vec::new();
      21            0 :         let mut image_ranges = Vec::new();
      22              : 
      23            0 :         let all_layer_files = {
      24            0 :             let guard = self.layers.read().await;
      25            0 :             guard.all_persistent_layers()
      26            0 :         };
      27            0 :         let lsn = self.get_last_record_lsn();
      28              : 
      29            0 :         for key in all_layer_files {
      30            0 :             split_points.insert(key.key_range.start);
      31            0 :             split_points.insert(key.key_range.end);
      32            0 :             if key.is_delta {
      33            0 :                 delta_ranges.push((key.key_range.clone(), key.lsn_range.clone()));
      34            0 :             } else {
      35            0 :                 image_ranges.push((key.key_range.clone(), key.lsn_range.start));
      36            0 :             }
      37              :         }
      38              : 
      39              :         // For each split range, compute the estimated read amplification.
      40            0 :         let split_points = split_points.into_iter().collect::<Vec<_>>();
      41            0 : 
      42            0 :         let mut result = Vec::new();
      43              : 
      44            0 :         for i in 0..(split_points.len() - 1) {
      45            0 :             let start = split_points[i];
      46            0 :             let end = split_points[i + 1];
      47            0 :             // Find the latest image layer that contains the information.
      48            0 :             let mut maybe_image_layers = image_ranges
      49            0 :                 .iter()
      50            0 :                 // We insert split points for all image layers, and therefore a `contains` check for the start point should be enough.
      51            0 :                 .filter(|(key_range, img_lsn)| key_range.contains(&start) && img_lsn <= &lsn)
      52            0 :                 .cloned()
      53            0 :                 .collect::<Vec<_>>();
      54            0 :             maybe_image_layers.sort_by(|a, b| a.1.cmp(&b.1));
      55            0 :             let image_layer = maybe_image_layers.last().cloned();
      56            0 :             let lsn_filter_start = image_layer
      57            0 :                 .as_ref()
      58            0 :                 .map(|(_, lsn)| *lsn)
      59            0 :                 .unwrap_or(Lsn::INVALID);
      60            0 : 
      61            0 :             fn overlaps_with(lsn_range_a: &Range<Lsn>, lsn_range_b: &Range<Lsn>) -> bool {
      62            0 :                 !(lsn_range_a.end <= lsn_range_b.start || lsn_range_a.start >= lsn_range_b.end)
      63            0 :             }
      64            0 : 
      65            0 :             let maybe_delta_layers = delta_ranges
      66            0 :                 .iter()
      67            0 :                 .filter(|(key_range, lsn_range)| {
      68            0 :                     key_range.contains(&start) && overlaps_with(&(lsn_filter_start..lsn), lsn_range)
      69            0 :                 })
      70            0 :                 .cloned()
      71            0 :                 .collect::<Vec<_>>();
      72            0 : 
      73            0 :             let pitr_delta_layers = delta_ranges
      74            0 :                 .iter()
      75            0 :                 .filter(|(key_range, _)| key_range.contains(&start))
      76            0 :                 .cloned()
      77            0 :                 .collect::<Vec<_>>();
      78            0 : 
      79            0 :             result.push(RangeAnalysis {
      80            0 :                 start: start.to_string(),
      81            0 :                 end: end.to_string(),
      82            0 :                 has_image: image_layer.is_some(),
      83            0 :                 num_of_deltas_above_image: maybe_delta_layers.len(),
      84            0 :                 total_num_of_deltas: pitr_delta_layers.len(),
      85            0 :             });
      86            0 :         }
      87              : 
      88            0 :         result
      89            0 :     }
      90              : }
        

Generated by: LCOV version 2.1-beta