Skip to content

Commit ab8d64c

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 aca9146 commit ab8d64c

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
@@ -760,7 +760,7 @@ void do_random_join(DbTableCATree* tb, Uint rand)
760760
return; /* No adaptation */
761761
}
762762
if (parent != NULL && !try_wlock_base_node(&node->u.base)) {
763-
if (!node->u.base.is_valid) {
763+
if (!node->is_valid) {
764764
wunlock_base_node(node);
765765
return;
766766
}
@@ -944,11 +944,10 @@ void unlock_iter_base_node(CATreeRootIterator* iter)
944944
ASSERT(iter->locked_bnode);
945945
if (iter->read_only)
946946
runlock_base_node(iter->locked_bnode, iter->tb);
947-
else if (iter->locked_bnode->u.base.is_valid) {
947+
else if (iter->locked_bnode->is_valid) {
948948
wunlock_adapt_base_node(iter->tb, iter->locked_bnode,
949949
iter->bnode_parent, iter->bnode_level);
950-
}
951-
else
950+
} else
952951
wunlock_base_node(iter->locked_bnode);
953952
iter->locked_bnode = NULL;
954953
}
@@ -1001,7 +1000,7 @@ DbTableCATreeNode* find_rlock_valid_base_node(DbTableCATree* tb, Eterm key)
10011000
while (1) {
10021001
base_node = find_base_node(tb, key, NULL);
10031002
rlock_base_node(base_node);
1004-
if (base_node->u.base.is_valid)
1003+
if (base_node->is_valid)
10051004
break;
10061005
runlock_base_node_no_rand(base_node);
10071006
}
@@ -1017,7 +1016,7 @@ DbTableCATreeNode* find_wlock_valid_base_node(DbTableCATree* tb, Eterm key,
10171016
while (1) {
10181017
base_node = find_base_node(tb, key, fbn);
10191018
wlock_base_node(base_node);
1020-
if (base_node->u.base.is_valid)
1019+
if (base_node->is_valid)
10211020
break;
10221021
wunlock_base_node(base_node);
10231022
}
@@ -1055,7 +1054,7 @@ static DbTableCATreeNode *create_base_node(DbTableCATree *tb,
10551054
ERTS_DB_ALC_MEM_UPDATE_((DbTable *) tb, 0, erts_rwmtx_size(&p->u.base.lock));
10561055
BASE_NODE_STAT_SET(p, ((tb->common.status & DB_CATREE_FORCE_SPLIT)
10571056
? INT_MAX : 0));
1058-
p->u.base.is_valid = true;
1057+
p->is_valid = true;
10591058
return p;
10601059
}
10611060

@@ -1080,7 +1079,7 @@ create_route_node(DbTableCATree *tb,
10801079

10811080
copy_route_key(&p->u.route.key, key, key_size);
10821081
p->is_base_node = false;
1083-
p->u.route.is_valid = true;
1082+
p->is_valid = true;
10841083
erts_atomic_init_nob(&p->u.route.left, (erts_aint_t)left);
10851084
erts_atomic_init_nob(&p->u.route.right, (erts_aint_t)right);
10861085
#ifdef ERTS_ENABLE_LOCK_CHECK
@@ -1236,16 +1235,16 @@ static void join_catree(DbTableCATree *tb,
12361235
BASE_NODE_STAT_SET(thiz, 0);
12371236
wunlock_base_node(thiz);
12381237
return;
1239-
} else if (!neighbor->u.base.is_valid) {
1238+
} else if (!neighbor->is_valid) {
12401239
BASE_NODE_STAT_SET(thiz, 0);
12411240
wunlock_base_node(thiz);
12421241
wunlock_base_node(neighbor);
12431242
return;
12441243
} else {
12451244
lock_route_node(parent);
1246-
parent->u.route.is_valid = false;
1247-
neighbor->u.base.is_valid = false;
1248-
thiz->u.base.is_valid = false;
1245+
parent->is_valid = false;
1246+
neighbor->is_valid = false;
1247+
thiz->is_valid = false;
12491248
gparent = NULL;
12501249
do {
12511250
if (gparent != NULL) {
@@ -1254,7 +1253,7 @@ static void join_catree(DbTableCATree *tb,
12541253
gparent = parent_of(tb, parent);
12551254
if (gparent != NULL)
12561255
lock_route_node(gparent);
1257-
} while (gparent != NULL && !gparent->u.route.is_valid);
1256+
} while (gparent != NULL && !gparent->is_valid);
12581257

12591258
if (gparent == NULL) {
12601259
SET_ROOT_RELB(tb, GET_RIGHT(parent));
@@ -1286,16 +1285,16 @@ static void join_catree(DbTableCATree *tb,
12861285
BASE_NODE_STAT_SET(thiz, 0);
12871286
wunlock_base_node(thiz);
12881287
return;
1289-
} else if (!neighbor->u.base.is_valid) {
1288+
} else if (!neighbor->is_valid) {
12901289
BASE_NODE_STAT_SET(thiz, 0);
12911290
wunlock_base_node(thiz);
12921291
wunlock_base_node(neighbor);
12931292
return;
12941293
} else {
12951294
lock_route_node(parent);
1296-
parent->u.route.is_valid = false;
1297-
neighbor->u.base.is_valid = false;
1298-
thiz->u.base.is_valid = false;
1295+
parent->is_valid = false;
1296+
neighbor->is_valid = false;
1297+
thiz->is_valid = false;
12991298
gparent = NULL;
13001299
do {
13011300
if (gparent != NULL) {
@@ -1307,7 +1306,7 @@ static void join_catree(DbTableCATree *tb,
13071306
} else {
13081307
gparent = NULL;
13091308
}
1310-
} while (gparent != NULL && !gparent->u.route.is_valid);
1309+
} while (gparent != NULL && !gparent->is_valid);
13111310
if (gparent == NULL) {
13121311
SET_ROOT_RELB(tb, GET_LEFT(parent));
13131312
} else if (GET_RIGHT(gparent) == parent) {
@@ -1397,7 +1396,7 @@ static void split_catree(DbTableCATree *tb,
13971396
} else {
13981397
SET_RIGHT_RELB(parent, new_route);
13991398
}
1400-
base->u.base.is_valid = false;
1399+
base->is_valid = false;
14011400
wunlock_base_node(base);
14021401
erts_schedule_db_free(&tb->common,
14031402
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)