ExpandableAllocator 0.2.0

A low-level .NET allocator that grows lazily.

There is a newer prerelease version of this package available.
See the version list below for details.
Install-Package ExpandableAllocator -Version 0.2.0
dotnet add package ExpandableAllocator --version 0.2.0
<PackageReference Include="ExpandableAllocator" Version="0.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ExpandableAllocator --version 0.2.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Usage

// Reserve 1 TB of memory.
use alloc = Allocator.Create(Protection.Read, 0x1_000_000_000_000L)

let addr = alloc.Address
let ptr = NativePtr.fromNativeInt addr

// Actually allocate 512 bytes.
alloc.ActualSize <- nativeint 512

// Make sure the pointer hasn't moved.
alloc.Address |> should equal addr

// Read something.
NativePtr.read ptr |> should equal 0

// This would throw an AccessViolationException:
// NativePtr.write ptr 42

// Change the region's protection.
alloc.Protection <- Protection.ReadWrite

// Now, actually write our value.
NativePtr.write ptr 42
NativePtr.read ptr |> should equal 42

More examples can be seen in the Tests.fs file.

How does it work?

Internally, the Allocator reserves memory when it is created
(it does not actually allocate it) using VirtualAlloc
or mmap.
This means that large chunks of memory (ie greater than 1TB) can be reserved
without any allocation.

Then, when more memory is actually needed (using TryReserve or ActualSize),
the Allocator commits the memory using VirtualAlloc or mprotect.

Finally, when the Allocator is Disposed, VirtualFree or munmap
is called on the allocated memory region.

Usage

// Reserve 1 TB of memory.
use alloc = Allocator.Create(Protection.Read, 0x1_000_000_000_000L)

let addr = alloc.Address
let ptr = NativePtr.fromNativeInt addr

// Actually allocate 512 bytes.
alloc.ActualSize <- nativeint 512

// Make sure the pointer hasn't moved.
alloc.Address |> should equal addr

// Read something.
NativePtr.read ptr |> should equal 0

// This would throw an AccessViolationException:
// NativePtr.write ptr 42

// Change the region's protection.
alloc.Protection <- Protection.ReadWrite

// Now, actually write our value.
NativePtr.write ptr 42
NativePtr.read ptr |> should equal 42

More examples can be seen in the Tests.fs file.

How does it work?

Internally, the Allocator reserves memory when it is created
(it does not actually allocate it) using VirtualAlloc
or mmap.
This means that large chunks of memory (ie greater than 1TB) can be reserved
without any allocation.

Then, when more memory is actually needed (using TryReserve or ActualSize),
the Allocator commits the memory using VirtualAlloc or mprotect.

Finally, when the Allocator is Disposed, VirtualFree or munmap
is called on the allocated memory region.

Release Notes

- Improved exceptions.
- Fixed mmap call on Unix and OSX.

This package is not used by any popular GitHub repositories.

Version History

Version Downloads Last updated
0.3.0-pre 233 2/14/2018
0.2.0 259 2/12/2018
0.1.0 250 2/11/2018