aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2018-10-25 13:35:12 +0200
committerSverker Eriksson <[email protected]>2018-10-26 11:57:54 +0200
commit13214aae3697d27d27d5c628997fd4a92b497f89 (patch)
tree539966cbda52ad0f8dc9b14be769bb80679843a4
parentc6af9cd30c151baaa0afb929ce6a0292607db86c (diff)
downloadotp-13214aae3697d27d27d5c628997fd4a92b497f89.tar.gz
otp-13214aae3697d27d27d5c628997fd4a92b497f89.tar.bz2
otp-13214aae3697d27d27d5c628997fd4a92b497f89.zip
erts: Join empty base nodes in catree
The original implementation did not do this due to fear of bad performance. But we think the negative effect of "leaking" empty base nodes is more important to fix. To get the bad performance a special kind of access patterns is needed where base nodes are frequently emptied and then repopulated soon again. ets_SUITE:throughput_benchmark for example did not show any negative effect from this commit at all.
-rw-r--r--erts/emulator/beam/erl_db_catree.c18
-rw-r--r--lib/stdlib/test/ets_SUITE.erl9
2 files changed, 15 insertions, 12 deletions
diff --git a/erts/emulator/beam/erl_db_catree.c b/erts/emulator/beam/erl_db_catree.c
index 5d88c61144..1cd01e7e33 100644
--- a/erts/emulator/beam/erl_db_catree.c
+++ b/erts/emulator/beam/erl_db_catree.c
@@ -703,20 +703,22 @@ void wunlock_base_node(DbTableCATreeNode *base_node)
static ERTS_INLINE
void wunlock_adapt_base_node(DbTableCATree* tb,
- DbTableCATreeNode* base_node,
+ DbTableCATreeNode* node,
DbTableCATreeNode* parent,
int current_level)
{
- dbg_maybe_force_splitjoin(base_node);
- if (base_node->u.base.lock_statistics > ERL_DB_CATREE_HIGH_CONTENTION_LIMIT
- && current_level < ERL_DB_CATREE_MAX_ROUTE_NODE_LAYER_HEIGHT) {
- split_catree(tb, base_node, parent);
+ dbg_maybe_force_splitjoin(node);
+ if ((!node->u.base.root && parent && !(tb->common.status
+ & DB_CATREE_FORCE_SPLIT))
+ || node->u.base.lock_statistics < ERL_DB_CATREE_LOW_CONTENTION_LIMIT) {
+ join_catree(tb, node, parent);
}
- else if (base_node->u.base.lock_statistics < ERL_DB_CATREE_LOW_CONTENTION_LIMIT) {
- join_catree(tb, base_node, parent);
+ else if (node->u.base.lock_statistics > ERL_DB_CATREE_HIGH_CONTENTION_LIMIT
+ && current_level < ERL_DB_CATREE_MAX_ROUTE_NODE_LAYER_HEIGHT) {
+ split_catree(tb, node, parent);
}
else {
- wunlock_base_node(base_node);
+ wunlock_base_node(node);
}
}
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 367c7533b4..74a4f47fa9 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -7393,13 +7393,14 @@ stimulate_contention(Tid) ->
RState = unique_rand_start(KeyRange, Seed),
stim_inserter_loop(T, RState, Num),
Num = ets:info(T, size),
- erts_debug:set_internal_state(ets_force_split, {T, false}),
ets:match_delete(T, {'$1','$1','$1'}),
+ 0 = ets:info(T, size),
+ erts_debug:set_internal_state(ets_force_split, {T, false}),
case ets:info(T,stats) of
{0, _, _} ->
- io:format("Houston, we got a testability problem.\n"
- "Someone seems to have implemented join-on-delete\n", []),
- ct:fail("Join on delete?");
+ io:format("No routing nodes in table?\n"
+ "Debug feature 'ets_force_split' does not seem to work.\n", []),
+ ct:fail("No ets_force_split?");
Stats ->
io:format("stimulated ordered_set: ~p\n", [Stats])
end.