PGC wanted size (#19349)
* fix wanted cache size calculation to always have an absolute minimum * add chart for out of memory protection
Costa Tsaousis committed
Jan 8, 2025 at 15:08 UTC
95a3194fabe96fc903fa2c3f24ee14bbe03a4f18
2 files changed
+47
-13
src/daemon/pulse/pulse-daemon-memory.c
+34
-1
@@ -178,6 +178,39 @@ void pulse_daemon_memory_do(bool extended) {
178
179
// ----------------------------------------------------------------------------------------------------------------
180
181
+ OS_SYSTEM_MEMORY sm = os_last_reported_system_memory();
182
+ if (sm.ram_total_bytes) {
183
+ static RRDSET *st_memory_available = NULL;
184
+ static RRDDIM *rd_available = NULL;
185
+
186
+ if (unlikely(!st_memory_available)) {
187
+ st_memory_available = rrdset_create_localhost(
188
+ "netdata",
189
+ "out_of_memory_protection",
190
+ NULL,
191
+ "Memory Usage",
192
+ NULL,
193
+ "Out of Memory Protection",
194
+ "bytes",
195
+ "netdata",
196
+ "pulse",
197
+ 130102,
198
+ localhost->rrd_update_every,
199
+ RRDSET_TYPE_AREA);
200
+
201
+ rd_available = rrddim_add(st_memory_available, "available", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
202
+ }
203
+
204
+ // the sum of all these needs to be above at the total buffers calculation
205
+ rrddim_set_by_pointer(
206
+ st_memory_available, rd_available,
207
+ (collected_number)sm.ram_available_bytes);
208
+
209
+ rrdset_done(st_memory_available);
210
+ }
211
+
212
+ // ----------------------------------------------------------------------------------------------------------------
213
+
214
if(!extended)
215
return;
216
@@ -211,7 +244,7 @@ void pulse_daemon_memory_do(bool extended) {
244
"bytes",
245
"netdata",
246
"pulse",
214
- 130101,
247
+ 130103,
248
localhost->rrd_update_every,
249
RRDSET_TYPE_STACKED);
250
src/database/engine/cache.c
+13
-12
@@ -396,15 +396,10 @@ static inline size_t cache_usage_per1000(PGC *cache, size_t *size_to_evict) {
396
else
397
wanted_cache_size = hot + dirty + index + cache->config.clean_size;
398
399
- // protection against huge queries
400
- // if huge queries are running, or huge amounts need to be saved
401
- // allow the cache to grow more (hot pages in the main cache are also referenced)
402
- if(unlikely(wanted_cache_size < referenced_size + dirty))
403
- wanted_cache_size = referenced_size + dirty;
404
-
405
- // if we don't have enough clean pages, there is no reason to be aggressive or critical
406
- if(wanted_cache_size < (current_cache_size - clean) && current_cache_size > clean)
407
- wanted_cache_size = current_cache_size - clean;
399
+ // calculate the absolute minimum we can go
400
+ const uint64_t min_cache_size1 = (referenced_size > hot ? referenced_size : hot) + dirty + index;
401
+ const uint64_t min_cache_size2 = (current_cache_size > clean) ? current_cache_size - clean : min_cache_size1;
402
+ const uint64_t min_cache_size = MAX(min_cache_size1, min_cache_size2);
403
404
if(cache->config.out_of_memory_protection_bytes) {
405
// out of memory protection
@@ -415,10 +410,12 @@ static inline size_t cache_usage_per1000(PGC *cache, size_t *size_to_evict) {
410
const uint64_t min_available = cache->config.out_of_memory_protection_bytes;
411
if (sm.ram_available_bytes < min_available) {
412
// we must shrink
418
- if(current_cache_size > (min_available - sm.ram_available_bytes))
419
- wanted_cache_size = current_cache_size - (min_available - sm.ram_available_bytes);
413
+ uint64_t must_lose = min_available - sm.ram_available_bytes;
414
+
415
+ if(current_cache_size > must_lose)
416
+ wanted_cache_size = current_cache_size - must_lose;
417
else
421
- wanted_cache_size = hot + dirty;
418
+ wanted_cache_size = min_cache_size;
419
}
420
else if(cache->config.use_all_ram) {
421
// we can grow
@@ -427,6 +424,10 @@ static inline size_t cache_usage_per1000(PGC *cache, size_t *size_to_evict) {
424
}
425
}
426
427
+ // never go below our minimum
428
+ if(unlikely(wanted_cache_size < min_cache_size))
429
+ wanted_cache_size = min_cache_size;
430
+
431
const size_t per1000 = (size_t)(current_cache_size * 1000ULL / wanted_cache_size);
432
__atomic_store_n(&cache->usage.per1000, per1000, __ATOMIC_RELAXED);
433
__atomic_store_n(&cache->stats.wanted_cache_size, wanted_cache_size, __ATOMIC_RELAXED);