Skip to content

Commit

Permalink
Limit remote batch size (#724)
Browse files Browse the repository at this point in the history
When processing a remote batch, the system will process every single message that was available at the start of processing.
This can lead to a long pause time if there have been a considerable number of frees to this thread.

This commit introduces a new mechanism to only process messages up to a limit of 1MiB. The limit is configurable using CMake.

Choosing too small a limit can cause freeing to never catch up with the incoming messages.
  • Loading branch information
mjp41 authored Jan 7, 2025
1 parent 35c5c60 commit 046c5ac
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ else()
target_compile_definitions(snmalloc INTERFACE SNMALLOC_USE_WAIT_ON_ADDRESS=0)
endif()

if(SNMALLOC_REMOTE_BATCH_PROCESS_SIZE)
target_compile_definitions(snmalloc INTERFACE SNMALLOC_REMOTE_BATCH_PROCESS_SIZE=${SNMALLOC_REMOTE_BATCH_PROCESS_SIZE})
endif()

if(SNMALLOC_USE_SELF_VENDORED_STL)
target_compile_definitions(snmalloc INTERFACE SNMALLOC_USE_SELF_VENDORED_STL=1)
else()
Expand Down
10 changes: 10 additions & 0 deletions src/snmalloc/ds/allocconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,16 @@ namespace snmalloc
#endif
;
// Stop processing remote batch when we reach this amount of deallocations in
// bytes
static constexpr int64_t REMOTE_BATCH_LIMIT =
#ifdef SNMALLOC_REMOTE_BATCH_PROCESS_SIZE
SNMALLOC_REMOTE_BATCH_PROCESS_SIZE
#else
1 * 1024 * 1024
#endif
;
// Used to configure when the backend should use thread local buddies.
// This only basically is used to disable some buddy allocators on small
// fixed heap scenarios like OpenEnclave.
Expand Down
35 changes: 22 additions & 13 deletions src/snmalloc/mem/corealloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,17 +510,18 @@ namespace snmalloc
handle_message_queue_inner(Action action, Args... args)
{
bool need_post = false;
size_t bytes_freed = 0;
auto local_state = backend_state_ptr();
auto domesticate = [local_state](freelist::QueuePtr p)
SNMALLOC_FAST_PATH_LAMBDA {
return capptr_domesticate<Config>(local_state, p);
};
auto cb = [this, domesticate, &need_post](
auto cb = [this, domesticate, &need_post, &bytes_freed](
capptr::Alloc<RemoteMessage> msg) SNMALLOC_FAST_PATH_LAMBDA {
auto& entry =
Config::Backend::get_metaentry(snmalloc::address_cast(msg));
handle_dealloc_remote(entry, msg, need_post, domesticate);
return true;
handle_dealloc_remote(entry, msg, need_post, domesticate, bytes_freed);
return bytes_freed < REMOTE_BATCH_LIMIT;
};

#ifdef SNMALLOC_TRACING
Expand Down Expand Up @@ -563,7 +564,8 @@ namespace snmalloc
const PagemapEntry& entry,
capptr::Alloc<RemoteMessage> msg,
bool& need_post,
Domesticator_queue domesticate)
Domesticator_queue domesticate,
size_t& bytes_returned)
{
// TODO this needs to not double count stats
// TODO this needs to not double revoke if using MTE
Expand All @@ -573,8 +575,8 @@ namespace snmalloc
{
auto meta = entry.get_slab_metadata();

auto unreturned =
dealloc_local_objects_fast(msg, entry, meta, entropy, domesticate);
auto unreturned = dealloc_local_objects_fast(
msg, entry, meta, entropy, domesticate, bytes_returned);

/*
* dealloc_local_objects_fast has updated the free list but not updated
Expand Down Expand Up @@ -777,7 +779,8 @@ namespace snmalloc
const PagemapEntry& entry,
BackendSlabMetadata* meta,
LocalEntropy& entropy,
Domesticator domesticate)
Domesticator domesticate,
size_t& bytes_freed)
{
SNMALLOC_ASSERT(!meta->is_unused());

Expand All @@ -795,6 +798,8 @@ namespace snmalloc
meta->as_key_tweak(),
domesticate);

bytes_freed = objsize * length;

// Update the head and the next pointer in the free list.
meta->free_queue.append_segment(
curr,
Expand Down Expand Up @@ -940,14 +945,18 @@ namespace snmalloc
return capptr_domesticate<Config>(local_state, p);
};

size_t bytes_flushed = 0; // Not currently used.

if (destroy_queue)
{
auto cb = [this, domesticate](capptr::Alloc<RemoteMessage> m) {
bool need_post = true; // Always going to post, so ignore.
const PagemapEntry& entry =
Config::Backend::get_metaentry(snmalloc::address_cast(m));
handle_dealloc_remote(entry, m, need_post, domesticate);
};
auto cb =
[this, domesticate, &bytes_flushed](capptr::Alloc<RemoteMessage> m) {
bool need_post = true; // Always going to post, so ignore.
const PagemapEntry& entry =
Config::Backend::get_metaentry(snmalloc::address_cast(m));
handle_dealloc_remote(
entry, m, need_post, domesticate, bytes_flushed);
};

message_queue().destroy_and_iterate(domesticate, cb);
}
Expand Down

0 comments on commit 046c5ac

Please sign in to comment.