Files
libopenshot/src/MemoryTrim.cpp
T

82 lines
1.9 KiB
C++

/**
* @file
* @brief Cross-platform helper to encourage returning freed memory to the OS
*
* @ref License
*/
// Copyright (c) 2008-2025 OpenShot Studios, LLC
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "MemoryTrim.h"
#include <atomic>
#include <chrono>
#include <cstdint>
#if defined(__GLIBC__)
#include <malloc.h>
#elif defined(_WIN32)
#include <malloc.h>
#elif defined(__APPLE__)
#include <malloc/malloc.h>
#endif
namespace {
// Limit trim attempts to once per interval to avoid spamming platform calls
constexpr uint64_t kMinTrimIntervalMs = 30000; // 30s debounce
std::atomic<uint64_t> g_last_trim_ms{0};
std::atomic<bool> g_trim_in_progress{false};
uint64_t NowMs() {
using namespace std::chrono;
return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}
} // namespace
namespace openshot {
bool TrimMemoryToOS() noexcept {
const uint64_t now_ms = NowMs();
const uint64_t last_ms = g_last_trim_ms.load(std::memory_order_relaxed);
// Skip if we recently trimmed
if (now_ms - last_ms < kMinTrimIntervalMs)
return false;
// Only one trim attempt runs at a time
bool expected = false;
if (!g_trim_in_progress.compare_exchange_strong(expected, true, std::memory_order_acq_rel))
return false;
bool did_trim = false;
#if defined(__GLIBC__)
// GLIBC exposes malloc_trim to release free arenas back to the OS
malloc_trim(0);
did_trim = true;
#elif defined(_WIN32)
// MinGW/MSYS2 expose _heapmin to compact the CRT heap
_heapmin();
did_trim = true;
#elif defined(__APPLE__)
// macOS uses the malloc zone API to relieve memory pressure
malloc_zone_t* zone = malloc_default_zone();
malloc_zone_pressure_relief(zone, 0);
did_trim = true;
#else
// Platforms without a known trimming API
did_trim = false;
#endif
if (did_trim) {
g_last_trim_ms.store(now_ms, std::memory_order_relaxed);
}
g_trim_in_progress.store(false, std::memory_order_release);
return did_trim;
}
} // namespace openshot