MmapPool: Merge blocks on deallocation if possible

This commit is contained in:
Eugen Wissner 2017-01-05 14:25:54 +01:00
parent a35e04c049
commit 8e0b742748
4 changed files with 37 additions and 27 deletions

View File

@ -298,6 +298,7 @@ struct Vector(T)
}
// Reserves memory to store len objects and initializes it.
// Doesn't change the length.
private void initialize(in size_t len)
{
reserve(len);
@ -316,7 +317,7 @@ struct Vector(T)
}
else
{
memset(vector + length_, 0, len * T.sizeof);
memset(vector + length_, 0, (len - length_) * T.sizeof);
}
}

View File

@ -391,7 +391,7 @@ struct Integer
{
auto tmp = Integer(h);
tmp.subtract(rep);
rep = tmp.rep;
swap(rep, tmp.rep);
sign = length == 0 ? false : h.sign;
}
}
@ -408,7 +408,7 @@ struct Integer
{
auto tmp = Integer(h);
tmp.subtract(rep);
rep = tmp.rep;
swap(rep, tmp.rep);
sign = length == 0 ? false : !sign;
}
}

View File

@ -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
* from the operating system on each call, but only if there are no large
* enough free blocks in the available regions.
@ -117,30 +117,17 @@ final class MmapPool : Allocator
{ // Split the block if needed
Block block2 = cast(Block) (cast(void*) block1 + blockEntrySize + size);
block2.prev = block1;
if (block1.next is null)
{
block2.next = null;
}
else
{
block2.next = block1.next.next;
}
block1.next = block2;
block1.free = false;
block2.next = block1.next;
block2.free = true;
block2.size = block1.size - blockEntrySize - size;
block1.size = size;
block2.region = block1.region;
atomicOp!"+="(block1.region.blocks, 1);
}
else
{
block1.free = false;
atomicOp!"+="(block1.region.blocks, 1);
block1.next = block2;
block1.size = size;
}
block1.free = false;
atomicOp!"+="(block1.region.blocks, 1);
return cast(void*) block1 + blockEntrySize;
}
@ -185,7 +172,29 @@ final class MmapPool : Allocator
}
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);
return true;
}

View File

@ -78,8 +78,8 @@ size_t alignedSize(in size_t size, in size_t alignment = 8) pure nothrow @safe @
*
* Params:
* T = Element type of the array being created.
* Init = If should be initialized.
* Throws = If $(D_PSYMBOL OutOfMemoryError) should be throwsn.
* Init = If should be initialized.
* Throws = If $(D_PSYMBOL OutOfMemoryError) should be throwsn.
* allocator = The allocator used for getting memory.
* array = A reference to the array being changed.
* length = New array length.