Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MemoryPool APIs #24681

Closed
KrzysztofCwalina opened this issue Jan 16, 2018 · 4 comments
Closed

Add MemoryPool APIs #24681

KrzysztofCwalina opened this issue Jan 16, 2018 · 4 comments
Labels
api-approved API was approved in API review, it can be implemented area-System.Memory
Milestone

Comments

@KrzysztofCwalina
Copy link
Member

This API is an abstraction and a singleton implementation of a pool providing OwnedMemory instances. The pool is used by (and required by) Pipelines, but is a very general purpose type.

The default implementation of the pool (MemoryPool<T>.Default) is using ArrayPool to provide actual memory buffers. Pipelines use an internal slab allocator implementation. There are other prototype implementations in corefxlab, e.g. NativeMemoryPool<T>; a pool based on native memory.

MemoryPool would go into System.Memory.dll and System.Buffers namespace

    public abstract class MemoryPool<T> : IDisposable {
        public static MemoryPool<T> Default { get; }
        public abstract OwnedMemory<T> Rent(int minBufferSize=AnySize);
        public const int AnySize = int.MinValue;
        public abstract int MaxBufferSize { get; }

        protected MemoryPool();
        public void Dispose();
        protected abstract void Dispose(bool disposing);
        ~MemoryPool();
    }

The pooled instances are returned to the pool when they are disposed:

using(OwnedMemory<byte> om = MemoryPool<byte>.Default.Rent()){
    Memory<byte> memory = om.Memory;
    Span<byte> span = memory.Span;
    ...
} // this is where the om is returned to the pool

cc: @davidfowl, @pakrym, @joshfree, @ahsonkhan

@terrajobst
Copy link
Member

terrajobst commented Jan 16, 2018

Video

  • Minimum size. The sentinel of int.MinValue seems over the top, -1 seesm good enough. 1 would be too harsh, as the semantics we want is "give me any buffer size that is convenient for the pool".

  • Finalizer. Don't define a finalizer. Otherwise, all derived types (even the fully managed ones) go into the finalizer queue.

  • Default. Renamed to Shared to align with ArrayPool<T>.

  • Dispose. What should Dispose do for the Shared instance? It seems no-op is the best choice, otherwise everyone has to special case when folks.

public abstract class MemoryPool<T> : IDisposable
{
    public static MemoryPool<T> Shared { get; }

    public abstract OwnedMemory<T> Rent(int minBufferSize=-1);
    public abstract int MaxBufferSize { get; }

    protected MemoryPool();
    public void Dispose();
    protected abstract void Dispose(bool disposing);
}

@benaadams
Copy link
Member

benaadams commented Jan 16, 2018

Should Dispose be explicit IDisposable.Dispose since a receiver shouldn't Dispose it?

@omariom
Copy link
Contributor

omariom commented Jan 17, 2018

Will it possible to use custom MemoryPools with Pipelines?

@pakrym
Copy link
Contributor

pakrym commented Jan 17, 2018

@omariom, yes, pipe constructor takes memory pool in PipeOptions

@joshfree joshfree assigned ghost Jan 17, 2018
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 18, 2020
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Memory
Projects
None yet
Development

No branches or pull requests

6 participants