snmalloc icon indicating copy to clipboard operation
snmalloc copied to clipboard

Reserve and limit memory usage?

Open richarddd opened this issue 7 months ago • 3 comments

I'm seeing fantastic performance with snmalloc in a resource constrained environment.

MiMalloc has MIMALLOC_RESERVE_OS_MEMORY and MIMALLOC_LIMIT_OS_ALLOC. Is there any equivalent for snmalloc? I wan't to improve the startup of my program that i know upfront will allocate a lot of memory. But I also want to limit request anymore memory from the OS simlar to MIMALLOC_LIMIT_OS_ALLOC

Thank you!

richarddd avatar Jan 30 '24 08:01 richarddd

This is not a facility we currently support, but the structure of the backend should make this easy to do.

So is the idea to have one parameter which sets the initial reservation that the OS requires, and then to add a bound on the requested memory?

I think we can easily add a range that prevents allocating more than a threshold. snmalloc has ranges that have a super simple interface, e.g.

https://github.com/microsoft/snmalloc/blob/main/src/snmalloc/backend_helpers/commitrange.h

We could make a LimitRange that would prevent allocating too much (typed quickly into github, so probably needs some work):

  template <size_t Limit>
  struct LimitRange
  {
    template<typename ParentRange>
    class Type : public ContainsParent<ParentRange>
    {
      using ContainsParent<ParentRange>::parent;

      size_t allocated{0}; 

    public:
      static constexpr bool Aligned = ParentRange::Aligned;

      static constexpr bool ConcurrencySafe = false;

      using ChunkBounds = typename ParentRange::ChunkBounds;

      CapPtr<void, ChunkBounds> alloc_range(size_t size)
      {
         if (allocated + size >= Limit)
           return nullptr;
         auto result = parent.alloc_range(size);
         if (result != nullptr)
           allocated += size;
         return result;
       }

       void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
       {
         allocated -= size;
         parent.dealloc_range(base, size);
       }
     }
   }

This version is taking a template parameter for the size, but that could be more dynamic, if required.

I have a few other things I am working on, so will be a little while before I can add this. So if you want to try, I am happy to review a PR.

mjp41 avatar Jan 30 '24 11:01 mjp41

P.S. Super interested to know you use case, and any benchmarking that we can use to improve snmalloc.

mjp41 avatar Jan 30 '24 11:01 mjp41

P.S. Super interested to know you use case, and any benchmarking that we can use to improve snmalloc.

I'm running snmalloc as an allocator for a JavaScript runtime written in Rust + C running in AWS Lambda that only has 128MB memory available. It uses A LOT of allocations due to the dynamic nature of JS. I see some regression in "startup" time compared with mimalloc when needing to process larger events as i can not upfront reserve. Lambda typically only needs a few MB for background processes and can dedicate the rest to the main runtime.

Whats really convenient in mimalloc is that this can be controlled via environment variables and thus set dynamically which is a requirement. It would be fantastic if we had a similar option for snmalloc :)

Unfortunately i posses zero c++ skill so a PR would be tricky to put together...

richarddd avatar Jan 30 '24 13:01 richarddd