1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//! The shard tick's free helpers (child module via `#[path]`, the
//! house pattern) — split from `commands.rs` at the 500-LOC ceiling.
//! The seam is real: everything here runs on the 100 ms tick, not on
//! a request path.
use kevy_store::Store;
use crate::KevyCommands;
/// Hand back free pages this shard's allocator holds. Returning pages
/// is the one thing kevy-alloc does that glibc's brk arena cannot, and
/// it does nothing until something asks: an allocator has no tick of its
/// own. Measured with it unwired, the resident ratio was 2.39x against
/// glibc's 2.40x — the design's whole point, absent.
#[inline]
pub(super) fn alloc_reclaim_tick() {
#[cfg(feature = "kevy-alloc")]
kevy_alloc::thread_reclaim();
}
/// Re-apply maxmemory + eviction policy in case `CONFIG SET` has
/// swapped the global since the previous tick. `store.set_max_memory`
/// is idempotent and cheap (compares + assigns two scalars + may
/// recompute soft-limit accounting); paying it every 100 ms is well
/// below the noise floor of any benchmark. The instance bound is
/// divided across shards here exactly as at `on_shard_init` —
/// this re-apply used to hand every shard the WHOLE figure, so
/// the init-time division was overwritten within one tick.
pub(super) fn maxmemory_tick(c: &KevyCommands, store: &mut Store, cfg: &kevy_config::Config) {
let n = c.state().nshards().max(1) as u64;
store.set_max_memory(
cfg.memory.maxmemory / n,
crate::map_eviction_policy(cfg.memory.maxmemory_policy),
);
}
/// The shard tick's tiering upkeep: re-resolve the
/// budget spec — auto/percent re-probe the cgroup/meminfo bound so
/// live limit changes are honored (the maxmemory reapply precedent) —
/// and feed the index/view memory floor into the unified watermark.
/// Gated on tiering being on: an untiered tick pays one branch.
pub(super) fn tier_tick(c: &KevyCommands, store: &mut Store, bits: u32, cfg: &kevy_config::Config) {
if !store.tier_enabled() {
return;
}
if let Ok(Some(total)) = crate::resolve_tier_budget(cfg) {
let n = c.state().nshards().max(1) as u64;
store.set_tier_budget((total / n).max(1));
}
let mut reserved = 0u64;
if bits & crate::state::IDX_NONEMPTY != 0 {
reserved += crate::index_runtime::reserved_bytes(&c.ctx(), store);
}
if bits & crate::state::VIEW_NONEMPTY != 0 {
reserved += crate::view_runtime::reserved_bytes(&c.ctx());
}
store.set_tier_reserved(reserved);
}