|
@@ -2335,6 +2335,36 @@ void MemoryStore::emitEvent(EventType type, const std::string& collection, const
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void MemoryStore::emitPressureHigh(MemoryPressure level) {
|
|
|
|
|
+ nlohmann::json payload = {
|
|
|
|
|
+ {"pressure_level", memoryPressureToString(level)},
|
|
|
|
|
+ {"pressure_percent", pressurePercent()},
|
|
|
|
|
+ {"estimated_bytes", estimatedMemoryBytes_.load(std::memory_order_relaxed)},
|
|
|
|
|
+ {"max_bytes", config_.maxMemoryBytes}
|
|
|
|
|
+ };
|
|
|
|
|
+ // System-level event: empty collection + id. Subscribers receive it
|
|
|
|
|
+ // when subscribed with no collection/pattern filter (matches-all path).
|
|
|
|
|
+ emitEvent(EventType::MEMORY_PRESSURE_HIGH, "", "", payload);
|
|
|
|
|
+ spdlog::warn("Emitted MEMORY_PRESSURE_HIGH: {} at {}% ({} MB / {} MB)",
|
|
|
|
|
+ memoryPressureToString(level),
|
|
|
|
|
+ pressurePercent(),
|
|
|
|
|
+ estimatedMemoryBytes_.load(std::memory_order_relaxed) / (1024 * 1024),
|
|
|
|
|
+ config_.maxMemoryBytes / (1024 * 1024));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void MemoryStore::emitEvictionBurst(uint64_t docs, uint64_t bytesFreed) {
|
|
|
|
|
+ nlohmann::json payload = {
|
|
|
|
|
+ {"evicted_docs", docs},
|
|
|
|
|
+ {"bytes_freed", bytesFreed},
|
|
|
|
|
+ {"pressure_level", memoryPressureToString(pressure())},
|
|
|
|
|
+ {"pressure_percent", pressurePercent()}
|
|
|
|
|
+ };
|
|
|
|
|
+ emitEvent(EventType::MEMORY_EVICTION_BURST, "", "", payload);
|
|
|
|
|
+ spdlog::warn("Emitted MEMORY_EVICTION_BURST: {} docs evicted, {} MB freed (pressure={})",
|
|
|
|
|
+ docs, bytesFreed / (1024 * 1024),
|
|
|
|
|
+ memoryPressureToString(pressure()));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void MemoryStore::emitPersist(const std::string& collection, const std::string& id,
|
|
void MemoryStore::emitPersist(const std::string& collection, const std::string& id,
|
|
|
const std::optional<Document>& doc, EventType eventType) {
|
|
const std::optional<Document>& doc, EventType eventType) {
|
|
|
std::lock_guard<std::mutex> lock(callbackMutex_);
|
|
std::lock_guard<std::mutex> lock(callbackMutex_);
|
|
@@ -2492,6 +2522,24 @@ void MemoryStore::evictionLoop() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
MemoryPressure p = pressure();
|
|
MemoryPressure p = pressure();
|
|
|
|
|
+
|
|
|
|
|
+ // v1.7.0 T10 — edge-triggered MEMORY_PRESSURE_HIGH event.
|
|
|
|
|
+ // Fire when we transition INTO Hard or Emergency from a lower level.
|
|
|
|
|
+ // Reset tracker only when we drop back to Normal/Soft so subscribers
|
|
|
|
|
+ // don't get spammed while we oscillate between Hard and Emergency.
|
|
|
|
|
+ MemoryPressure prevObserved =
|
|
|
|
|
+ lastObservedPressure_.load(std::memory_order_relaxed);
|
|
|
|
|
+ bool crossedIntoHigh =
|
|
|
|
|
+ (p == MemoryPressure::Hard || p == MemoryPressure::Emergency) &&
|
|
|
|
|
+ (prevObserved != MemoryPressure::Hard &&
|
|
|
|
|
+ prevObserved != MemoryPressure::Emergency);
|
|
|
|
|
+ if (crossedIntoHigh) {
|
|
|
|
|
+ emitPressureHigh(p);
|
|
|
|
|
+ }
|
|
|
|
|
+ // Always advance the tracker. "Reset" happens naturally when p drops
|
|
|
|
|
+ // into Normal/Soft, so the next Hard/Emergency climb re-triggers.
|
|
|
|
|
+ lastObservedPressure_.store(p, std::memory_order_relaxed);
|
|
|
|
|
+
|
|
|
if (p == MemoryPressure::Normal) {
|
|
if (p == MemoryPressure::Normal) {
|
|
|
continue; // nothing to do
|
|
continue; // nothing to do
|
|
|
}
|
|
}
|
|
@@ -2689,6 +2737,14 @@ uint64_t MemoryStore::evictOneChunk() {
|
|
|
spdlog::info("Eviction chunk: {} docs evicted, {} bytes freed, pressure={}",
|
|
spdlog::info("Eviction chunk: {} docs evicted, {} bytes freed, pressure={}",
|
|
|
evictedCount, actuallyFreed, memoryPressureToString(pressure()));
|
|
evictedCount, actuallyFreed, memoryPressureToString(pressure()));
|
|
|
|
|
|
|
|
|
|
+ // v1.7.0 T10 — MEMORY_EVICTION_BURST event.
|
|
|
|
|
+ // Large chunks are interesting because they indicate the eviction loop
|
|
|
|
|
+ // is doing heavy work, not trickling. Subscribers (shadowman-cpp metrics
|
|
|
|
|
+ // rollup) can annotate memory graphs with "burst" markers.
|
|
|
|
|
+ if (evictedCount >= config_.evictionBurstThreshold) {
|
|
|
|
|
+ emitEvictionBurst(evictedCount, actuallyFreed);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return actuallyFreed;
|
|
return actuallyFreed;
|
|
|
}
|
|
}
|
|
|
|
|
|