1
0
Fork 0

reduce number of mallocs

This commit is contained in:
Jan Steemann 2015-02-15 21:53:07 +01:00
parent 205736a028
commit 4f6c598c42
1 changed files with 29 additions and 15 deletions

View File

@ -27,8 +27,9 @@
/// @author Copyright 2013-2013, triAGENS GmbH, Cologne, Germany /// @author Copyright 2013-2013, triAGENS GmbH, Cologne, Germany
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "Basics/random.h"
#include "skip-list.h" #include "skip-list.h"
#include "Basics/random.h"
#include "Basics/Exceptions.h"
using namespace triagens::basics; using namespace triagens::basics;
@ -50,9 +51,11 @@ static int randomHeight (void) {
while (true) { // will be left by return when the right height is found while (true) { // will be left by return when the right height is found
uint32_t r = TRI_UInt32Random(); uint32_t r = TRI_UInt32Random();
for (count = 32; count > 0; count--) { for (count = 32; count > 0; count--) {
if (0 != (r & 1UL) || height == TRI_SKIPLIST_MAX_HEIGHT) return height; if (0 != (r & 1UL) || height == TRI_SKIPLIST_MAX_HEIGHT) {
r = r >> 1; return height;
height++; }
r = r >> 1;
height++;
} }
} }
} }
@ -63,24 +66,32 @@ static int randomHeight (void) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
SkipListNode* SkipList::allocNode (int height) { SkipListNode* SkipList::allocNode (int height) {
SkipListNode* newNode = new SkipListNode();
newNode->_doc = nullptr;
if (0 == height) { if (0 == height) {
newNode->_height = randomHeight(); height = randomHeight();
} }
else {
newNode->_height = height; // allocate enough memory for skiplist node plus all the next nodes in one go
void* ptr = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(SkipListNode) + sizeof(SkipListNode*) * height, false);
if (ptr == nullptr) {
THROW_OUT_OF_MEMORY_ERROR();
} }
SkipListNode* newNode;
try { try {
newNode->_next = new SkipListNode*[newNode->_height]; // use placement new
newNode = new(ptr) SkipListNode();
} }
catch (...) { catch (...) {
delete newNode; TRI_Free(TRI_UNKNOWN_MEM_ZONE, ptr);
throw; throw;
} }
newNode->_doc = nullptr;
newNode->_height = height;
newNode->_next = reinterpret_cast<SkipListNode**>(static_cast<char*>(ptr) + sizeof(SkipListNode));
for (int i = 0; i < newNode->_height; i++) { for (int i = 0; i < newNode->_height; i++) {
newNode->_next[i] = nullptr; newNode->_next[i] = nullptr;
} }
@ -100,8 +111,11 @@ void SkipList::freeNode (SkipListNode* node) {
// update memory usage // update memory usage
_memoryUsed -= sizeof(SkipListNode) + _memoryUsed -= sizeof(SkipListNode) +
sizeof(SkipListNode*) * node->_height; sizeof(SkipListNode*) * node->_height;
delete[] node->_next;
delete node; // we have used placement new to construct the skiplist node,
// so now we have to manually call its dtor and free the underlying memory
node->~SkipListNode();
TRI_Free(TRI_UNKNOWN_MEM_ZONE, node);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////