Move malloc_trim invocations to background thread (#14744)

This commit is contained in:
sfan5 2024-06-17 15:59:35 +02:00 committed by GitHub
parent d7f4ce6cff
commit fac9aac821
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 30 additions and 11 deletions

View File

@ -24,18 +24,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock.h"
#include "map.h"
#include "util/directiontables.h"
#include "porting.h"
static class BlockPlaceholder {
public:
MapNode data[MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE];
// Data placeholder used for copying from non-existent blocks
static struct BlockPlaceholder {
MapNode data[MapBlock::nodecount];
BlockPlaceholder()
{
for (std::size_t i = 0; i < MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; i++)
for (std::size_t i = 0; i < MapBlock::nodecount; i++)
data[i] = MapNode(CONTENT_IGNORE);
}
} block_placeholder;
/*
QueuedMeshUpdate
*/
@ -225,12 +227,13 @@ void MeshUpdateWorkerThread::doUpdate()
while ((q = m_queue_in->pop())) {
if (m_generation_interval)
sleep_ms(m_generation_interval);
porting::TriggerMemoryTrim();
ScopeProfiler sp(g_profiler, "Client: Mesh making (sum)");
MapBlockMesh *mesh_new = new MapBlockMesh(m_client, q->data, *m_camera_offset);
MeshUpdateResult r;
r.p = q->p;
r.mesh = mesh_new;

View File

@ -662,6 +662,8 @@ void *EmergeThread::run()
EmergeAction action;
MapBlock *block = nullptr;
porting::TriggerMemoryTrim();
if (!popBlockEmerge(&pos, &bedata)) {
m_queue_event.wait();
continue;

View File

@ -920,22 +920,29 @@ double perf_freq = get_perf_freq();
*
* As a workaround we track freed memory coarsely and call malloc_trim() once a
* certain amount is reached.
*
* Because trimming can take more than 10ms and would cause jitter if done
* uncontrolled we have a separate function, which is called from background threads.
*/
static std::atomic<size_t> memory_freed;
constexpr size_t MEMORY_TRIM_THRESHOLD = 128 * 1024 * 1024;
constexpr size_t MEMORY_TRIM_THRESHOLD = 256 * 1024 * 1024;
void TrackFreedMemory(size_t amount)
{
memory_freed.fetch_add(amount, std::memory_order_relaxed);
}
void TriggerMemoryTrim()
{
constexpr auto MO = std::memory_order_relaxed;
memory_freed.fetch_add(amount, MO);
if (memory_freed.load(MO) >= MEMORY_TRIM_THRESHOLD) {
// Synchronize call
if (memory_freed.exchange(0, MO) < MEMORY_TRIM_THRESHOLD)
return;
// Leave some headroom for future allocations
malloc_trim(1 * 1024 * 1024);
malloc_trim(8 * 1024 * 1024);
}
}

View File

@ -290,15 +290,22 @@ void osSpecificInit();
// This attaches to the parents process console, or creates a new one if it doesnt exist.
void attachOrCreateConsole();
#if HAVE_MALLOC_TRIM
/**
* Call this after freeing bigger blocks of memory. Used on some platforms to
* properly give memory back to the OS.
* @param amount Number of bytes freed
*/
#if HAVE_MALLOC_TRIM
void TrackFreedMemory(size_t amount);
/**
* Call this regularly from background threads. This performs the actual trimming
* and is potentially slow.
*/
void TriggerMemoryTrim();
#else
inline void TrackFreedMemory(size_t amount) { (void)amount; }
static inline void TrackFreedMemory(size_t amount) { (void)amount; }
static inline void TriggerMemoryTrim() { (void)0; }
#endif
#ifdef _WIN32