Skip to content

Commit 581b213

Browse files
jooho812MinWooJin
authored andcommitted
FEATURE : Add block allocator for more efficient memory management
- This feature is applied only on map collection
1 parent 3483993 commit 581b213

File tree

6 files changed

+187
-0
lines changed

6 files changed

+187
-0
lines changed

engines/default/default_engine.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,12 +630,21 @@ default_map_elem_alloc(ENGINE_HANDLE* handle, const void* cookie,
630630
return ret;
631631
}
632632

633+
#ifdef USE_EBLOCK_RESULT
634+
static void
635+
default_map_elem_release(ENGINE_HANDLE* handle, const void *cookie,
636+
eitem *eitem, EITEM_TYPE type)
637+
{
638+
map_elem_release(get_handle(handle), eitem, type);
639+
}
640+
#else
633641
static void
634642
default_map_elem_release(ENGINE_HANDLE* handle, const void *cookie,
635643
eitem **eitem_array, const int eitem_count)
636644
{
637645
map_elem_release(get_handle(handle), (map_elem_item**)eitem_array, eitem_count);
638646
}
647+
#endif
639648

640649
static ENGINE_ERROR_CODE
641650
default_map_elem_insert(ENGINE_HANDLE* handle, const void* cookie,
@@ -687,7 +696,11 @@ static ENGINE_ERROR_CODE
687696
default_map_elem_get(ENGINE_HANDLE* handle, const void* cookie,
688697
const void* key, const int nkey, const int numfields,
689698
const field_t *flist, const bool delete, const bool drop_if_empty,
699+
#ifdef USE_EBLOCK_RESULT
700+
eblock_result_t *eblk_ret, uint32_t* flags,
701+
#else
690702
eitem** eitem, uint32_t* eitem_count, uint32_t* flags,
703+
#endif
691704
bool* dropped, uint16_t vbucket)
692705
{
693706
struct default_engine *engine = get_handle(handle);
@@ -696,7 +709,11 @@ default_map_elem_get(ENGINE_HANDLE* handle, const void* cookie,
696709

697710
if (delete) ACTION_BEFORE_WRITE(cookie, key, nkey);
698711
ret = map_elem_get(engine, key, nkey, numfields, flist, delete, drop_if_empty,
712+
#ifdef USE_EBLOCK_RESULT
713+
eblk_ret, flags, dropped);
714+
#else
699715
(map_elem_item**)eitem, eitem_count, flags, dropped);
716+
#endif
700717
if (delete) ACTION_AFTER_WRITE(cookie, ret);
701718
return ret;
702719
}

engines/default/items.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8564,6 +8564,18 @@ static void do_map_elem_free(struct default_engine *engine, map_elem_item *elem)
85648564
do_mem_slot_free(engine, elem, ntotal);
85658565
}
85668566

