mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-23 19:42:50 -06:00
consolidation of free blocks
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
// #define DEBUG_MEMORY_ALLOCATOR
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -372,13 +374,14 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
|
|||||||
cleanup_revisions();
|
cleanup_revisions();
|
||||||
}
|
}
|
||||||
|
|
||||||
top = ms->top;
|
top = ms->top;
|
||||||
free_blocks = ms->free_blocks;
|
free_blocks = ms->free_blocks;
|
||||||
free_descriptors[0] = ms->free_descriptors;
|
free_descriptors[0] = ms->free_descriptors;
|
||||||
free_descriptors[1] = 0;
|
free_descriptors[1] = 0;
|
||||||
free_descriptors[2] = 0;
|
free_descriptors[2] = 0;
|
||||||
last_free_block = 0;
|
last_free_block = 0;
|
||||||
last_free_block_size= 0;
|
last_free_block_size = 0;
|
||||||
|
last_free_block_txn_id= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
@@ -1024,7 +1027,7 @@ object PgfDB::pop_last_block_descriptor(object map, object *res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
|
object PgfDB::delete_block_descriptor(object map, object *po, size_t *psize, txn_t *ptxn_id)
|
||||||
{
|
{
|
||||||
if (map == 0) {
|
if (map == 0) {
|
||||||
*po = 0;
|
*po = 0;
|
||||||
@@ -1034,11 +1037,11 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
|
|||||||
block_descr *descr = ptr(block_descr, map);
|
block_descr *descr = ptr(block_descr, map);
|
||||||
int cmp = (*psize < descr->block_size) ? -1
|
int cmp = (*psize < descr->block_size) ? -1
|
||||||
: (*psize > descr->block_size) ? 1
|
: (*psize > descr->block_size) ? 1
|
||||||
: (descr->block_txn_id > ms->min_txn_id) ? -1
|
: (ms->min_txn_id < descr->block_txn_id) ? -1
|
||||||
: 0;
|
: 0;
|
||||||
if (cmp < 0) {
|
if (cmp < 0) {
|
||||||
object right = descr->right;
|
object right = descr->right;
|
||||||
object left = delete_block_descriptor(descr->left, psize, po);
|
object left = delete_block_descriptor(descr->left, po, psize, ptxn_id);
|
||||||
if (*po != 0) {
|
if (*po != 0) {
|
||||||
map = upd_block_descr(map,left,right);
|
map = upd_block_descr(map,left,right);
|
||||||
map = balanceR_block_descriptor(map);
|
map = balanceR_block_descriptor(map);
|
||||||
@@ -1052,7 +1055,7 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
|
|||||||
return map;
|
return map;
|
||||||
} else if (cmp > 0) {
|
} else if (cmp > 0) {
|
||||||
object left = descr->left;
|
object left = descr->left;
|
||||||
object right = delete_block_descriptor(descr->right, psize, po);
|
object right = delete_block_descriptor(descr->right, po, psize, ptxn_id);
|
||||||
if (*po != 0) {
|
if (*po != 0) {
|
||||||
map = upd_block_descr(map,left,right);
|
map = upd_block_descr(map,left,right);
|
||||||
map = balanceL_block_descriptor(map);
|
map = balanceL_block_descriptor(map);
|
||||||
@@ -1061,6 +1064,7 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
|
|||||||
} else {
|
} else {
|
||||||
fit:
|
fit:
|
||||||
*po = descr->o;
|
*po = descr->o;
|
||||||
|
*ptxn_id = descr->block_txn_id;
|
||||||
|
|
||||||
object new_map;
|
object new_map;
|
||||||
if (descr->left == 0) {
|
if (descr->left == 0) {
|
||||||
@@ -1126,11 +1130,39 @@ object PgfDB::malloc_internal(size_t bytes)
|
|||||||
size_t block_size = request2size(bytes);
|
size_t block_size = request2size(bytes);
|
||||||
|
|
||||||
object o;
|
object o;
|
||||||
|
if (last_free_block != 0 &&
|
||||||
|
last_free_block_size >= block_size &&
|
||||||
|
last_free_block_txn_id < ms->min_txn_id) {
|
||||||
|
|
||||||
|
/* We can grab a piece of the last free block */
|
||||||
|
o = last_free_block;
|
||||||
|
last_free_block += block_size;
|
||||||
|
last_free_block_size -= block_size;
|
||||||
|
if (last_free_block_size == 0) {
|
||||||
|
last_free_block = 0;
|
||||||
|
last_free_block_txn_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
|
fprintf(stderr, "grabbed from the last block %016lx %ld\n", o, block_size);
|
||||||
|
#endif
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
txn_t txn_id;
|
||||||
size_t alloc_size = block_size;
|
size_t alloc_size = block_size;
|
||||||
free_blocks = delete_block_descriptor(free_blocks, &alloc_size, &o);
|
free_blocks = delete_block_descriptor(free_blocks, &o, &alloc_size, &txn_id);
|
||||||
if (o != 0) {
|
if (o != 0) {
|
||||||
if (alloc_size > block_size) {
|
if (alloc_size > block_size) {
|
||||||
free_blocks = insert_block_descriptor(free_blocks, o+block_size, alloc_size-block_size);
|
if (last_free_block != 0) {
|
||||||
|
free_blocks = insert_block_descriptor(free_blocks,
|
||||||
|
last_free_block,
|
||||||
|
last_free_block_size,
|
||||||
|
last_free_block_txn_id);
|
||||||
|
}
|
||||||
|
last_free_block = o+block_size;
|
||||||
|
last_free_block_size = alloc_size-block_size;
|
||||||
|
last_free_block_txn_id = txn_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
@@ -1140,10 +1172,6 @@ object PgfDB::malloc_internal(size_t bytes)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
} else {
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
|
||||||
fprintf(stderr, "allocated from top %016lx\n", top);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t free_size = mmap_size - top;
|
size_t free_size = mmap_size - top;
|
||||||
@@ -1159,6 +1187,10 @@ object PgfDB::malloc_internal(size_t bytes)
|
|||||||
o = top;
|
o = top;
|
||||||
top += block_size;
|
top += block_size;
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
|
fprintf(stderr, "allocated from top %016lx\n", o);
|
||||||
|
#endif
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1206,10 +1238,8 @@ object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
object PgfDB::insert_block_descriptor(object map, object o, size_t size)
|
object PgfDB::insert_block_descriptor(object map, object o, size_t size, txn_t txn_id)
|
||||||
{
|
{
|
||||||
txn_t txn_id = (o >= ms->top) ? 0 : ms->curr_txn_id;
|
|
||||||
|
|
||||||
if (map == 0)
|
if (map == 0)
|
||||||
return new_block_descr(o, size, txn_id);
|
return new_block_descr(o, size, txn_id);
|
||||||
|
|
||||||
@@ -1222,12 +1252,12 @@ object PgfDB::insert_block_descriptor(object map, object o, size_t size)
|
|||||||
: 1;
|
: 1;
|
||||||
if (cmp < 0) {
|
if (cmp < 0) {
|
||||||
object right = descr->right;
|
object right = descr->right;
|
||||||
object left = insert_block_descriptor(descr->left, o, size);
|
object left = insert_block_descriptor(descr->left, o, size, txn_id);
|
||||||
map = upd_block_descr(map,left,right);
|
map = upd_block_descr(map,left,right);
|
||||||
return balanceL_block_descriptor(map);
|
return balanceL_block_descriptor(map);
|
||||||
} else {
|
} else {
|
||||||
object left = descr->left;
|
object left = descr->left;
|
||||||
object right = insert_block_descriptor(descr->right, o, size);
|
object right = insert_block_descriptor(descr->right, o, size, txn_id);
|
||||||
map = upd_block_descr(map,left,right);
|
map = upd_block_descr(map,left,right);
|
||||||
return balanceR_block_descriptor(map);
|
return balanceR_block_descriptor(map);
|
||||||
}
|
}
|
||||||
@@ -1244,36 +1274,64 @@ void PgfDB::free_internal(object o, size_t bytes)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
size_t block_size = request2size(bytes);
|
size_t block_size = request2size(bytes);
|
||||||
|
txn_t txn_id = (o >= ms->top) ? 0 : ms->curr_txn_id;
|
||||||
|
|
||||||
if (o >= ms->top && o+block_size == top) {
|
if (txn_id == 0 && o+block_size == top) {
|
||||||
// The block has been allocated in the current transaction
|
// The block has been allocated in the current transaction
|
||||||
// and it is the last just before the top area. We can
|
// and it is the last just before the top area. We can
|
||||||
// simply decrement top;
|
// simply decrement top;
|
||||||
top -= block_size;
|
top -= block_size;
|
||||||
|
if (last_free_block_txn_id == 0 &&
|
||||||
|
last_free_block != 0 &&
|
||||||
|
last_free_block+last_free_block_size == top) {
|
||||||
|
// After the merge of the current block, the last one is
|
||||||
|
// also on the border with top.
|
||||||
|
top -= last_free_block_size;
|
||||||
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
|
fprintf(stderr, "merged with last free block and top %016lx\n", top);
|
||||||
|
#endif
|
||||||
|
last_free_block = 0;
|
||||||
|
last_free_block_size = 0;
|
||||||
|
last_free_block_txn_id = 0;
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
|
fprintf(stderr, "merged with top %016lx\n", top);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_free_block != 0) {
|
if (last_free_block != 0) {
|
||||||
if (last_free_block+last_free_block_size == o) {
|
if (last_free_block_txn_id == txn_id && last_free_block+last_free_block_size == o) {
|
||||||
last_free_block_size += block_size;
|
last_free_block_size += block_size;
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
fprintf(stderr, "merged block %016lx %ld\n", last_free_block, last_free_block_size);
|
fprintf(stderr, "merged block %016lx %ld\n", last_free_block, last_free_block_size);
|
||||||
#endif
|
#endif
|
||||||
} else if (o+block_size == last_free_block) {
|
return;
|
||||||
|
} else if (txn_id == last_free_block_txn_id && o+block_size == last_free_block) {
|
||||||
last_free_block = o;
|
last_free_block = o;
|
||||||
last_free_block_size += block_size;
|
last_free_block_size += block_size;
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
fprintf(stderr, "merged block %016lx %ld\n", last_free_block, last_free_block_size);
|
fprintf(stderr, "merged block %016lx %ld\n", last_free_block, last_free_block_size);
|
||||||
#endif
|
#endif
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
free_blocks = insert_block_descriptor(free_blocks,
|
||||||
|
last_free_block,
|
||||||
|
last_free_block_size,
|
||||||
|
last_free_block_txn_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
last_free_block = o;
|
last_free_block = o;
|
||||||
last_free_block_size = block_size;
|
last_free_block_size = block_size;
|
||||||
|
last_free_block_txn_id = txn_id;
|
||||||
free_blocks = insert_block_descriptor(free_blocks, o, block_size);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
|
fprintf(stderr, "last free block %016lx (size: %ld, txn_id: %ld)\n",
|
||||||
|
last_free_block,
|
||||||
|
last_free_block_size,
|
||||||
|
last_free_block_txn_id);
|
||||||
dump_free_blocks(free_blocks);
|
dump_free_blocks(free_blocks);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -1341,14 +1399,20 @@ void PgfDB::start_transaction()
|
|||||||
free_descriptors[2] = 0;
|
free_descriptors[2] = 0;
|
||||||
last_free_block = 0;
|
last_free_block = 0;
|
||||||
last_free_block_size = 0;
|
last_free_block_size = 0;
|
||||||
|
last_free_block_txn_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
void PgfDB::commit(object o)
|
void PgfDB::commit(object o)
|
||||||
{
|
{
|
||||||
if (last_free_block != 0) {
|
if (last_free_block != 0) {
|
||||||
last_free_block = 0;
|
free_blocks = insert_block_descriptor(free_blocks,
|
||||||
|
last_free_block,
|
||||||
|
last_free_block_size,
|
||||||
|
last_free_block_txn_id);
|
||||||
|
last_free_block = 0;
|
||||||
last_free_block_size = 0;
|
last_free_block_size = 0;
|
||||||
|
last_free_block_txn_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
malloc_state *ms = current_db->ms;
|
malloc_state *ms = current_db->ms;
|
||||||
@@ -1445,8 +1509,9 @@ void PgfDB::rollback()
|
|||||||
free_descriptors[0] = ms->free_descriptors;
|
free_descriptors[0] = ms->free_descriptors;
|
||||||
free_descriptors[1] = 0;
|
free_descriptors[1] = 0;
|
||||||
free_descriptors[2] = 0;
|
free_descriptors[2] = 0;
|
||||||
last_free_block = 0;
|
last_free_block = 0;
|
||||||
last_free_block_size = 0;
|
last_free_block_size = 0;
|
||||||
|
last_free_block_txn_id = 0;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pthread_mutex_unlock(&ms->write_mutex);
|
pthread_mutex_unlock(&ms->write_mutex);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ private:
|
|||||||
object free_descriptors[3];
|
object free_descriptors[3];
|
||||||
object last_free_block;
|
object last_free_block;
|
||||||
size_t last_free_block_size;
|
size_t last_free_block_size;
|
||||||
|
txn_t last_free_block_txn_id;
|
||||||
|
|
||||||
size_t mmap_size;
|
size_t mmap_size;
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
@@ -136,8 +137,8 @@ private:
|
|||||||
PGF_INTERNAL_DECL object balanceR_block_descriptor(object map);
|
PGF_INTERNAL_DECL object balanceR_block_descriptor(object map);
|
||||||
PGF_INTERNAL_DECL object pop_first_block_descriptor(object map, object *res);
|
PGF_INTERNAL_DECL object pop_first_block_descriptor(object map, object *res);
|
||||||
PGF_INTERNAL_DECL object pop_last_block_descriptor(object map, object *res);
|
PGF_INTERNAL_DECL object pop_last_block_descriptor(object map, object *res);
|
||||||
PGF_INTERNAL_DECL object insert_block_descriptor(object map, object o, size_t size);
|
PGF_INTERNAL_DECL object insert_block_descriptor(object map, object o, size_t size, txn_t txn_id);
|
||||||
PGF_INTERNAL_DECL object delete_block_descriptor(object map, size_t *psize, object *po);
|
PGF_INTERNAL_DECL object delete_block_descriptor(object map, object *po, size_t *psize, txn_t *ptxn_id);
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
PGF_INTERNAL_DECL void dump_free_blocks(object map);
|
PGF_INTERNAL_DECL void dump_free_blocks(object map);
|
||||||
|
|||||||
Reference in New Issue
Block a user