diff options
-rw-r--r-- | src/btree/bt_split.c | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c index 94c73106d70..519452b8253 100644 --- a/src/btree/bt_split.c +++ b/src/btree/bt_split.c @@ -257,13 +257,12 @@ __split_ovfl_key_cleanup(WT_SESSION_IMPL *session, WT_PAGE *page, WT_REF *ref) } /* - * __split_ref_deepen_move -- - * Move a WT_REF from a parent to a child in service of a split to deepen - * the tree, including updating the accounting information. + * __split_ref_instantiate -- + * Instantiate key/address pairs in memory in service of a split. */ static int -__split_ref_deepen_move(WT_SESSION_IMPL *session, - WT_PAGE *parent, WT_REF *ref, size_t *parent_decrp, size_t *child_incrp) +__split_ref_instantiate(WT_SESSION_IMPL *session, + WT_PAGE *page, WT_REF *ref, size_t *parent_decrp, size_t *child_incrp) { WT_ADDR *addr; WT_CELL_UNPACK unpack; @@ -280,6 +279,8 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session, * of child pages, and so we can no longer reference the block image * that remains with the page being split. * + * Track how much memory the parent is losing and the child gaining. + * * No locking is required to update the WT_REF structure because we're * the only thread splitting the parent page, and there's no way for * readers to race with our updates of single pointers. The changes @@ -288,13 +289,13 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session, * * Row-store keys, first. */ - if (parent->type == WT_PAGE_ROW_INT) { + if (page->type == WT_PAGE_ROW_INT) { if ((ikey = __wt_ref_key_instantiated(ref)) == NULL) { - __wt_ref_key(parent, ref, &key, &size); + __wt_ref_key(page, ref, &key, &size); WT_RET(__wt_row_ikey(session, 0, key, size, &ikey)); ref->key.ikey = ikey; } else { - WT_RET(__split_ovfl_key_cleanup(session, parent, ref)); + WT_RET(__split_ovfl_key_cleanup(session, page, ref)); WT_MEMSIZE_ADD(*parent_decrp, sizeof(WT_IKEY) + ikey->size); } @@ -306,8 +307,12 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session, * address has been instantiated, there's no work to do. Otherwise, * get the address from the on-page cell. */ - addr = ref->addr; - if (addr != NULL && !__wt_off_page(parent, addr)) { + if ((addr = ref->addr) == NULL) + return (0); + if (__wt_off_page(page, addr)) + WT_MEMSIZE_TRANSFER(*parent_decrp, *child_incrp, + sizeof(WT_ADDR) + addr->size); + else { __wt_cell_unpack((WT_CELL *)ref->addr, &unpack); WT_RET(__wt_calloc_one(session, &addr)); if ((ret = __wt_strndup( @@ -319,11 +324,8 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session, addr->type = unpack.raw == WT_CELL_ADDR_INT ? WT_ADDR_INT : WT_ADDR_LEAF; ref->addr = addr; + WT_MEMSIZE_ADD(*child_incrp, sizeof(WT_ADDR) + addr->size); } - - /* And finally, the WT_REF itself. */ - WT_MEMSIZE_TRANSFER(*parent_decrp, *child_incrp, sizeof(WT_REF)); - return (0); } @@ -500,9 +502,12 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children) child_incr = 0; child_pindex = WT_INTL_INDEX_COPY(child); for (child_refp = child_pindex->index, j = 0; j < slots; ++j) { - WT_ERR(__split_ref_deepen_move(session, + WT_ERR(__split_ref_instantiate(session, parent, *parent_refp, &parent_decr, &child_incr)); *child_refp++ = *parent_refp++; + + WT_MEMSIZE_TRANSFER( + parent_decr, child_incr, sizeof(WT_REF)); } __wt_cache_page_inmem_incr(session, child, child_incr); } @@ -598,7 +603,6 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children) WT_ERR(__split_safe_free(session, 0, pindex, size)); WT_MEMSIZE_ADD(parent_decr, size); -#if 0 /* * Adjust the parent's memory footprint. This may look odd, but we * have already taken the allocation overhead into account, and an @@ -607,19 +611,6 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children) */ __wt_cache_page_inmem_incr(session, parent, parent_incr); __wt_cache_page_inmem_decr(session, parent, parent_decr); -#else - /* - * XXX - * The code to track page sizes is fundamentally flawed in the face of - * splits: for example, we don't add in an overhead allocation constant - * when allocating WT_REF structures as pages are created, but the - * calculations during split assume that correction. For now, ignore - * our carefully calculated values and force the internal page size to - * 5% of its current value. - */ - size = parent->memory_footprint - (parent->memory_footprint / 20); - __wt_cache_page_inmem_decr(session, parent, size); -#endif if (0) { err: __wt_free_ref_index(session, parent, alloc_index, 1); @@ -783,11 +774,13 @@ __wt_multi_to_ref(WT_SESSION_IMPL *session, * the confusion. */ WT_RET(__wt_calloc_one(session, &addr)); + WT_MEMSIZE_ADD(incr, sizeof(WT_ADDR)); ref->addr = addr; addr->size = multi->addr.size; addr->type = multi->addr.type; WT_RET(__wt_strndup(session, multi->addr.addr, addr->size, &addr->addr)); + WT_MEMSIZE_ADD(incr, addr->size); } else WT_RET(__split_multi_inmem(session, page, ref, multi)); |