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. // 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);
} }
} }

View File

@ -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;
} }
} }

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 * 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;
} }

View File

@ -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.