LCOV - differential code coverage report
Current view: top level - pageserver/src/tenant/layer_map - layer_coverage.rs (source / functions) Coverage Total Hit CBC
Current: f6946e90941b557c917ac98cd5a7e9506d180f3e.info Lines: 100.0 % 81 81 81
Current Date: 2023-10-19 02:04:12 Functions: 100.0 % 21 21 21
Baseline: c8637f37369098875162f194f92736355783b050.info
Baseline Date: 2023-10-18 20:25:20

           TLA  Line data    Source code
       1                 : use std::ops::Range;
       2                 : 
       3                 : // NOTE the `im` crate has 20x more downloads and also has
       4                 : // persistent/immutable BTree. But it's bugged so rpds is a
       5                 : // better choice <https://github.com/neondatabase/neon/issues/3395>
       6                 : use rpds::RedBlackTreeMapSync;
       7                 : 
       8                 : /// Data structure that can efficiently:
       9                 : /// - find the latest layer by lsn.end at a given key
      10                 : /// - iterate the latest layers in a key range
      11                 : /// - insert layers in non-decreasing lsn.start order
      12                 : ///
      13                 : /// For a detailed explanation and justification of this approach, see:
      14                 : /// <https://neon.tech/blog/persistent-structures-in-neons-wal-indexing>
      15                 : ///
      16                 : /// NOTE The struct is parameterized over Value for easier
      17                 : ///      testing, but in practice it's some sort of layer.
      18                 : pub struct LayerCoverage<Value> {
      19                 :     /// For every change in coverage (as we sweep the key space)
      20                 :     /// we store (lsn.end, value).
      21                 :     ///
      22                 :     /// NOTE We use an immutable/persistent tree so that we can keep historic
      23                 :     ///      versions of this coverage without cloning the whole thing and
      24                 :     ///      incurring quadratic memory cost. See HistoricLayerCoverage.
      25                 :     ///
      26                 :     /// NOTE We use the Sync version of the map because we want Self to
      27                 :     ///      be Sync. Using nonsync might be faster, if we can work with
      28                 :     ///      that.
      29                 :     nodes: RedBlackTreeMapSync<i128, Option<(u64, Value)>>,
      30                 : }
      31                 : 
      32                 : impl<T: Clone> Default for LayerCoverage<T> {
      33 CBC        5086 :     fn default() -> Self {
      34            5086 :         Self::new()
      35            5086 :     }
      36                 : }
      37                 : 
      38                 : impl<Value: Clone> LayerCoverage<Value> {
      39            5086 :     pub fn new() -> Self {
      40            5086 :         Self {
      41            5086 :             nodes: RedBlackTreeMapSync::default(),
      42            5086 :         }
      43            5086 :     }
      44                 : 
      45                 :     /// Helper function to subdivide the key range without changing any values
      46                 :     ///
      47                 :     /// This operation has no semantic effect by itself. It only helps us pin in
      48                 :     /// place the part of the coverage we don't want to change when inserting.
      49                 :     ///
      50                 :     /// As an analogy, think of a polygon. If you add a vertex along one of the
      51                 :     /// segments, the polygon is still the same, but it behaves differently when
      52                 :     /// we move or delete one of the other points.
      53                 :     ///
      54                 :     /// Complexity: O(log N)
      55           71060 :     fn add_node(&mut self, key: i128) {
      56           71060 :         let value = match self.nodes.range(..=key).last() {
      57           13401 :             Some((_, Some(v))) => Some(v.clone()),
      58           56269 :             Some((_, None)) => None,
      59            1390 :             None => None,
      60                 :         };
      61           71060 :         self.nodes.insert_mut(key, value);
      62           71060 :     }
      63                 : 
      64                 :     /// Insert a layer.
      65                 :     ///
      66                 :     /// Complexity: worst case O(N), in practice O(log N). See NOTE in implementation.
      67           35530 :     pub fn insert(&mut self, key: Range<i128>, lsn: Range<u64>, value: Value) {
      68           35530 :         // Add nodes at endpoints
      69           35530 :         //
      70           35530 :         // NOTE The order of lines is important. We add nodes at the start
      71           35530 :         // and end of the key range **before updating any nodes** in order
      72           35530 :         // to pin down the current coverage outside of the relevant key range.
      73           35530 :         // Only the coverage inside the layer's key range should change.
      74           35530 :         self.add_node(key.start);
      75           35530 :         self.add_node(key.end);
      76           35530 : 
      77           35530 :         // Raise the height where necessary
      78           35530 :         //
      79           35530 :         // NOTE This loop is worst case O(N), but amortized O(log N) in the special
      80           35530 :         // case when rectangles have no height. In practice I don't think we'll see
      81           35530 :         // the kind of layer intersections needed to trigger O(N) behavior. The worst
      82           35530 :         // case is N/2 horizontal layers overlapped with N/2 vertical layers in a
      83           35530 :         // grid pattern.
      84           35530 :         let mut to_update = Vec::new();
      85           35530 :         let mut to_remove = Vec::new();
      86           35530 :         let mut prev_covered = false;
      87           50021 :         for (k, node) in self.nodes.range(key) {
      88           50021 :             let needs_cover = match node {
      89           28098 :                 None => true,
      90           21923 :                 Some((h, _)) => h < &lsn.end,
      91                 :             };
      92           50021 :             if needs_cover {
      93           50016 :                 match prev_covered {
      94           14483 :                     true => to_remove.push(*k),
      95           35533 :                     false => to_update.push(*k),
      96                 :                 }
      97               5 :             }
      98           50021 :             prev_covered = needs_cover;
      99                 :         }
     100                 :         // TODO check if the nodes inserted at key.start and key.end are safe
     101                 :         //      to remove. It's fine to keep them but they could be redundant.
     102           71063 :         for k in to_update {
     103           35533 :             self.nodes.insert_mut(k, Some((lsn.end, value.clone())));
     104           35533 :         }
     105           50013 :         for k in to_remove {
     106           14483 :             self.nodes.remove_mut(&k);
     107           14483 :         }
     108           35530 :     }
     109                 : 
     110                 :     /// Get the latest (by lsn.end) layer at a given key
     111                 :     ///
     112                 :     /// Complexity: O(log N)
     113        57286808 :     pub fn query(&self, key: i128) -> Option<Value> {
     114        57286808 :         self.nodes
     115        57286808 :             .range(..=key)
     116        57286808 :             .next_back()?
     117                 :             .1
     118        34844739 :             .as_ref()
     119        34844739 :             .map(|(_, v)| v.clone())
     120        57286808 :     }
     121                 : 
     122                 :     /// Iterate the changes in layer coverage in a given range. You will likely
     123                 :     /// want to start with self.query(key.start), and then follow up with self.range
     124                 :     ///
     125                 :     /// Complexity: O(log N + result_size)
     126         9392536 :     pub fn range(&self, key: Range<i128>) -> impl '_ + Iterator<Item = (i128, Option<Value>)> {
     127         9392536 :         self.nodes
     128         9392536 :             .range(key)
     129         9392536 :             .map(|(k, v)| (*k, v.as_ref().map(|x| x.1.clone())))
     130         9392536 :     }
     131                 : 
     132                 :     /// O(1) clone
     133           80682 :     pub fn clone(&self) -> Self {
     134           80682 :         Self {
     135           80682 :             nodes: self.nodes.clone(),
     136           80682 :         }
     137           80682 :     }
     138                 : }
     139                 : 
     140                 : /// Image and delta coverage at a specific LSN.
     141                 : pub struct LayerCoverageTuple<Value> {
     142                 :     pub image_coverage: LayerCoverage<Value>,
     143                 :     pub delta_coverage: LayerCoverage<Value>,
     144                 : }
     145                 : 
     146                 : impl<T: Clone> Default for LayerCoverageTuple<T> {
     147            2543 :     fn default() -> Self {
     148            2543 :         Self {
     149            2543 :             image_coverage: LayerCoverage::default(),
     150            2543 :             delta_coverage: LayerCoverage::default(),
     151            2543 :         }
     152            2543 :     }
     153                 : }
     154                 : 
     155                 : impl<Value: Clone> LayerCoverageTuple<Value> {
     156           40341 :     pub fn clone(&self) -> Self {
     157           40341 :         Self {
     158           40341 :             image_coverage: self.image_coverage.clone(),
     159           40341 :             delta_coverage: self.delta_coverage.clone(),
     160           40341 :         }
     161           40341 :     }
     162                 : }
        

Generated by: LCOV version 2.1-beta