Skip to content

Commit 046c5ac

Browse files
authored
Limit remote batch size (#724)
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.
1 parent 35c5c60 commit 046c5ac

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ else()
206206
target_compile_definitions(snmalloc INTERFACE SNMALLOC_USE_WAIT_ON_ADDRESS=0)
207207
endif()
208208

209+
if(SNMALLOC_REMOTE_BATCH_PROCESS_SIZE)
210+
target_compile_definitions(snmalloc INTERFACE SNMALLOC_REMOTE_BATCH_PROCESS_SIZE=${SNMALLOC_REMOTE_BATCH_PROCESS_SIZE})
211+
endif()
212+
209213
if(SNMALLOC_USE_SELF_VENDORED_STL)
210214
target_compile_definitions(snmalloc INTERFACE SNMALLOC_USE_SELF_VENDORED_STL=1)
211215
else()

src/snmalloc/ds/allocconfig.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,16 @@ namespace snmalloc
182182
#endif
183183
;
184184
185+
// Stop processing remote batch when we reach this amount of deallocations in
186+
// bytes
187+
static constexpr int64_t REMOTE_BATCH_LIMIT =
188+
#ifdef SNMALLOC_REMOTE_BATCH_PROCESS_SIZE
189+
SNMALLOC_REMOTE_BATCH_PROCESS_SIZE
190+
#else
191+
1 * 1024 * 1024
192+
#endif
193+
;
194+
185195
// Used to configure when the backend should use thread local buddies.
186196
// This only basically is used to disable some buddy allocators on small
187197
// fixed heap scenarios like OpenEnclave.

src/snmalloc/mem/corealloc.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -510,17 +510,18 @@ namespace snmalloc
510510
handle_message_queue_inner(Action action, Args... args)
511511
{
512512
bool need_post = false;
513+
size_t bytes_freed = 0;
513514
auto local_state = backend_state_ptr();
514515
auto domesticate = [local_state](freelist::QueuePtr p)
515516
SNMALLOC_FAST_PATH_LAMBDA {
516517
return capptr_domesticate<Config>(local_state, p);
517518
};
518-
auto cb = [this, domesticate, &need_post](
519+
auto cb = [this, domesticate, &need_post, &bytes_freed](
519520
capptr::Alloc<RemoteMessage> msg) SNMALLOC_FAST_PATH_LAMBDA {
520521
auto& entry =
521522
Config::Backend::get_metaentry(snmalloc::address_cast(msg));
522-
handle_dealloc_remote(entry, msg, need_post, domesticate);
523-
return true;
523+
handle_dealloc_remote(entry, msg, need_post, domesticate, bytes_freed);
524+
return bytes_freed < REMOTE_BATCH_LIMIT;
524525
};
525526

526527
#ifdef SNMALLOC_TRACING
@@ -563,7 +564,8 @@ namespace snmalloc
563564
const PagemapEntry& entry,
564565
capptr::Alloc<RemoteMessage> msg,
565566
bool& need_post,
566-
Domesticator_queue domesticate)
567+
Domesticator_queue domesticate,
568+
size_t& bytes_returned)
567569
{
568570
// TODO this needs to not double count stats
569571
// TODO this needs to not double revoke if using MTE
@@ -573,8 +575,8 @@ namespace snmalloc
573575
{
574576
auto meta = entry.get_slab_metadata();
575577

576-
auto unreturned =
577-
dealloc_local_objects_fast(msg, entry, meta, entropy, domesticate);
578+
auto unreturned = dealloc_local_objects_fast(
579+
msg, entry, meta, entropy, domesticate, bytes_returned);
578580

579581
/*
580582
* dealloc_local_objects_fast has updated the free list but not updated
@@ -777,7 +779,8 @@ namespace snmalloc
777779
const PagemapEntry& entry,
778780
BackendSlabMetadata* meta,
779781
LocalEntropy& entropy,
780-
Domesticator domesticate)
782+
Domesticator domesticate,
783+
size_t& bytes_freed)
781784
{
782785
SNMALLOC_ASSERT(!meta->is_unused());
783786

@@ -795,6 +798,8 @@ namespace snmalloc
795798
meta->as_key_tweak(),
796799
domesticate);
797800

801+
bytes_freed = objsize * length;
802+
798803
// Update the head and the next pointer in the free list.
799804
meta->free_queue.append_segment(
800805
curr,
@@ -940,14 +945,18 @@ namespace snmalloc
940945
return capptr_domesticate<Config>(local_state, p);
941946
};
942947

948+
size_t bytes_flushed = 0; // Not currently used.
949+
943950
if (destroy_queue)
944951
{
945-
auto cb = [this, domesticate](capptr::Alloc<RemoteMessage> m) {
946-
bool need_post = true; // Always going to post, so ignore.
947-
const PagemapEntry& entry =
948-
Config::Backend::get_metaentry(snmalloc::address_cast(m));
949-
handle_dealloc_remote(entry, m, need_post, domesticate);
950-
};
952+
auto cb =
953+
[this, domesticate, &bytes_flushed](capptr::Alloc<RemoteMessage> m) {
954+
bool need_post = true; // Always going to post, so ignore.
955+
const PagemapEntry& entry =
956+
Config::Backend::get_metaentry(snmalloc::address_cast(m));
957+
handle_dealloc_remote(
958+
entry, m, need_post, domesticate, bytes_flushed);
959+
};
951960

952961
message_queue().destroy_and_iterate(domesticate, cb);
953962
}

0 commit comments

Comments
 (0)