8567+
#ifdef USE_EBLOCK_RESULT
8568+
static void do_map_elem_release(struct default_engine *engine, eitem *eitem)
8569+
{
8570+
map_elem_item *elem = (map_elem_item *)eitem;
8571+
if (elem->refcount != 0) {
8572+
elem->refcount--;
8573+
}
8574+
if (elem->refcount == 0 && elem->next == (map_elem_item *)ADDR_MEANS_UNLINKED) {
8575+
do_map_elem_free(engine, elem);
8576+
}
8577+
}
8578+
#else
85678579
static void do_map_elem_release(struct default_engine *engine, map_elem_item *elem)
85688580
{
85698581
if (elem->refcount != 0) {
@@ -8573,6 +8585,7 @@ static void do_map_elem_release(struct default_engine *engine, map_elem_item *el
85738585
do_map_elem_free(engine, elem);
85748586
}
85758587
}
8588+
#endif
85768589

85778590
static void do_map_node_link(struct default_engine *engine,
85788591
map_meta_info *info,
@@ -8812,14 +8825,22 @@ static void do_map_elem_unlink(struct default_engine *engine,
88128825
static bool do_map_elem_traverse_dfs_byfield(struct default_engine *engine,
88138826
map_meta_info *info, map_hash_node *node, const int hval,
88148827
const field_t *field, const bool delete,
8828+
#ifdef USE_EBLOCK_RESULT
8829+
eblock_result_t *eblk_ret)
8830+
#else
88158831
map_elem_item **elem_array)
8832+
#endif
88168833
{
88178834
bool ret;
88188835
int hidx = MAP_GET_HASHIDX(hval, node->hdepth);
88198836

88208837
if (node->hcnt[hidx] == -1) {
88218838
map_hash_node *child_node = node->htab[hidx];
8839+
#ifdef USE_EBLOCK_RESULT
8840+
ret = do_map_elem_traverse_dfs_byfield(engine, info, child_node, hval, field, delete, eblk_ret);
8841+
#else
88228842
ret = do_map_elem_traverse_dfs_byfield(engine, info, child_node, hval, field, delete, elem_array);
8843+
#endif
88238844
if (ret && delete) {
88248845
if (child_node->tot_hash_cnt == 0 &&
88258846
child_node->tot_elem_cnt < (MAP_MAX_HASHCHAIN_SIZE/2)) {
@@ -8833,10 +8854,17 @@ static bool do_map_elem_traverse_dfs_byfield(struct default_engine *engine,
88338854
map_elem_item *elem = node->htab[hidx];
88348855
while (elem != NULL) {
88358856
if (map_hash_eq(hval, field->value, field->length, elem->hval, elem->data, elem->nfield)) {
8857+
#ifdef USE_EBLOCK_RESULT
8858+
if (eblk_ret != NULL) {
8859+
elem->refcount++;
8860+
eblk_add_elem(eblk_ret, elem);
8861+
}
8862+
#else
88368863
if (elem_array) {
88378864
elem->refcount++;
88388865
elem_array[0] = elem;
88398866
}
8867+
#endif
88408868

88418869
if (delete) {
88428870
do_map_elem_unlink(engine, info, node, hidx, prev, elem, ELEM_DELETE_NORMAL);
@@ -8855,7 +8883,11 @@ static bool do_map_elem_traverse_dfs_byfield(struct default_engine *engine,
88558883
static int do_map_elem_traverse_dfs_bycnt(struct default_engine *engine,
88568884
map_meta_info *info, map_hash_node *node,
88578885
const uint32_t count, const bool delete,
8886+
#ifdef USE_EBLOCK_RESULT
8887+
eblock_result_t *eblk_ret, enum elem_delete_cause cause)
8888+
#else
88588889
map_elem_item **elem_array, enum elem_delete_cause cause)
8890+
#endif
88598891
{
88608892
int hidx = -1;
88618893
int rcnt = 0; /* request count */
@@ -8866,8 +8898,13 @@ static int do_map_elem_traverse_dfs_bycnt(struct default_engine *engine,
88668898
if (node->hcnt[hidx] == -1) {
88678899
map_hash_node *child_node = (map_hash_node *)node->htab[hidx];
88688900
if (count > 0) rcnt = count - fcnt;
8901+
#ifdef USE_EBLOCK_RESULT
8902+
fcnt += do_map_elem_traverse_dfs_bycnt(engine, info, child_node, rcnt, delete,
8903+
eblk_ret, cause);
8904+
#else
88698905
fcnt += do_map_elem_traverse_dfs_bycnt(engine, info, child_node, rcnt, delete,
88708906
(elem_array==NULL ? NULL : &elem_array[fcnt]), cause);
8907+
#endif
88718908
if (delete) {
88728909
if (child_node->tot_hash_cnt == 0 &&
88738910
child_node->tot_elem_cnt < (MAP_MAX_HASHCHAIN_SIZE/2)) {
@@ -8885,10 +8922,17 @@ static int do_map_elem_traverse_dfs_bycnt(struct default_engine *engine,
88858922
if (node->hcnt[hidx] > 0) {
88868923
map_elem_item *elem = node->htab[hidx];
88878924
while (elem != NULL) {
8925+
#ifdef USE_EBLOCK_RESULT
8926+
if (eblk_ret != NULL) {
8927+
elem->refcount++;
8928+
eblk_add_elem(eblk_ret, elem);
8929+
}
8930+
#else
88888931
if (elem_array) {
88898932
elem->refcount++;
88908933
elem_array[fcnt] = elem;
88918934
}
8935+
#endif
88928936
fcnt++;
88938937
if (delete) do_map_elem_unlink(engine, info, node, hidx, NULL, elem, cause);
88948938
if (count > 0 && fcnt >= count) break;
@@ -9017,29 +9061,52 @@ static uint32_t do_map_elem_delete(struct default_engine *engine,
90179061

90189062
static ENGINE_ERROR_CODE do_map_elem_get(struct default_engine *engine,
90199063
map_meta_info *info, const int numfields, const field_t *flist,
9064+
#ifdef USE_EBLOCK_RESULT
9065+
const bool delete, eblock_result_t *eblk_ret)
9066+
#else
90209067
const bool delete, map_elem_item **elem_array, uint32_t *elem_count)
9068+
#endif
90219069
{
90229070
int ii;
90239071
uint32_t array_cnt = 0;
90249072

90259073
if (info->root != NULL) {
9074+
#ifdef USE_EBLOCK_RESULT
9075+
if (!eblk_prepare(eblk_ret, (numfields == 0 || numfields > info->ccnt) ? info->ccnt : numfields))
9076+
return ENGINE_ENOMEM;
9077+
#endif
90269078
if (numfields == 0) {
9079+
#ifdef USE_EBLOCK_RESULT
9080+
array_cnt = do_map_elem_traverse_dfs_bycnt(engine, info, info->root, 0, delete, eblk_ret, ELEM_DELETE_NORMAL);
9081+
#else
90279082
array_cnt = do_map_elem_traverse_dfs_bycnt(engine, info, info->root, 0, delete, elem_array, ELEM_DELETE_NORMAL);
9083+
#endif
90289084
} else {
90299085
for (ii = 0; ii < numfields; ii++) {
90309086
int hval = genhash_string_hash(flist[ii].value, flist[ii].length);
9087+
#ifdef USE_EBLOCK_RESULT
9088+
if (do_map_elem_traverse_dfs_byfield(engine, info, info->root, hval, &flist[ii],
9089+
delete, eblk_ret)) {
9090+
#else
90319091
if (do_map_elem_traverse_dfs_byfield(engine, info, info->root, hval, &flist[ii],
90329092
delete, &elem_array[array_cnt])) {
9093+
#endif
90339094
array_cnt++;
90349095
}
90359096
}
90369097
}
9098+
#ifdef USE_EBLOCK_RESULT
9099+
eblk_truncate(eblk_ret);
9100+
#endif
90379101
if (delete && info->root->tot_hash_cnt == 0 && info->root->tot_elem_cnt == 0) {
90389102
do_map_node_unlink(engine, info, NULL, 0);
90399103
}
90409104
}
90419105

9106+
#ifdef USE_EBLOCK_RESULT
9107+
#else
90429108
*elem_count = array_cnt;
9109+
#endif
90439110
if (array_cnt > 0) {
90449111
return ENGINE_SUCCESS;
90459112
} else {
@@ -9129,6 +9196,12 @@ map_elem_item *map_elem_alloc(struct default_engine *engine, const int nfield, c
91299196
return elem;
91309197
}
91319198

9199+
#ifdef USE_EBLOCK_RESULT
9200+
void map_elem_release(struct default_engine *engine, eitem *eitem, EITEM_TYPE type)
9201+
{
9202+
do_coll_elem_release(engine, eitem, type, do_map_elem_release);
9203+
}
9204+
#else
91329205
void map_elem_release(struct default_engine *engine, map_elem_item **elem_array, const int elem_count)
91339206
{
91349207
int cnt = 0;
@@ -9142,6 +9215,7 @@ void map_elem_release(struct default_engine *engine, map_elem_item **elem_array,
91429215
}
91439216
pthread_mutex_unlock(&engine->cache_lock);
91449217
}
9218+
#endif
91459219

91469220
ENGINE_ERROR_CODE map_elem_insert(struct default_engine *engine, const char *key, const size_t nkey,
91479221
map_elem_item *elem, item_attr *attrp, bool *created, const void *cookie)
@@ -9227,7 +9301,11 @@ ENGINE_ERROR_CODE map_elem_delete(struct default_engine *engine, const char *key
92279301

92289302
ENGINE_ERROR_CODE map_elem_get(struct default_engine *engine, const char *key, const size_t nkey,
92299303
const int numfields, const field_t *flist, const bool delete,
9304+
#ifdef USE_EBLOCK_RESULT
9305+
const bool drop_if_empty, eblock_result_t *eblk_ret,
9306+
#else
92309307
const bool drop_if_empty, map_elem_item **elem_array, uint32_t *elem_count,
9308+
#endif
92319309
uint32_t *flags, bool *dropped)
92329310
{
92339311
hash_item *it;
@@ -9242,7 +9320,11 @@ ENGINE_ERROR_CODE map_elem_get(struct default_engine *engine, const char *key, c
92429320
if ((info->mflags & COLL_META_FLAG_READABLE) == 0) {
92439321
ret = ENGINE_UNREADABLE; break;
92449322
}
9323+
#ifdef USE_EBLOCK_RESULT
9324+
ret = do_map_elem_get(engine, info, numfields, flist, delete, eblk_ret);
9325+
#else
92459326
ret = do_map_elem_get(engine, info, numfields, flist, delete, elem_array, elem_count);
9327+
#endif
92469328
if (ret == ENGINE_SUCCESS) {
92479329
if (info->ccnt == 0 && drop_if_empty) {
92489330
assert(delete == true);
@@ -9252,7 +9334,11 @@ ENGINE_ERROR_CODE map_elem_get(struct default_engine *engine, const char *key, c
92529334
*dropped = false;
92539335
}
92549336
*flags = it->flags;
9337+
#ifdef USE_EBLOCK_RESULT
9338+
} /* ret = ENGINE_ENOMEM or ENGINE_ELEM_ENOENT */
9339+
#else
92559340
} /* ret = ENGINE_ELEM_ENOENT */
9341+
#endif
92569342
} while (0);
92579343
do_item_release(engine, it);
92589344
}

engines/default/items.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,11 @@ map_elem_item *map_elem_alloc(struct default_engine *engine, const int nfield,
478478
const int nbytes, const void *cookie);
479479

480480
void map_elem_release(struct default_engine *engine,
481+
#ifdef USE_EBLOCK_RESULT
482+
eitem *eitem, EITEM_TYPE type);
483+
#else
481484
map_elem_item **elem_array, const int elem_count);
485+
#endif
482486

483487
ENGINE_ERROR_CODE map_elem_insert(struct default_engine *engine,
484488
const char *key, const size_t nkey,
@@ -501,8 +505,13 @@ ENGINE_ERROR_CODE map_elem_delete(struct default_engine *engine,
501505
ENGINE_ERROR_CODE map_elem_get(struct default_engine *engine,
502506
const char *key, const size_t nkey,
503507
const int numfields, const field_t *flist, const bool delete,
508+
#ifdef USE_EBLOCK_RESULT
509+
const bool drop_if_empty, eblock_result_t *eblk_ret,
510+
uint32_t *flags, bool *dropped);
511+
#else
504512
const bool drop_if_empty, map_elem_item **elem_array,
505513
uint32_t *elem_count, uint32_t *flags, bool *dropped);
514+
#endif
506515

507516
ENGINE_ERROR_CODE btree_struct_create(struct default_engine *engine,
508517
const char *key, const size_t nkey,

engines/demo/demo_engine.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,21 @@ Demo_map_elem_alloc(ENGINE_HANDLE* handle, const void* cookie,
422422
return ENGINE_ENOTSUP;
423423
}
424424

425+
#ifdef USE_EBLOCK_RESULT
426+
static void
427+
Demo_map_elem_release(ENGINE_HANDLE* handle, const void *cookie,
428+
eitem *eitem, EITEM_TYPE type)
429+
{
430+
return;
431+
}
432+
#else
425433
static void
426434
Demo_map_elem_release(ENGINE_HANDLE* handle, const void *cookie,
427435
eitem **eitem_array, const int eitem_count)
428436
{
429437
return;
430438
}
439+
#endif
431440

432441
static ENGINE_ERROR_CODE
433442
Demo_map_elem_insert(ENGINE_HANDLE* handle, const void* cookie,
@@ -458,7 +467,11 @@ static ENGINE_ERROR_CODE
458467
Demo_map_elem_get(ENGINE_HANDLE* handle, const void* cookie,
459468
const void* key, const int nkey, const int numfields,
460469
const field_t *flist, const bool delete, const bool drop_if_empty,
470+
#ifdef USE_EBLOCK_RESULT
471+
eblock_result_t* eblk_ret, uint32_t* flags,
472+
#else
461473
eitem** eitem, uint32_t* eitem_count, uint32_t* flags,
474+
#endif
462475
bool* dropped, uint16_t vbucket)
463476
{
464477
return ENGINE_ENOTSUP;

include/memcached/engine.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,13 @@ extern "C" {
438438
eitem** eitem);
439439
void (*map_elem_release)(ENGINE_HANDLE* handle,
440440
const void *cookie,
441+
#ifdef USE_EBLOCK_RESULT
442+
eitem *eitem,
443+
EITEM_TYPE type);
444+
#else
441445
eitem **eitem_array,
442446
const int eitem_count);
447+
#endif
443448
ENGINE_ERROR_CODE (*map_elem_insert)(ENGINE_HANDLE* handle,
444449
const void* cookie,
445450
const void* key,
@@ -474,8 +479,12 @@ extern "C" {
474479
const field_t *flist,
475480
const bool delete,
476481
const bool drop_if_empty,
482+
#ifdef USE_EBLOCK_RESULT
483+
eblock_result_t *eblk_ret,
484+
#else
477485
eitem** eitem,
478486
uint32_t* eitem_count,
487+
#endif
479488
uint32_t* flags,
480489
bool* dropped,
481490
uint16_t vbucket);

0 commit comments

Comments
 (0)