Optimized freeing client memory if it spans the whole area.

* If a block of client memory spans the whole chunk, there is no need to walk
  the free list for adjacent blocks to join.
* Minor cleanup.
This commit is contained in:
Axel Dörfler
2012-04-28 23:35:17 +02:00
parent 03b82a629d
commit 6068e43923
+46 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -19,15 +19,18 @@
area might be temporarily unavailable or might be relocated at any time.
*/
// TODO: right now, areas will always stay static until they are deleted;
// locking is not yet done or enforced!
#include "ClientMemoryAllocator.h"
#include "ServerApp.h"
#include <stdio.h>
#include <stdlib.h>
#include "ServerApp.h"
typedef block_list::Iterator block_iterator;
typedef chunk_list::Iterator chunk_iterator;
@@ -126,46 +129,51 @@ ClientMemoryAllocator::Free(block* freeBlock)
block_iterator iterator = fFreeBlocks.GetIterator();
struct block* before = NULL;
struct block* after = NULL;
bool inFreeList = true;
// TODO: this could be done better if free blocks are sorted,
// and if we had one free blocks list per chunk!
// IOW this is a bit slow...
if (freeBlock->size != freeBlock->chunk->size) {
// TODO: this could be done better if free blocks are sorted,
// and if we had one free blocks list per chunk!
// IOW this is a bit slow...
while (struct block* block = iterator.Next()) {
if (block->chunk != freeBlock->chunk)
continue;
while (struct block* block = iterator.Next()) {
if (block->chunk != freeBlock->chunk)
continue;
if (block->base + block->size == freeBlock->base)
before = block;
if (block->base + block->size == freeBlock->base)
before = block;
if (block->base == freeBlock->base + freeBlock->size)
after = block;
}
if (block->base == freeBlock->base + freeBlock->size)
after = block;
}
if (before != NULL && after != NULL) {
// merge with adjacent blocks
before->size += after->size + freeBlock->size;
fFreeBlocks.Remove(after);
free(after);
free(freeBlock);
freeBlock = before;
} else if (before != NULL) {
before->size += freeBlock->size;
free(freeBlock);
freeBlock = before;
} else if (after != NULL) {
after->base -= freeBlock->size;
after->size += freeBlock->size;
free(freeBlock);
freeBlock = after;
if (before != NULL && after != NULL) {
// merge with adjacent blocks
before->size += after->size + freeBlock->size;
fFreeBlocks.Remove(after);
free(after);
free(freeBlock);
freeBlock = before;
} else if (before != NULL) {
before->size += freeBlock->size;
free(freeBlock);
freeBlock = before;
} else if (after != NULL) {
after->base -= freeBlock->size;
after->size += freeBlock->size;
free(freeBlock);
freeBlock = after;
} else
fFreeBlocks.Add(freeBlock);
} else
fFreeBlocks.Add(freeBlock);
inFreeList = false;
if (freeBlock->size == freeBlock->chunk->size) {
// We can delete the chunk now
struct chunk* chunk = freeBlock->chunk;
fFreeBlocks.Remove(freeBlock);
if (inFreeList)
fFreeBlocks.Remove(freeBlock);
free(freeBlock);
fChunks.Remove(chunk);
@@ -284,6 +292,9 @@ ClientMemoryAllocator::_AllocateChunk(size_t size, bool& newArea)
}
// #pragma mark -
ClientMemory::ClientMemory()
:
fBlock(NULL)
@@ -303,7 +314,7 @@ ClientMemory::Allocate(ClientMemoryAllocator* allocator, size_t size,
bool& newArea)
{
fAllocator = allocator;
return fAllocator->Allocate(size, &fBlock, newArea);
return fAllocator->Allocate(size, &fBlock, newArea);
}
@@ -334,6 +345,9 @@ ClientMemory::AreaOffset()
}
// #pragma mark -
ClonedAreaMemory::ClonedAreaMemory()
:
fClonedArea(-1),