diff options
author | David Goldblatt <davidgoldblatt@fb.com> | 2021-01-04 18:40:27 -0800 |
---|---|---|
committer | David Goldblatt <davidtgoldblatt@gmail.com> | 2021-02-19 15:10:54 -0800 |
commit | f47b4c2cd8ed3e843b987ee972d187df45391b69 (patch) | |
tree | 6fb329e44a262e7619da346b83d5a5c76a98d7da | |
parent | 4b8870c7dbfaeea7136a8e0b9f93a2ad85d31a55 (diff) | |
download | jemalloc-f47b4c2cd8ed3e843b987ee972d187df45391b69.tar.gz |
PAI/SEC: Add a dalloc_batch function.
This lets the SEC flush all of its items in a single call, rather than flushing
everything at once.
-rw-r--r-- | Makefile.in | 1 | ||||
-rw-r--r-- | include/jemalloc/internal/pai.h | 14 | ||||
-rw-r--r-- | msvc/projects/vc2015/jemalloc/jemalloc.vcxproj | 1 | ||||
-rw-r--r-- | msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters | 3 | ||||
-rw-r--r-- | msvc/projects/vc2017/jemalloc/jemalloc.vcxproj | 1 | ||||
-rw-r--r-- | msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters | 3 | ||||
-rw-r--r-- | src/hpa.c | 1 | ||||
-rw-r--r-- | src/pac.c | 1 | ||||
-rw-r--r-- | src/pai.c | 13 | ||||
-rw-r--r-- | src/sec.c | 8 | ||||
-rw-r--r-- | test/unit/sec.c | 34 |
11 files changed, 69 insertions, 11 deletions
diff --git a/Makefile.in b/Makefile.in index 40c41442..11a553b0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -132,6 +132,7 @@ C_SRCS := $(srcroot)src/jemalloc.c \ $(srcroot)src/nstime.c \ $(srcroot)src/pa.c \ $(srcroot)src/pa_extra.c \ + $(srcroot)src/pai.c \ $(srcroot)src/pac.c \ $(srcroot)src/pages.c \ $(srcroot)src/peak_event.c \ diff --git a/include/jemalloc/internal/pai.h b/include/jemalloc/internal/pai.h index 45edd69c..f7f3e077 100644 --- a/include/jemalloc/internal/pai.h +++ b/include/jemalloc/internal/pai.h @@ -13,6 +13,8 @@ struct pai_s { bool (*shrink)(tsdn_t *tsdn, pai_t *self, edata_t *edata, size_t old_size, size_t new_size); void (*dalloc)(tsdn_t *tsdn, pai_t *self, edata_t *edata); + void (*dalloc_batch)(tsdn_t *tsdn, pai_t *self, + edata_list_active_t *list); }; /* @@ -42,4 +44,16 @@ pai_dalloc(tsdn_t *tsdn, pai_t *self, edata_t *edata) { self->dalloc(tsdn, self, edata); } +static inline void +pai_dalloc_batch(tsdn_t *tsdn, pai_t *self, edata_list_active_t *list) { + return self->dalloc_batch(tsdn, self, list); +} + +/* + * An implementation of batch deallocation that simply calls dalloc once for + * each item in the list. + */ +void pai_dalloc_batch_default(tsdn_t *tsdn, pai_t *self, + edata_list_active_t *list); + #endif /* JEMALLOC_INTERNAL_PAI_H */ diff --git a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj index a93511d1..9ec953a2 100644 --- a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj +++ b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj @@ -73,6 +73,7 @@ <ClCompile Include="..\..\..\..\src\nstime.c" /> <ClCompile Include="..\..\..\..\src\pa.c" /> <ClCompile Include="..\..\..\..\src\pa_extra.c" /> + <ClCompile Include="..\..\..\..\src\pai.c" /> <ClCompile Include="..\..\..\..\src\pac.c" /> <ClCompile Include="..\..\..\..\src\pages.c" /> <ClCompile Include="..\..\..\..\src\peak_event.c" /> diff --git a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters index 06460e5a..210204a5 100644 --- a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters +++ b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters @@ -103,6 +103,9 @@ <ClCompile Include="..\..\..\..\src\pa_extra.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\..\src\pai.c"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="..\..\..\..\src\pac.c"> <Filter>Source Files</Filter> </ClCompile> diff --git a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj index 916460a7..171b95f2 100644 --- a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj +++ b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj @@ -73,6 +73,7 @@ <ClCompile Include="..\..\..\..\src\nstime.c" /> <ClCompile Include="..\..\..\..\src\pa.c" /> <ClCompile Include="..\..\..\..\src\pa_extra.c" /> + <ClCompile Include="..\..\..\..\src\pai.c" /> <ClCompile Include="..\..\..\..\src\pac.c" /> <ClCompile Include="..\..\..\..\src\pages.c" /> <ClCompile Include="..\..\..\..\src\peak_event.c" /> diff --git a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters index 06460e5a..210204a5 100644 --- a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters +++ b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters @@ -103,6 +103,9 @@ <ClCompile Include="..\..\..\..\src\pa_extra.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\..\src\pai.c"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="..\..\..\..\src\pac.c"> <Filter>Source Files</Filter> </ClCompile> @@ -91,6 +91,7 @@ hpa_shard_init(hpa_shard_t *shard, emap_t *emap, base_t *base, shard->pai.expand = &hpa_expand; shard->pai.shrink = &hpa_shrink; shard->pai.dalloc = &hpa_dalloc; + shard->pai.dalloc_batch = &pai_dalloc_batch_default; return false; } @@ -94,6 +94,7 @@ pac_init(tsdn_t *tsdn, pac_t *pac, base_t *base, emap_t *emap, pac->pai.expand = &pac_expand_impl; pac->pai.shrink = &pac_shrink_impl; pac->pai.dalloc = &pac_dalloc_impl; + pac->pai.dalloc_batch = &pai_dalloc_batch_default; return false; } diff --git a/src/pai.c b/src/pai.c new file mode 100644 index 00000000..1035c850 --- /dev/null +++ b/src/pai.c @@ -0,0 +1,13 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + + +void +pai_dalloc_batch_default(tsdn_t *tsdn, pai_t *self, + edata_list_active_t *list) { + edata_t *edata; + while ((edata = edata_list_active_first(list)) != NULL) { + edata_list_active_remove(list, edata); + pai_dalloc(tsdn, self, edata); + } +} @@ -46,6 +46,7 @@ bool sec_init(sec_t *sec, pai_t *fallback, size_t nshards, size_t alloc_max, sec->pai.expand = &sec_expand; sec->pai.shrink = &sec_shrink; sec->pai.dalloc = &sec_dalloc; + sec->pai.dalloc_batch = &pai_dalloc_batch_default; return false; } @@ -142,6 +143,7 @@ sec_do_flush_locked(tsdn_t *tsdn, sec_t *sec, sec_shard_t *shard) { for (pszind_t i = 0; i < SEC_NPSIZES; i++) { edata_list_active_concat(&to_flush, &shard->freelist[i]); } + /* * A better way to do this would be to add a batch dalloc function to * the pai_t. Practically, the current method turns into O(n) locks and @@ -149,11 +151,7 @@ sec_do_flush_locked(tsdn_t *tsdn, sec_t *sec, sec_shard_t *shard) { * HPA) can straightforwardly do many deallocations in a single lock / * unlock pair. */ - while (!edata_list_active_empty(&to_flush)) { - edata_t *e = edata_list_active_first(&to_flush); - edata_list_active_remove(&to_flush, e); - pai_dalloc(tsdn, sec->fallback, e); - } + pai_dalloc_batch(tsdn, sec->fallback, &to_flush); } static void diff --git a/test/unit/sec.c b/test/unit/sec.c index cb0c17d1..7657537b 100644 --- a/test/unit/sec.c +++ b/test/unit/sec.c @@ -8,6 +8,7 @@ struct pai_test_allocator_s { bool alloc_fail; size_t alloc_count; size_t dalloc_count; + size_t dalloc_batch_count; /* * We use a simple bump allocator as the implementation. This isn't * *really* correct, since we may allow expansion into a subsequent @@ -64,11 +65,25 @@ pai_test_allocator_dalloc(tsdn_t *tsdn, pai_t *self, edata_t *edata) { free(edata); } +static void +pai_test_allocator_dalloc_batch(tsdn_t *tsdn, pai_t *self, + edata_list_active_t *list) { + pai_test_allocator_t *ta = (pai_test_allocator_t *)self; + + edata_t *edata; + while ((edata = edata_list_active_first(list)) != NULL) { + edata_list_active_remove(list, edata); + ta->dalloc_batch_count++; + free(edata); + } +} + static inline void pai_test_allocator_init(pai_test_allocator_t *ta) { ta->alloc_fail = false; ta->alloc_count = 0; ta->dalloc_count = 0; + ta->dalloc_batch_count = 0; /* Just don't start the edata at 0. */ ta->next_ptr = 10 * PAGE; ta->expand_count = 0; @@ -79,6 +94,7 @@ pai_test_allocator_init(pai_test_allocator_t *ta) { ta->pai.expand = &pai_test_allocator_expand; ta->pai.shrink = &pai_test_allocator_shrink; ta->pai.dalloc = &pai_test_allocator_dalloc; + ta->pai.dalloc_batch = &pai_test_allocator_dalloc_batch; } TEST_BEGIN(test_reuse) { @@ -190,8 +206,10 @@ TEST_BEGIN(test_auto_flush) { pai_dalloc(tsdn, &sec.pai, extra_alloc); expect_zu_eq(NALLOCS + 1, ta.alloc_count, "Incorrect number of allocations"); - expect_zu_eq(NALLOCS + 1, ta.dalloc_count, - "Incorrect number of deallocations"); + expect_zu_eq(0, ta.dalloc_count, + "Incorrect number of (non-batch) deallocations"); + expect_zu_eq(NALLOCS + 1, ta.dalloc_batch_count, + "Incorrect number of batch deallocations"); } TEST_END @@ -233,8 +251,10 @@ do_disable_flush_test(bool is_disable) { expect_zu_eq(NALLOCS, ta.alloc_count, "Incorrect number of allocations"); - expect_zu_eq(NALLOCS - 1, ta.dalloc_count, - "Incorrect number of deallocations"); + expect_zu_eq(0, ta.dalloc_count, + "Incorrect number of (non-batch) deallocations"); + expect_zu_eq(NALLOCS - 1, ta.dalloc_batch_count, + "Incorrect number of batch deallocations"); /* * If we free into a disabled SEC, it should forward to the fallback. @@ -244,8 +264,10 @@ do_disable_flush_test(bool is_disable) { expect_zu_eq(NALLOCS, ta.alloc_count, "Incorrect number of allocations"); - expect_zu_eq(is_disable ? NALLOCS : NALLOCS - 1, ta.dalloc_count, - "Incorrect number of deallocations"); + expect_zu_eq(is_disable ? 1 : 0, ta.dalloc_count, + "Incorrect number of (non-batch) deallocations"); + expect_zu_eq(NALLOCS - 1, ta.dalloc_batch_count, + "Incorrect number of batch deallocations"); } TEST_BEGIN(test_disable) { |