From 8e0b7427482cacd9b4d5a69a13f9a43c11457323 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 5 Jan 2017 14:25:54 +0100 Subject: [PATCH] MmapPool: Merge blocks on deallocation if possible --- source/tanya/container/vector.d | 3 +- source/tanya/math/mp.d | 4 +-- source/tanya/memory/mmappool.d | 53 +++++++++++++++++++-------------- source/tanya/memory/package.d | 4 +-- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d index ae909cc..1316a96 100644 --- a/source/tanya/container/vector.d +++ b/source/tanya/container/vector.d @@ -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); } } diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d index 6ef9926..d36ec18 100644 --- a/source/tanya/math/mp.d +++ b/source/tanya/math/mp.d @@ -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; } } diff --git a/source/tanya/memory/mmappool.d b/source/tanya/memory/mmappool.d index 0e322af..5682b52 100644 --- a/source/tanya/memory/mmappool.d +++ b/source/tanya/memory/mmappool.d @@ -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; } diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d index 8b27dcf..60a45a6 100644 --- a/source/tanya/memory/package.d +++ b/source/tanya/memory/package.d @@ -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.