summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-01-05 14:25:54 +0100
committerEugen Wissner <belka@caraus.de>2017-01-05 14:25:54 +0100
commit8e0b7427482cacd9b4d5a69a13f9a43c11457323 (patch)
tree5b28645d381115cde6c4393e0abd2acaaa2c9e90 /source
parenta35e04c049ca0d9310315fe46475ba1cd5aa5b6f (diff)
downloadtanya-8e0b7427482cacd9b4d5a69a13f9a43c11457323.tar.gz
MmapPool: Merge blocks on deallocation if possible
Diffstat (limited to 'source')
-rw-r--r--source/tanya/container/vector.d3
-rw-r--r--source/tanya/math/mp.d4
-rw-r--r--source/tanya/memory/mmappool.d53
-rw-r--r--source/tanya/memory/package.d4
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.