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.
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user