Skip to content

Commit bd03ca6

Browse files
committed
erts: lift is_valid to DbTableCATreeNode and align lock_statistics
Lift is_valid into the DbTableCATreeNode wrapper (shared by both variants), saving 8 bytes per route node and moving key.term from cache line 2 to cache line 1. Align lock_statistics to the cache line (ERTS_CACHE_LINE_SIZE) so it sits on its own line and avoids false sharing with the lock and root when contending threads update it without holding the lock.
1 parent e9daab8 commit bd03ca6

2 files changed

Lines changed: 26 additions & 29 deletions

File tree

erts/emulator/beam/erl_db_catree.c

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ void do_random_join(DbTableCATree* tb, Uint rand)
758758
return; /* No adaptation */
759759
}
760760
if (parent != NULL && !try_wlock_base_node(&node->u.base)) {
761-
if (!node->u.base.is_valid) {
761+
if (!node->is_valid) {
762762
wunlock_base_node(node);
763763
return;
764764
}
@@ -942,11 +942,10 @@ void unlock_iter_base_node(CATreeRootIterator* iter)
942942
ASSERT(iter->locked_bnode);
943943
if (iter->read_only)
944944
runlock_base_node(iter->locked_bnode, iter->tb);
945-
else if (iter->locked_bnode->u.base.is_valid) {
945+
else if (iter->locked_bnode->is_valid) {
946946
wunlock_adapt_base_node(iter->tb, iter->locked_bnode,
947947
iter->bnode_parent, iter->bnode_level);
948-
}
949-
else
948+
} else
950949
wunlock_base_node(iter->locked_bnode);
951950
iter->locked_bnode = NULL;
952951
}
@@ -999,7 +998,7 @@ DbTableCATreeNode* find_rlock_valid_base_node(DbTableCATree* tb, Eterm key)
999998
while (1) {
1000999
base_node = find_base_node(tb, key, NULL);
10011000
rlock_base_node(base_node);
1002-
if (base_node->u.base.is_valid)
1001+
if (base_node->is_valid)
10031002
break;
10041003
runlock_base_node_no_rand(base_node);
10051004
}
@@ -1015,7 +1014,7 @@ DbTableCATreeNode* find_wlock_valid_base_node(DbTableCATree* tb, Eterm key,
10151014
while (1) {
10161015
base_node = find_base_node(tb, key, fbn);
10171016
wlock_base_node(base_node);
1018-
if (base_node->u.base.is_valid)
1017+
if (base_node->is_valid)
10191018
break;
10201019
wunlock_base_node(base_node);
10211020
}
@@ -1053,7 +1052,7 @@ static DbTableCATreeNode *create_base_node(DbTableCATree *tb,
10531052
ERTS_DB_ALC_MEM_UPDATE_((DbTable *) tb, 0, erts_rwmtx_size(&p->u.base.lock));
10541053
BASE_NODE_STAT_SET(p, ((tb->common.status & DB_CATREE_FORCE_SPLIT)
10551054
? INT_MAX : 0));
1056-
p->u.base.is_valid = true;
1055+
p->is_valid = true;
10571056
return p;
10581057
}
10591058

@@ -1078,7 +1077,7 @@ create_route_node(DbTableCATree *tb,
10781077

10791078
copy_route_key(&p->u.route.key, key, key_size);
10801079
p->is_base_node = false;
1081-
p->u.route.is_valid = true;
1080+
p->is_valid = true;
10821081
erts_atomic_init_nob(&p->u.route.left, (erts_aint_t)left);
10831082
erts_atomic_init_nob(&p->u.route.right, (erts_aint_t)right);
10841083
#ifdef ERTS_ENABLE_LOCK_CHECK
@@ -1234,16 +1233,16 @@ static void join_catree(DbTableCATree *tb,
12341233
BASE_NODE_STAT_SET(thiz, 0);
12351234
wunlock_base_node(thiz);
12361235
return;
1237-
} else if (!neighbor->u.base.is_valid) {
1236+
} else if (!neighbor->is_valid) {
12381237
BASE_NODE_STAT_SET(thiz, 0);
12391238
wunlock_base_node(thiz);
12401239
wunlock_base_node(neighbor);
12411240
return;
12421241
} else {
12431242
lock_route_node(parent);
1244-
parent->u.route.is_valid = false;
1245-
neighbor->u.base.is_valid = false;
1246-
thiz->u.base.is_valid = false;
1243+
parent->is_valid = false;
1244+
neighbor->is_valid = false;
1245+
thiz->is_valid = false;
12471246
gparent = NULL;
12481247
do {
12491248
if (gparent != NULL) {
@@ -1252,7 +1251,7 @@ static void join_catree(DbTableCATree *tb,
12521251
gparent = parent_of(tb, parent);
12531252
if (gparent != NULL)
12541253
lock_route_node(gparent);
1255-
} while (gparent != NULL && !gparent->u.route.is_valid);
1254+
} while (gparent != NULL && !gparent->is_valid);
12561255

12571256
if (gparent == NULL) {
12581257
SET_ROOT_RELB(tb, GET_RIGHT(parent));
@@ -1284,16 +1283,16 @@ static void join_catree(DbTableCATree *tb,
12841283
BASE_NODE_STAT_SET(thiz, 0);
12851284
wunlock_base_node(thiz);
12861285
return;
1287-
} else if (!neighbor->u.base.is_valid) {
1286+
} else if (!neighbor->is_valid) {
12881287
BASE_NODE_STAT_SET(thiz, 0);
12891288
wunlock_base_node(thiz);
12901289
wunlock_base_node(neighbor);
12911290
return;
12921291
} else {
12931292
lock_route_node(parent);
1294-
parent->u.route.is_valid = false;
1295-
neighbor->u.base.is_valid = false;
1296-
thiz->u.base.is_valid = false;
1293+
parent->is_valid = false;
1294+
neighbor->is_valid = false;
1295+
thiz->is_valid = false;
12971296
gparent = NULL;
12981297
do {
12991298
if (gparent != NULL) {
@@ -1305,7 +1304,7 @@ static void join_catree(DbTableCATree *tb,
13051304
} else {
13061305
gparent = NULL;
13071306
}
1308-
} while (gparent != NULL && !gparent->u.route.is_valid);
1307+
} while (gparent != NULL && !gparent->is_valid);
13091308
if (gparent == NULL) {
13101309
SET_ROOT_RELB(tb, GET_LEFT(parent));
13111310
} else if (GET_RIGHT(gparent) == parent) {
@@ -1395,7 +1394,7 @@ static void split_catree(DbTableCATree *tb,
13951394
} else {
13961395
SET_RIGHT_RELB(parent, new_route);
13971396
}
1398-
base->u.base.is_valid = false;
1397+
base->is_valid = false;
13991398
wunlock_base_node(base);
14001399
erts_schedule_db_free(&tb->common,
14011400
do_free_base_node,
@@ -1762,7 +1761,7 @@ TreeDbTerm** catree_find_root(Eterm key, CATreeRootIterator* iter)
17621761
while (1) {
17631762
base_node = find_base_node(iter->tb, key, &fbn);
17641763
lock_iter_base_node(iter, base_node, fbn.parent, fbn.current_level);
1765-
if (base_node->u.base.is_valid)
1764+
if (base_node->is_valid)
17661765
break;
17671766
unlock_iter_base_node(iter);
17681767
}
@@ -1841,7 +1840,7 @@ TreeDbTerm** catree_find_nextprev_root(CATreeRootIterator *iter,
18411840
}
18421841
ASSERT(node != rejected_invalid);
18431842
lock_iter_base_node(iter, node, parent, current_level);
1844-
if (node->u.base.is_valid) {
1843+
if (node->is_valid) {
18451844
ASSERT(node != rejected_empty);
18461845
if (node->u.base.root) {
18471846
iter->next_route_key = (next_route_node ?
@@ -1856,8 +1855,7 @@ TreeDbTerm** catree_find_nextprev_root(CATreeRootIterator *iter,
18561855
}
18571856
route_key = next_route_node->u.route.key.term;
18581857
IF_DEBUG(rejected_empty = node);
1859-
}
1860-
else
1858+
} else
18611859
IF_DEBUG(rejected_invalid = node);
18621860

18631861
/* Retry */
@@ -1914,7 +1912,7 @@ TreeDbTerm** catree_find_next_from_pb_key_root(Eterm pb_key,
19141912
}
19151913
ASSERT(node != rejected_base);
19161914
lock_iter_base_node(iter, node, parent, current_level);
1917-
if (node->u.base.is_valid) {
1915+
if (node->is_valid) {
19181916
iter->next_route_key = (next_route_node ?
19191917
next_route_node->u.route.key.term :
19201918
THE_NON_VALUE);
@@ -1967,7 +1965,7 @@ TreeDbTerm** catree_find_prev_from_pb_key_root(Eterm key,
19671965
}
19681966
ASSERT(node != rejected_base);
19691967
lock_iter_base_node(iter, node, parent, current_level);
1970-
if (node->u.base.is_valid) {
1968+
if (node->is_valid) {
19711969
iter->next_route_key = (next_route_node ?
19721970
next_route_node->u.route.key.term :
19731971
THE_NON_VALUE);
@@ -2002,7 +2000,7 @@ static TreeDbTerm** catree_find_firstlast_root(CATreeRootIterator* iter,
20022000
}
20032001
ASSERT(node != rejected_base);
20042002
lock_iter_base_node(iter, node, next_route_node, current_level);
2005-
if (node->u.base.is_valid) {
2003+
if (node->is_valid) {
20062004
iter->next_route_key = (next_route_node ?
20072005
next_route_node->u.route.key.term :
20082006
THE_NON_VALUE);

erts/emulator/beam/erl_db_catree.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ typedef struct {
4545
typedef struct {
4646
erts_rwmtx_t lock; /* The lock for this base node */
4747
TreeDbTerm *root; /* The root of the sequential tree */
48-
bool is_valid; /* If this base node is still valid */
49-
erts_atomic_t lock_statistics;
48+
erts_atomic_t lock_statistics erts_align_attribute(ERTS_CACHE_LINE_SIZE);
5049
ErtsThrPrgrLaterOp free_item; /* Used when freeing using thread progress */
5150

5251
char end_of_struct__;
@@ -59,13 +58,13 @@ typedef struct {
5958
#ifdef ERTS_ENABLE_LOCK_CHECK
6059
Sint lc_order;
6160
#endif
62-
bool is_valid; /* If this route node is still valid */
6361
ErtsThrPrgrLaterOp free_item; /* Used when freeing using thread progress */
6462
DbRouteKey key;
6563
} DbTableCATreeRouteNode;
6664

6765
typedef struct DbTableCATreeNode {
6866
bool is_base_node;
67+
bool is_valid; /* Shared by both base and route node variants */
6968
union {
7069
DbTableCATreeRouteNode route;
7170
DbTableCATreeBaseNode base;

0 commit comments

Comments
 (0)