MmapPool: Merge blocks on deallocation if possible
This commit is contained in:
parent
a35e04c049
commit
8e0b742748
@ -298,6 +298,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reserves memory to store len objects and initializes it.
|
// Reserves memory to store len objects and initializes it.
|
||||||
|
// Doesn't change the length.
|
||||||
private void initialize(in size_t len)
|
private void initialize(in size_t len)
|
||||||
{
|
{
|
||||||
reserve(len);
|
reserve(len);
|
||||||
@ -316,7 +317,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset(vector + length_, 0, len * T.sizeof);
|
memset(vector + length_, 0, (len - length_) * T.sizeof);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ struct Integer
|
|||||||
{
|
{
|
||||||
auto tmp = Integer(h);
|
auto tmp = Integer(h);
|
||||||
tmp.subtract(rep);
|
tmp.subtract(rep);
|
||||||
rep = tmp.rep;
|
swap(rep, tmp.rep);
|
||||||
sign = length == 0 ? false : h.sign;
|
sign = length == 0 ? false : h.sign;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,7 +408,7 @@ struct Integer
|
|||||||
{
|
{
|
||||||
auto tmp = Integer(h);
|
auto tmp = Integer(h);
|
||||||
tmp.subtract(rep);
|
tmp.subtract(rep);
|
||||||
rep = tmp.rep;
|
swap(rep, tmp.rep);
|
||||||
sign = length == 0 ? false : !sign;
|
sign = length == 0 ? false : !sign;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ else version (Windows)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This allocator allocates memory in regions (multiple of 4 KB for example).
|
* This allocator allocates memory in regions (multiple of 64 KB for example).
|
||||||
* Each region is then splitted in blocks. So it doesn't request the memory
|
* Each region is then splitted in blocks. So it doesn't request the memory
|
||||||
* from the operating system on each call, but only if there are no large
|
* from the operating system on each call, but only if there are no large
|
||||||
* enough free blocks in the available regions.
|
* enough free blocks in the available regions.
|
||||||
@ -117,30 +117,17 @@ final class MmapPool : Allocator
|
|||||||
{ // Split the block if needed
|
{ // Split the block if needed
|
||||||
Block block2 = cast(Block) (cast(void*) block1 + blockEntrySize + size);
|
Block block2 = cast(Block) (cast(void*) block1 + blockEntrySize + size);
|
||||||
block2.prev = block1;
|
block2.prev = block1;
|
||||||
if (block1.next is null)
|
block2.next = block1.next;
|
||||||
{
|
|
||||||
block2.next = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
block2.next = block1.next.next;
|
|
||||||
}
|
|
||||||
block1.next = block2;
|
|
||||||
|
|
||||||
block1.free = false;
|
|
||||||
block2.free = true;
|
block2.free = true;
|
||||||
|
|
||||||
block2.size = block1.size - blockEntrySize - size;
|
block2.size = block1.size - blockEntrySize - size;
|
||||||
block1.size = size;
|
|
||||||
|
|
||||||
block2.region = block1.region;
|
block2.region = block1.region;
|
||||||
atomicOp!"+="(block1.region.blocks, 1);
|
|
||||||
}
|
block1.next = block2;
|
||||||
else
|
block1.size = size;
|
||||||
{
|
|
||||||
block1.free = false;
|
|
||||||
atomicOp!"+="(block1.region.blocks, 1);
|
|
||||||
}
|
}
|
||||||
|
block1.free = false;
|
||||||
|
atomicOp!"+="(block1.region.blocks, 1);
|
||||||
|
|
||||||
return cast(void*) block1 + blockEntrySize;
|
return cast(void*) block1 + blockEntrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +172,29 @@ final class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
block.free = true;
|
// Merge blocks if neigbours are free.
|
||||||
|
if (block.next !is null && block.next.free)
|
||||||
|
{
|
||||||
|
block.size = blockEntrySize + block.next.size;
|
||||||
|
if (block.next.next !is null)
|
||||||
|
{
|
||||||
|
block.next.next.prev = block;
|
||||||
|
}
|
||||||
|
block.next = block.next.next;
|
||||||
|
}
|
||||||
|
if (block.prev !is null && block.prev.free)
|
||||||
|
{
|
||||||
|
block.size = blockEntrySize + block.size;
|
||||||
|
if (block.next !is null)
|
||||||
|
{
|
||||||
|
block.next.prev = block.prev;
|
||||||
|
}
|
||||||
|
block.prev.next = block.next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block.free = true;
|
||||||
|
}
|
||||||
atomicOp!"-="(block.region.blocks, 1);
|
atomicOp!"-="(block.region.blocks, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -78,8 +78,8 @@ size_t alignedSize(in size_t size, in size_t alignment = 8) pure nothrow @safe @
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* T = Element type of the array being created.
|
* T = Element type of the array being created.
|
||||||
* Init = If should be initialized.
|
* Init = If should be initialized.
|
||||||
* Throws = If $(D_PSYMBOL OutOfMemoryError) should be throwsn.
|
* Throws = If $(D_PSYMBOL OutOfMemoryError) should be throwsn.
|
||||||
* allocator = The allocator used for getting memory.
|
* allocator = The allocator used for getting memory.
|
||||||
* array = A reference to the array being changed.
|
* array = A reference to the array being changed.
|
||||||
* length = New array length.
|
* length = New array length.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user