Skip to main content

bound

Function bound 

Source
fn bound(
    out: &mut BTreeMap<String, Series>,
    dropped: &mut BTreeSet<String>,
    max: usize,
)
Expand description

Hold out to max_series entries by evicting its largest key.

The result is the same set sort(keys).truncate(max_series) produced, and the argument is short enough to check: the answer is the max_series smallest keys, and a key that belongs in it can never be the largest key of a map that is already one over — everything else in that map is smaller, so there are already max_series keys ahead of it. Evicting the maximum therefore only ever discards a key the sort would have truncated. It also cannot come back: the evicted key is greater than every key in the map, and the map’s maximum only falls, so the same key arriving from a later block is evicted again on sight.

The difference is when, and that is the whole point. The old map grew one entry per distinct (name, unit, kind, temporality, monotonic, attributes) tuple until the query finished, each carrying a rendered descriptor, a rendered attribute object and a key concatenating both — about a kilobyte. max_points bounded the points inside a series and nothing bounded the series, so a query_metric with no name over a store with a request id in a data-point attribute allocated until the process died.

The evicted key is kept, without its payload, so the response can say how many series it is not showing. ponytail: that record is itself capped at max_series keys, so dropped_series saturates rather than counting an unbounded number of them exactly — remembering every key to count it is the allocation this function exists to prevent. dropped_series == max_series reads as “at least”. Counting evictions instead of distinct keys was the other option and it is worse: a series above the cap is re-inserted and re-evicted once per point, so a store with 100 series and a cap of 64 would report tens of thousands dropped.