Skip to content

Commit bbbbfb1

Browse files
committed
Add branch prediction hints to quicklist
Actually makes a noticeable difference. Branch hints were selected based on profiler hotspots.
1 parent 5f506b6 commit bbbbfb1

File tree

1 file changed

+21
-10
lines changed

1 file changed

+21
-10
lines changed

src/quicklist.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ static const size_t optimization_level[] = {4096, 8192, 16384, 32768, 65536};
7777
(e)->sz = 0; \
7878
} while (0)
7979

80+
#if __GNUC__ >= 3
81+
#define likely(x) __builtin_expect(!!(x), 1)
82+
#define unlikely(x) __builtin_expect(!!(x), 0)
83+
#else
84+
#define likely(x) (x)
85+
#define unlikely(x) (x)
86+
#endif
87+
8088
/* Create a new quicklist.
8189
* Free with quicklistRelease(). */
8290
quicklist *quicklistCreate(void) {
@@ -405,7 +413,7 @@ static int _quicklistNodeSizeMeetsOptimizationRequirement(const size_t sz,
405413

406414
static int _quicklistNodeAllowInsert(const quicklistNode *node, const int fill,
407415
const size_t sz) {
408-
if (!node)
416+
if (unlikely(!node))
409417
return 0;
410418

411419
int ziplist_overhead;
@@ -418,14 +426,14 @@ static int _quicklistNodeAllowInsert(const quicklistNode *node, const int fill,
418426
/* size of forward offset */
419427
if (sz < 64)
420428
ziplist_overhead += 1;
421-
else if (sz < 16384)
429+
else if (likely(sz < 16384))
422430
ziplist_overhead += 2;
423431
else
424432
ziplist_overhead += 5;
425433

426434
/* new_sz overestimates if 'sz' encodes to an integer type */
427435
unsigned int new_sz = node->sz + sz + ziplist_overhead;
428-
if (_quicklistNodeSizeMeetsOptimizationRequirement(new_sz, fill))
436+
if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(new_sz, fill)))
429437
return 1;
430438
else if (!sizeMeetsSafetyLimit(new_sz))
431439
return 0;
@@ -443,7 +451,7 @@ static int _quicklistNodeAllowMerge(const quicklistNode *a,
443451
/* approximate merged ziplist size (- 11 to remove one ziplist
444452
* header/trailer) */
445453
unsigned int merge_sz = a->sz + b->sz - 11;
446-
if (_quicklistNodeSizeMeetsOptimizationRequirement(merge_sz, fill))
454+
if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(merge_sz, fill)))
447455
return 1;
448456
else if (!sizeMeetsSafetyLimit(merge_sz))
449457
return 0;
@@ -464,7 +472,8 @@ static int _quicklistNodeAllowMerge(const quicklistNode *a,
464472
* Returns 1 if new head created. */
465473
int quicklistPushHead(quicklist *quicklist, void *value, size_t sz) {
466474
quicklistNode *orig_head = quicklist->head;
467-
if (_quicklistNodeAllowInsert(quicklist->head, quicklist->fill, sz)) {
475+
if (likely(
476+
_quicklistNodeAllowInsert(quicklist->head, quicklist->fill, sz))) {
468477
quicklist->head->zl =
469478
ziplistPush(quicklist->head->zl, value, sz, ZIPLIST_HEAD);
470479
quicklistNodeUpdateSz(quicklist->head);
@@ -486,7 +495,8 @@ int quicklistPushHead(quicklist *quicklist, void *value, size_t sz) {
486495
* Returns 1 if new tail created. */
487496
int quicklistPushTail(quicklist *quicklist, void *value, size_t sz) {
488497
quicklistNode *orig_tail = quicklist->tail;
489-
if (_quicklistNodeAllowInsert(quicklist->tail, quicklist->fill, sz)) {
498+
if (likely(
499+
_quicklistNodeAllowInsert(quicklist->tail, quicklist->fill, sz))) {
490500
quicklist->tail->zl =
491501
ziplistPush(quicklist->tail->zl, value, sz, ZIPLIST_TAIL);
492502
quicklistNodeUpdateSz(quicklist->tail);
@@ -649,8 +659,8 @@ void quicklistDelEntry(quicklistIter *iter, quicklistEntry *entry) {
649659
int quicklistReplaceAtIndex(quicklist *quicklist, long index, void *data,
650660
int sz) {
651661
quicklistEntry entry;
652-
if (quicklistIndex(quicklist, index, &entry)) {
653-
// quicklistDecompressNode(entry.node);
662+
if (likely(quicklistIndex(quicklist, index, &entry))) {
663+
/* quicklistIndex provides an uncompressed node */
654664
entry.node->zl = ziplistDelete(entry.node->zl, &entry.zi);
655665
entry.node->zl = ziplistInsert(entry.node->zl, entry.zi, data, sz);
656666
quicklistCompress(quicklist, entry.node);
@@ -1223,7 +1233,7 @@ int quicklistIndex(const quicklist *quicklist, const long long idx,
12231233
if (index >= quicklist->count)
12241234
return 0;
12251235

1226-
while (n) {
1236+
while (likely(n)) {
12271237
if ((accum + n->count) > index) {
12281238
break;
12291239
} else {
@@ -1253,7 +1263,8 @@ int quicklistIndex(const quicklist *quicklist, const long long idx,
12531263
quicklistDecompressNodeForUse(entry->node);
12541264
entry->zi = ziplistIndex(entry->node->zl, entry->offset);
12551265
ziplistGet(entry->zi, &entry->value, &entry->sz, &entry->longval);
1256-
// quicklistCompress(quicklist, entry->node);
1266+
/* The caller will use our result, so we don't re-compress here.
1267+
* The caller can recompress or delete the node as needed. */
12571268
return 1;
12581269
}
12591270

0 commit comments

Comments
 (0)