On Sunday, November 18, 2018 at 11:37:49 AM UTC-5, Nadav Har'El wrote:
>
> Thanks! This is a very welcome patch :-)
>
> I'm committing your patch because it is correct, but I have a comment
> below maybe it could have been done slightly differently and cover yet
> another corner case, so please consider my comments below for a followup
> patch - if you agree with my comments.
>
> On Sat, Nov 17, 2018 at 5:49 AM Waldemar Kozaczuk <[email protected]
> <javascript:>> wrote:
>
>> This patch adjusts std_malloc() to handle small
>> allocations (smaller than 16-bytes) more efficiently.
>> More specifically instead of allocating whole page
>> for each such request, adjusted std_malloc() uses memory
>> pool adequate to requested size and thus saves almost
>> entire page (4K) of memory.
>>
>> Fixes #1011
>>
>> Signed-off-by: Waldemar Kozaczuk <[email protected] <javascript:>>
>> ---
>> core/mempool.cc | 5 +++--
>> modules/tests/Makefile | 2 +-
>> tests/tst-small-malloc.cc | 45 +++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 49 insertions(+), 3 deletions(-)
>> create mode 100644 tests/tst-small-malloc.cc
>>
>> diff --git a/core/mempool.cc b/core/mempool.cc
>> index 1ac3f676..deb7a0bb 100644
>> --- a/core/mempool.cc
>> +++ b/core/mempool.cc
>> @@ -1546,8 +1546,9 @@ static inline void* std_malloc(size_t size, size_t
>> alignment)
>> if ((ssize_t)size < 0)
>> return libc_error_ptr<void *>(ENOMEM);
>> void *ret;
>> - if (size <= memory::pool::max_object_size && alignment <= size &&
>> smp_allocator) {
>> - size = std::max(size, memory::pool::min_object_size);
>> + size_t minimum_size = std::max(size, memory::pool::min_object_size);
>> + if (size <= memory::pool::max_object_size && alignment <=
>> minimum_size && smp_allocator) {
>> + size = minimum_size;
>>
>
> Here you're modifying the original "size" parameter anyway, so I don't
> think you really need this "minimum_size" variable, you could have just
> done above
>
> if (size < minimum_size) {
> size = minimum_size;
> }
>
> And then kept the original if().
> Alternatively, maybe it makes sense not to modify size at all, and instead
> set the new variable n (defind below with a roundup). This will have
> allowed the original "size" to be remembered for the memory leak tracker,
> for example.
>
> But now that I think of this code, I think it misses another, rarer,
> possibility: What if someone allocates size=15 alignment=16 (that's easy to
> add a test for it in your test)? The if() will fail and fall back to a full
> page, but because ! 16 <= 15, but actually when we do the roundup, we
> anyway change the size (n actually) to 16. So maybe the easiest way to do
> this patch is to remove the "alignment" check from the above if,
> and instead do something like this in the code below:
>
> Your observation is correct about two types of sub-scenarios: 1) size <=
alignment and 2) alignment <=size
> unsigned n = ilog2_roundup(std::max(size, memory::pool::min_object_size);
> if (alignment <= n) {
>
I am not sure you meant to compare log2 of size with alignment, did you?
> // .. allocate from a pool
> } else if (alignment <= max_object_size ) { // a new case not handled
> before
> // ... allocate from a pool of size "alignment" instead of "n"
> (assuming alignment is a power of 2 ;-))
> } else {
> // do the large allocation, with the correct alignment.
> }
>
I have sent new patch that addresses your observation. I have also greatly
enhanced the unit test to cover more scenarios.
>
>
>> unsigned n = ilog2_roundup(size);
>> ret = memory::malloc_pools[n].alloc();
>> ret = translate_mem_area(mmu::mem_area::main,
>> mmu::mem_area::mempool,
>> diff --git a/modules/tests/Makefile b/modules/tests/Makefile
>> index b7042a1f..ece5f846 100644
>> --- a/modules/tests/Makefile
>> +++ b/modules/tests/Makefile
>> @@ -116,7 +116,7 @@ tests := tst-pthread.so misc-ramdisk.so tst-vblk.so
>> tst-bsd-evh.so \
>> tst-ifaddrs.so tst-pthread-affinity-inherit.so
>> tst-sem-timed-wait.so \
>> tst-ttyname.so tst-pthread-barrier.so tst-feexcept.so tst-math.so
>> \
>> tst-sigaltstack.so tst-fread.so tst-tcp-cork.so tst-tcp-v6.so \
>> - tst-calloc.so tst-crypt.so tst-non-fpic.so
>> + tst-calloc.so tst-crypt.so tst-non-fpic.so tst-small-malloc.so
>>
>> # libstatic-thread-variable.so tst-static-thread-variable.so \
>>
>> diff --git a/tests/tst-small-malloc.cc b/tests/tst-small-malloc.cc
>> new file mode 100644
>> index 00000000..b0c97c03
>> --- /dev/null
>> +++ b/tests/tst-small-malloc.cc
>> @@ -0,0 +1,45 @@
>> +/*
>> + * Copyright (C) 2018 Waldemar Kozaczuk
>> + *
>> + * This work is open source software, licensed under the terms of the
>> + * BSD license as described in the LICENSE file in the top-level
>> directory.
>> + */
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <cassert>
>> +#include <osv/trace-count.hh>
>> +
>> +int main() {
>> + tracepoint_counter *memory_malloc_mempool_counter = nullptr,
>> + *memory_malloc_page_counter = nullptr;
>> +
>> + for (auto & tp : tracepoint_base::tp_list) {
>> + if ("memory_malloc_mempool" == std::string(tp.name)) {
>> + memory_malloc_mempool_counter = new tracepoint_counter(tp);
>> + }
>> + if ("memory_malloc_page" == std::string(tp.name)) {
>> + memory_malloc_page_counter = new tracepoint_counter(tp);
>> + }
>> + }
>> + assert(memory_malloc_mempool_counter != nullptr);
>> + assert(memory_malloc_page_counter != nullptr);
>> +
>> + auto memory_malloc_mempool_counter_now =
>> memory_malloc_mempool_counter->read();
>> + auto memory_malloc_page_counter_now =
>> memory_malloc_page_counter->read();
>> +
>> + const int allocation_count = 1024;
>> + for( int i = 0; i < allocation_count; i++) {
>> + void *addr = malloc(7);
>> + assert(addr);
>> + free(addr);
>> +
>> + addr = malloc(17);
>> + assert(addr);
>> + free(addr);
>> + }
>> +
>> + // Verify all allocations above were handled by malloc_pool
>> + assert(memory_malloc_mempool_counter->read() -
>> memory_malloc_mempool_counter_now >= 2 * allocation_count);
>> + // Verify that NO allocations were handled by alloc_page
>> + assert(memory_malloc_page_counter->read() -
>> memory_malloc_page_counter_now == 0);
>> +}
>> \ No newline at end of file
>> --
>> 2.19.1
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "OSv Development" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
--
You received this message because you are subscribed to the Google Groups "OSv
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.