Skip to content

Add batched prefetch for HGETALL on hashtable encoding#14988

Merged
sundb merged 7 commits into
redis:unstablefrom
filipecosta90:hgetall-batch-prefetch
Apr 29, 2026
Merged

Add batched prefetch for HGETALL on hashtable encoding#14988
sundb merged 7 commits into
redis:unstablefrom
filipecosta90:hgetall-batch-prefetch

Conversation

@fcostaoliveira

@fcostaoliveira fcostaoliveira commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add a batched prefetch fast path for HGETALL on hashtable-encoded hashes. When iterating large hash tables, pointer chasing through scattered heap allocations (dictEntryEntry → value SDS) causes cache misses that dominate CPU time (~10% flat in dictNext).

The new path collects dict entries in batches of configured batch size, issues software prefetches for the Entry structs and their value SDS data, then emits replies while the data is cache-warm. This hides memory latency by overlapping prefetch with reply generation.

Conditions for the fast path:

  • Hashtable encoding (not listpack)
  • Both key and value requested
  • prefetch-batch-max-size > 0

Falls back to the existing generic iterator path otherwise.

Benchmark Results

Tested on x86-aws-m7i.metal-24xl and arm-aws-m8g.metal-24xl, oss-standalone topology.

x86 — 5 improvements, 0 regressions

Test Baseline (unstable) PR Change
10Kkeys-500f-100B 14,387 ±3.1% 17,229 ±1.8% +19.8%
10Kkeys-200f-100B 35,701 ±0.2% 42,024 ±0.9% +17.7%
1key-1Kf-hgetall-pipeline-10 15,409 ±0.8% 18,116 ±0.3% +17.6%
1key-1Kf-hgetall 16,539 ±0.7% 18,866 ±0.2% +14.1%
10Kkeys-100f-100B 65,592 ±0.1% 72,793 ±1.3% +11.0%
100Kkeys-50f-100B 163,447 ±1.4% 163,626 ±2.0% +0.1%
1Mkeys-50f-10B (listpack) 171,672 ±1.9% 174,819 +1.8%
1Mkeys-mixed-hget/hgetall/hkeys/hvals 173,737 ±2.0% 173,966 +0.1%

ARM — 5 improvements, 0 regressions

Test Baseline (unstable) PR Change
10Kkeys-200f-100B 43,894 ±1.1% 52,665 ±1.2% +20.0%
1key-1Kf-hgetall-pipeline-10 15,146 ±0.7% 17,732 ±0.1% +17.1%
1key-1Kf-hgetall 16,216 ±0.5% 18,659 ±0.5% +15.1%
10Kkeys-100f-100B 77,862 ±1.4% 86,865 ±0.6% +11.6%
100Kkeys-50f-100B 205,051 ±0.4% 206,866 ±0.5% +0.9%
1Mkeys-50f-10B (listpack) 212,915 ±0.6% 211,842 -0.5%
1Mkeys-mixed-hget/hgetall/hkeys/hvals 219,900 ±0.4% 220,934 +0.5%

Improvement scales with field count — more fields means more cache misses hidden by prefetch. Zero regressions on listpack-encoded or small hashtable hashes.


Note

Medium Risk
Touches the hot reply/iteration path for HGETALL and adds new control flow (goto done) plus expiry filtering, so subtle count/order or iterator correctness issues could surface under edge cases despite being scoped to HT encoding.

Overview
Adds a batched prefetch fast path to genericHgetallCommand for hashtable-encoded hashes (OBJ_ENCODING_HT), issuing redis_prefetch_read on Entry structs and their value SDS in small batches before writing replies.

The new path compacts out expired fields (when allow_access_expired is off), preserves existing reply shape/count assertions, and falls back to the existing hashTypeIterator loop for non-HT encodings.

Reviewed by Cursor Bugbot for commit b475e1c. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 9d820b7. Configure here.

Comment thread src/t_hash.c
Comment thread src/t_hash.c Outdated
@augmentcode

augmentcode Bot commented Apr 4, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Adds a batched software-prefetch fast path for HGETALL/GETALL on hashtable-encoded hashes to reduce cache-miss overhead during iteration.

Changes:

  • Introduces a 3-phase loop that batches 16 dict entries, prefetches Entry structs and then their value SDS, and finally emits replies
  • Keeps the existing generic iterator path as a fallback for other encodings / flag combinations
  • Gates the new path behind prefetch-batch-max-size > 0

Technical Notes: The new path manually skips expired fields and uses addReplyBulkCBuffer directly for field/value bulk replies.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/t_hash.c Outdated
Comment thread src/t_hash.c Outdated
@fcostaoliveira fcostaoliveira requested a review from sundb April 8, 2026 09:28
Comment thread src/t_hash.c Outdated
Comment thread src/t_hash.c Outdated

@ShooterIT ShooterIT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was thinking we should make a more generic dict prefetching API or structure.

Comment thread src/t_hash.c Outdated
@fcostaoliveira

Copy link
Copy Markdown
Collaborator Author

Agreed @ShooterIT — a generic dict batched-prefetch iterator would be useful for SMEMBERS, KEYS, and other dict-scanning commands. Happy to follow up with that once this pattern is validated. For now keeping it scoped to HGETALL where the profiling data shows the biggest win (dictNext at 10.1% flat CPU).

@fcostaoliveira

fcostaoliveira commented Apr 13, 2026

Copy link
Copy Markdown
Collaborator Author

Automated performance analysis summary

This comment was automatically generated given there is performance data available.

Using platform named: arm-aws-m8g.metal-24xl for both baseline and comparison.

Using triggering environment: ci for both baseline and comparison.

In summary:

  • Detected a total of 241 stable tests between versions.
  • Detected a total of 6 improvements above the improvement water line (IMPROVEMENT).
    • The median improvement (IMPROVEMENT) was 14.2%, with values ranging from 7.0% to 44.6%.
    • Quartile distribution: P25=12.9%, P50=14.2%, P75=16.3%.
  • Detected a total of 2 regressions below the regression water line of 3.0 (REGRESSION).
    • The median regression (REGRESSION) was -4.4%, with values ranging from -5.3% to -3.6%.
    • Quartile distribution: P25=-4.8%, P50=-4.4%, P75=-4.0%.

You can check a comparison in detail via the grafana link

Comparison between unstable and 718ae4c.

Time Period from 2 years ago. (environment used: oss-standalone)

By GROUP change csv:

command_group,min_change,q1_change,median_change,q3_change,max_change
sorted-set,-2.017,-0.544,-0.069,0.688,2.412
geo,-1.273,-0.603,-0.471,-0.017,1.050
string,-1.255,-0.315,0.149,0.692,2.810
hash,-3.600,-0.367,0.032,0.541,44.643
generic,-5.256,-0.067,0.225,0.611,7.021
list,-1.410,-0.177,0.196,0.479,1.697
set,-2.737,-0.334,-0.020,0.503,1.597
bitmap,-0.365,-0.066,0.233,0.415,0.597
transactions,0.190,0.190,0.190,0.190,0.190
stream,-0.208,-0.132,0.030,0.098,0.517
scripting,-0.969,-0.796,-0.622,-0.449,-0.276
hyperloglog,0.456,0.456,0.456,0.456,0.456

By COMMAND change csv:

command,min_change,q1_change,median_change,q3_change,max_change
zunionstore,1.302,1.302,1.302,1.302,1.302
zrank,-1.802,-1.676,-1.009,-0.372,-0.334
geosearch,-0.476,-0.472,-0.176,0.352,1.050
set,-1.255,-0.320,0.164,0.521,2.040
get,-1.201,-0.313,0.121,0.470,2.810
hsetex,-1.663,-1.195,-0.227,0.217,1.297
ttl,-0.067,-0.067,-0.067,-0.067,-0.067
mget,-0.570,-0.570,-0.570,-0.570,-0.570
setx,-0.322,-0.065,0.100,0.360,0.903
del,-0.322,-0.065,0.100,0.360,0.903
setex,-0.322,-0.002,0.175,0.482,1.551
lrange,-0.284,-0.003,0.261,0.517,1.209
hgetall,0.008,0.423,12.910,15.694,44.643
sscan,-2.737,-1.739,-0.742,-0.663,-0.583
lpop,0.161,0.194,0.226,0.256,0.285
rpop,0.161,0.194,0.226,0.256,0.285
smembers,-0.537,-0.258,-0.030,0.608,1.026
sdiff,0.804,0.804,0.804,0.804,0.804
hpexpire,-0.164,0.012,0.189,0.366,0.543
hkeys,-3.600,-0.845,0.367,0.451,1.273
hscan,-2.164,-0.804,-0.324,-0.193,0.119
sadd,-0.956,0.065,0.294,0.452,0.935
zrange,-0.556,-0.376,-0.179,0.057,0.356
sismember,-0.266,0.028,0.531,1.101,1.597
geodist,-1.273,-1.035,-0.796,-0.557,-0.319
hgetex,-0.364,-0.358,-0.353,-0.109,0.134
incr,1.110,1.110,1.110,1.110,1.110
scan,-5.256,-1.123,0.596,0.976,7.021
zscore,-0.018,-0.018,-0.018,-0.018,-0.018
getbit,0.597,0.597,0.597,0.597,0.597
hset,-1.969,-0.395,0.105,0.519,2.808
rpush,-1.032,-0.742,-0.452,-0.162,0.128
zscan,0.275,0.809,1.343,1.877,2.412
sunion,-0.030,-0.030,-0.030,-0.030,-0.030
zadd,-0.508,-0.371,-0.095,0.142,1.522
httl,-1.958,-1.958,-1.958,-1.958,-1.958
incrbyfloat,0.098,0.284,0.471,0.657,0.843
lpush,-0.842,-0.811,-0.227,0.416,1.697
zunion,-0.003,-0.003,-0.003,-0.003,-0.003
lindex,0.183,0.401,0.619,0.777,0.935
rpoplpush,-0.285,-0.285,-0.285,-0.285,-0.285
multi,0.190,0.190,0.190,0.190,0.190
exec,0.190,0.190,0.190,0.190,0.190
hsetnx,0.190,0.190,0.190,0.190,0.190
hexists,-0.487,-0.318,-0.149,0.021,0.190
hget,0.190,0.255,0.320,0.385,0.451
hdel,0.190,0.190,0.190,0.190,0.190
xread,-0.175,-0.002,0.171,0.344,0.517
srem,-0.020,-0.020,-0.020,-0.020,-0.020
geopos,-0.876,-0.769,-0.662,-0.408,-0.154
touch,0.550,0.550,0.550,0.550,0.550
hincrby,-0.125,-0.125,-0.125,-0.125,-0.125
incrby,0.761,1.093,1.425,1.756,2.088
hmset,-0.659,-0.659,-0.659,-0.659,-0.659
evalsha,-0.969,-0.969,-0.969,-0.969,-0.969
expire,-0.969,-0.622,-0.276,-0.096,0.083
ping,-0.969,-0.796,-0.622,-0.449,-0.276
decr,-0.036,-0.036,-0.036,-0.036,-0.036
geohash,-0.543,-0.239,0.064,0.368,0.671
setrange,-0.836,-0.385,0.066,0.517,0.967
eval,-0.276,-0.276,-0.276,-0.276,-0.276
lpos,0.026,0.317,0.608,0.899,1.190
bitcount,-0.365,-0.215,-0.066,0.084,0.233
exists,0.225,0.225,0.225,0.225,0.225
zcard,0.953,0.953,0.953,0.953,0.953
zrangestore,0.152,0.313,0.475,0.637,0.798
zrangebyscore,-0.877,-0.701,-0.526,-0.350,-0.175
hexpireat,-0.107,0.027,0.161,0.295,0.429
append,-0.080,0.005,0.089,0.174,0.259
hpexpireat,-0.208,-0.148,-0.088,-0.028,0.032
smismember,-0.144,0.044,0.232,0.420,0.608
zrevrange,1.850,1.901,1.952,2.003,2.054
hmget,-0.009,-0.009,-0.009,-0.009,-0.009
hincrbyfloat,0.593,0.593,0.593,0.593,0.593
zincrby,-1.024,-1.024,-1.024,-1.024,-1.024
hexpire,-0.304,-0.000,0.303,0.607,0.911
zrevrangebyscore,-2.017,-1.258,-0.500,0.258,1.017
psetex,-0.341,-0.341,-0.341,-0.341,-0.341
zrem,-0.597,-0.597,-0.597,-0.597,-0.597
expireat,0.279,0.279,0.279,0.279,0.279
mset,-0.478,-0.420,-0.362,-0.303,-0.245
zrevrank,-0.582,-0.582,-0.582,-0.582,-0.582
llen,0.466,0.466,0.466,0.466,0.466
xadd,-0.208,-0.055,0.030,0.076,0.109
pfadd,0.456,0.456,0.456,0.456,0.456
strlen,-0.547,-0.547,-0.547,-0.547,-0.547
pexpire,0.552,0.552,0.552,0.552,0.552
linsert,-1.410,-1.077,-0.743,-0.410,-0.077
lrem,-1.410,-1.077,-0.743,-0.410,-0.077
sinter,1.026,1.026,1.026,1.026,1.026
hvals,0.451,0.451,0.451,0.451,0.451

#### Regressions Table
Test Case Baseline redis/redis unstable (median obs. +- std.dev) Comparison redis/redis 718ae4c (median obs. +- std.dev) % change (higher-better) Note
memtier_benchmark-1Mkeys-generic-scan-pipeline-10 774867 +- 3.1% (3 datapoints) 734140 -5.3% REGRESSION
memtier_benchmark-1Mkeys-hash-hkeys-5-fields-with-100B-values-with-expiration-pipeline-10 1041505 +- 3.2% (3 datapoints) 1004016 -3.6% REGRESSION

Regressions test regexp names: memtier_benchmark-1Mkeys-generic-scan-pipeline-10|memtier_benchmark-1Mkeys-hash-hkeys-5-fields-with-100B-values-with-expiration-pipeline-10

Improvements Table

Test Case Baseline redis/redis unstable (median obs. +- std.dev) Comparison redis/redis 718ae4c (median obs. +- std.dev) % change (higher-better) Note
memtier_benchmark-10Kkeys-hash-hgetall-200-fields-100B-values 44959 +- 1.1% (3 datapoints) 51874 15.4% IMPROVEMENT
memtier_benchmark-10Kkeys-hash-hgetall-500-fields-100B-values 14968 +- 1.5% (3 datapoints) 21650 44.6% IMPROVEMENT
memtier_benchmark-1key-hash-1K-fields-hgetall 16217 +- 0.1% (3 datapoints) 18296 12.8% IMPROVEMENT
memtier_benchmark-10Kkeys-hash-hgetall-100-fields-100B-values 77327 +- 1.4% (3 datapoints) 87380 13.0% IMPROVEMENT
memtier_benchmark-1Mkeys-generic-scan-type-pipeline-10 702057 +- 4.5% (3 datapoints) 751349 7.0% IMPROVEMENT
memtier_benchmark-1key-hash-1K-fields-hgetall-pipeline-10 15146 +- 0.7% (3 datapoints) 17665 16.6% IMPROVEMENT

Improvements test regexp names: memtier_benchmark-10Kkeys-hash-hgetall-200-fields-100B-values|memtier_benchmark-10Kkeys-hash-hgetall-500-fields-100B-values|memtier_benchmark-1key-hash-1K-fields-hgetall|memtier_benchmark-10Kkeys-hash-hgetall-100-fields-100B-values|memtier_benchmark-1Mkeys-generic-scan-type-pipeline-10|memtier_benchmark-1key-hash-1K-fields-hgetall-pipeline-10

Full Results table:
Test Case Baseline redis/redis unstable (median obs. +- std.dev) Comparison redis/redis 718ae4c (median obs. +- std.dev) % change (higher-better) Note
memtier_benchmark-2keys-zset-300-elements-skiplist-encoded-zunionstore 7460 +- 0.6% (3 datapoints) 7557 1.3% No Change
memtier_benchmark-1key-zrank-1M-elements-pipeline-1 66713 +- 0.4% (3 datapoints) 65623 -1.6% No Change
memtier_benchmark-1key-geo-60M-elements-geosearch-fromlonlat-bybox 204458 +- 0.4% (3 datapoints) 203495 -0.5% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-512B-pipeline-10 909627 +- 0.2% (3 datapoints) 916489 0.8% No Change
memtier_benchmark-100Kkeys-load-hash-5-fields-with-10B-values-long-expiration 150135 +- 0.5% (3 datapoints) 148341 -1.2% No Change
memtier_benchmark-1Mkeys-string-get-10B 230293 +- 0.4% (3 datapoints) 229029 -0.5% No Change
memtier_benchmark-1Mkeys-string-get-10B-pipeline-100-nokeyprefix 3152833 +- 0.2% (3 datapoints) 3173980 0.7% No Change
memtier_benchmark-1Mkeys-generic-ttl-pipeline-10 1459516 +- 0.4% (3 datapoints) 1458540 -0.1% No Change
memtier_benchmark-1Mkeys-string-mget-1KiB 151912 +- 0.2% (3 datapoints) 151046 -0.6% No Change
memtier_benchmark-1Mkeys-10B-expire-use-case 236577 +- 0.1% (3 datapoints) 235815 -0.3% No Change
memtier_benchmark-1key-list-2K-elements-quicklist-lrange-all-elements-longs 14521 +- 0.4% (3 datapoints) 14521 -0.0% No Change
memtier_benchmark-1Mkeys-hash-hgetall-50-fields-10B-values 212867 +- 0.7% (3 datapoints) 212883 0.0% No Change
memtier_benchmark-1key-set-1K-elements-sscan 195134 +- 1.8% (3 datapoints) 189793 -2.7% No Change
memtier_benchmark-1Mkeys-list-lpop-rpop-with-10B-values 217667 +- 1.5% (3 datapoints) 218019 0.2% No Change
memtier_benchmark-1key-list-100-elements-int-lrange-all-elements-pipeline-10 244031 +- 0.8% (3 datapoints) 244539 0.2% No Change
memtier_benchmark-2keys-set-10-100-elements-sdiff 48800 +- 0.3% (3 datapoints) 49193 0.8% No Change
memtier_benchmark-10Kkeys-hash-hgetall-200-fields-100B-values 44959 +- 1.1% (3 datapoints) 51874 15.4% IMPROVEMENT
memtier_benchmark-100Kkeys-hash-hpexpire-5-fields-10B-values 165834 +- 0.6% (3 datapoints) 166734 0.5% No Change
memtier_benchmark-1Mkeys-hash-hkeys-10-fields-with-10B-values-with-expiration-pipeline-10 849580 +- 0.2% (3 datapoints) 852700 0.4% No Change
memtier_benchmark-1key-hash-hscan-50-fields-10B-values 149191 +- 1.7% (3 datapoints) 148668 -0.4% No Change
memtier_benchmark-1Mkeys-load-set-intset-with-100-elements 99186 +- 0.3% (3 datapoints) 98238 -1.0% No Change
memtier_benchmark-1Mkeys-string-get-10B-pipeline-50 2550631 +- 0.1% (3 datapoints) 2550798 0.0% No Change
memtier_benchmark-1key-zrank-10M-elements-pipeline-1 62731 +- 1.0% (3 datapoints) 62522 -0.3% No Change
memtier_benchmark-3Mkeys-load-string-with-512B-values-pipeline-10 923844 +- 0.2% (3 datapoints) 926464 0.3% No Change
memtier_benchmark-1key-zset-100-elements-zrange-all-elements 55366 +- 0.0% (3 datapoints) 55342 -0.0% No Change
memtier_benchmark-1Mkeys-string-setget200c-512B-pipeline-1 210691 +- 0.4% (3 datapoints) 209846 -0.4% No Change
memtier_benchmark-1key-set-100-elements-sismember-is-a-member 219476 +- 0.3% (3 datapoints) 218892 -0.3% No Change
memtier_benchmark-1key-geo-60M-elements-geodist-pipeline-10 1518002 +- 0.2% (3 datapoints) 1513163 -0.3% No Change
memtier_benchmark-100Kkeys-hash-hgetex-persist-50-fields-10B-values 38464 +- 0.1% (3 datapoints) 38324 -0.4% No Change
memtier_benchmark-1Mkeys-string-incr-pipeline-10 1386487 +- 1.1% (3 datapoints) 1401876 1.1% No Change
memtier_benchmark-1Mkeys-generic-scan-cursor-count-500-pipeline-10 10915 +- 2.1% (3 datapoints) 11007 0.8% No Change
memtier_benchmark-1Mkeys-generic-scan-count-50-incremental-iteration 103814 +- 0.8% (3 datapoints) 101791 -1.9% No Change
memtier_benchmark-1Mkeys-generic-scan-cursor-count-5000-pipeline-10 1032 +- 0.4% (3 datapoints) 1029 -0.3% No Change
memtier_benchmark-1key-zset-1M-elements-zscore-pipeline-10 1315716 +- 0.3% (3 datapoints) 1315476 -0.0% No Change
memtier_benchmark-1key-zset-10-elements-zrange-all-elements-long-scores 167908 +- 0.3% (3 datapoints) 167379 -0.3% No Change
memtier_benchmark-1Mkeys-load-string-with-10B-values-pipeline-500 2183039 +- 1.6% (3 datapoints) 2166312 -0.8% No Change
memtier_benchmark-1Mkeys-bitmap-getbit-pipeline-10 2413038 +- 0.4% (3 datapoints) 2427452 0.6% No Change
memtier_benchmark-100Kkeys-load-hash-1-fields-with-10B-values-long-expiration 191771 +- 1.6% (3 datapoints) 192187 0.2% No Change
memtier_benchmark-1Mkeys-generic-scan-pipeline-10 774867 +- 3.1% (3 datapoints) 734140 -5.3% REGRESSION
memtier_benchmark-1Mkeys-string-get-32B-pipeline-10 1471382 +- 0.8% (3 datapoints) 1485622 1.0% No Change
memtier_benchmark-1Mkeys-load-hash-5-fields-with-1000B-values 124625 +- 0.7% (3 datapoints) 125300 0.5% No Change
memtier_benchmark-100Kkeys-load-hash-50-fields-with-10B-values-expiration 23014 +- 0.0% (3 datapoints) 22962 -0.2% No Change
memtier_benchmark-10Kkeys-load-list-rpush-bulkload-pipeline-50 142962 +- 0.4% (3 datapoints) 143145 0.1% No Change
memtier_benchmark-1key-list-100-elements-lrange-all-elements 154642 +- 0.3% (3 datapoints) 154203 -0.3% No Change
memtier_benchmark-1Mkeys-generic-scan-count-10-incremental-iteration 197010 +- 0.3% (3 datapoints) 192023 -2.5% No Change
memtier_benchmark-1Mkeys-list-lpop-rpop-with-1KiB-values 218283 +- 1.1% (3 datapoints) 218777 0.2% No Change
memtier_benchmark-1key-zset-100-elements-zscan 109667 +- 0.1% (3 datapoints) 109968 0.3% No Change
memtier_benchmark-2keys-set-10-100-elements-sunion 62794 +- 0.3% (3 datapoints) 62775 -0.0% No Change
memtier_benchmark-1Mkeys-load-zset-with-10-elements-int-score 159326 +- 0.4% (3 datapoints) 159552 0.1% No Change
memtier_benchmark-100Kkeys-hash-htll-50-fields-10B-values 59172 +- 1.2% (3 datapoints) 58014 -2.0% No Change
memtier_benchmark-10Mkeys-string-get-10B-pipeline-100-nokeyprefix 3229264 +- 0.2% (3 datapoints) 3221200 -0.2% No Change
memtier_benchmark-1key-set-1M-elements-sismember-50pct-chance 223145 +- 0.3% (3 datapoints) 223427 0.1% No Change
memtier_benchmark-1Mkeys-load-string-with-10B-values-pipeline-100-nokeyprefix 2238516 +- 1.4% (3 datapoints) 2280355 1.9% No Change
memtier_benchmark-100Kkeys-load-hash-50-fields-with-10B-values 56792 +- 0.3% (3 datapoints) 56811 0.0% No Change
memtier_benchmark-1Mkeys-load-string-with-100B-values 202078 +- 0.5% (3 datapoints) 202338 0.1% No Change
memtier_benchmark-1Mkeys-string-incrbyfloat 190432 +- 0.4% (3 datapoints) 190619 0.1% No Change
memtier_benchmark-1Mkeys-load-list-rpush-with-10B-values 200795 +- 0.0% (3 datapoints) 198724 -1.0% No Change
memtier_benchmark-100Kkeys-load-hash-1-fields-with-10B-values-short-expiration 181338 +- 0.6% (3 datapoints) 178689 -1.5% No Change
memtier_benchmark-1Mkeys-load-zset-with-10-elements-double-score 149908 +- 0.4% (3 datapoints) 149351 -0.4% No Change
memtier_benchmark-1Mkeys-1KiB-expire-use-case 228400 +- 0.7% (3 datapoints) 230463 0.9% No Change
memtier_benchmark-1Mkeys-load-list-with-10B-values-pipeline-10 1071817 +- 0.9% (3 datapoints) 1076276 0.4% No Change
memtier_benchmark-2keys-zset-300-elements-skiplist-encoded-zunion 6721 +- 0.6% (3 datapoints) 6721 -0.0% No Change
memtier_benchmark-100Kkeys-load-hash-50-fields-with-1000B-values-expiration 18513 +- 0.4% (3 datapoints) 18443 -0.4% No Change
memtier_benchmark-1key-list-10K-elements-lindex-integer 193837 +- 0.3% (3 datapoints) 195038 0.6% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-1KB-pipeline-10 730096 +- 0.5% (3 datapoints) 733524 0.5% No Change
memtier_benchmark-1Mkeys-list-rpoplpush-with-10B-values 212273 +- 0.6% (3 datapoints) 211667 -0.3% No Change
memtier_benchmark-10Kkeys-load-hash-50-fields-with-10000B-values 5023 +- 0.4% (3 datapoints) 5029 0.1% No Change
memtier_benchmark-1Mkeys-hash-transactions-multi-exec-pipeline-20 1704762 +- 1.5% (3 datapoints) 1708001 0.2% No Change
memtier_benchmark-1Mkeys-load-list-with-100B-values 188828 +- 0.3% (3 datapoints) 187296 -0.8% No Change
memtier_benchmark-1key-set-2M-elements-sadd-increasing 219001 +- 0.3% (3 datapoints) 220351 0.6% No Change
memtier_benchmark-2keys-stream-5-entries-xread-all-entries-pipeline-10 235354 +- 0.1% (3 datapoints) 234943 -0.2% No Change
memtier_benchmark-1key-set-10M-elements-srem-50pct-chance 219444 +- 0.6% (3 datapoints) 219400 -0.0% No Change
memtier_benchmark-1key-geo-2-elements-geopos 207525 +- 0.4% (3 datapoints) 205707 -0.9% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-32B 209750 +- 0.4% (3 datapoints) 208957 -0.4% No Change
memtier_benchmark-1key-hash-hscan-1K-fields-10B-values-cursor-count-100 70755 +- 0.5% (3 datapoints) 70839 0.1% No Change
memtier_benchmark-1Mkeys-load-set-intset-with-100-elements-19-digits 55171 +- 0.2% (3 datapoints) 55283 0.2% No Change
memtier_benchmark-10Kkeys-hash-hgetall-500-fields-100B-values 14968 +- 1.5% (3 datapoints) 21650 44.6% IMPROVEMENT
memtier_benchmark-1Mkeys-100B-expire-use-case 235749 +- 0.2% (3 datapoints) 236169 0.2% No Change
memtier_benchmark-1Mkeys-generic-touch-pipeline-10 1481450 +- 0.0% (3 datapoints) 1489603 0.6% No Change
memtier_benchmark-3Mkeys-load-string-with-512B-values 183095 +- 0.2% (3 datapoints) 180796 -1.3% No Change
memtier_benchmark-1Mkeys-hash-hincrby 235832 +- 0.5% (3 datapoints) 235536 -0.1% No Change
memtier_benchmark-1Mkeys-string-incrby 222144 +- 0.6% (3 datapoints) 223835 0.8% No Change
memtier_benchmark-1key-hash-hscan-1K-fields-10B-values 185253 +- 2.2% (3 datapoints) 181245 -2.2% No Change
memtier_benchmark-1key-zset-1K-elements-zscan 113094 +- 2.5% (3 datapoints) 115821 2.4% No Change
memtier_benchmark-1Mkeys-load-hash-hmset-5-fields-with-1000B-values 125375 +- 1.3% (3 datapoints) 124548 -0.7% No Change
memtier_benchmark-2keys-lua-evalsha-hset-expire 149251 +- 0.7% (3 datapoints) 147805 -1.0% No Change
memtier_benchmark-1Mkeys-string-decr 221669 +- 0.2% (3 datapoints) 221589 -0.0% No Change
memtier_benchmark-10Mkeys-load-hash-5-fields-with-10B-values-pipeline-10 671675 +- 0.3% (3 datapoints) 668219 -0.5% No Change
memtier_benchmark-1key-geo-60M-elements-geodist 228964 +- 1.8% (3 datapoints) 226049 -1.3% No Change
memtier_benchmark-1Mkeys-string-setex-100B-pipeline-10 922551 +- 0.7% (3 datapoints) 936857 1.6% No Change
memtier_benchmark-1key-geo-60M-elements-geohash-pipeline-10 1558988 +- 0.4% (3 datapoints) 1569455 0.7% No Change
memtier_benchmark-1key-set-10M-elements-sismember-50pct-chance 218781 +- 1.3% (3 datapoints) 220827 0.9% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-with-expiration-240B-400_conns 202170 +- 0.3% (3 datapoints) 202218 0.0% No Change
memtier_benchmark-1key-geo-60M-elements-geosearch-fromlonlat 205846 +- 0.3% (3 datapoints) 206091 0.1% No Change
memtier_benchmark-1key-list-100-elements-lrange-all-elements-pipeline-10 296488 +- 0.6% (3 datapoints) 299774 1.1% No Change
memtier_benchmark-1Mkeys-load-hash-50-fields-with-10B-values-long-expiration-pipeline-10 25946 +- 0.5% (3 datapoints) 26184 0.9% No Change
memtier_benchmark-100Kkeys-hash-hgetall-50-fields-100B-values 205824 +- 0.4% (3 datapoints) 206526 0.3% No Change
memtier_benchmark-1Mkeys-string-incrbyfloat-pipeline-10 686459 +- 0.6% (3 datapoints) 692246 0.8% No Change
memtier_benchmark-1Mkeys-load-string-with-10B-values-pipeline-100 2013377 +- 1.2% (3 datapoints) 2036420 1.1% No Change
memtier_benchmark-1Mkeys-generic-scan-count-500-pipeline-10 27149 +- 0.6% (3 datapoints) 27770 2.3% No Change
memtier_benchmark-1Mkeys-string-get-32B 230683 +- 0.4% (3 datapoints) 230406 -0.1% No Change
memtier_benchmark-1Mkeys-generic-expire-pipeline-10 1385962 +- 0.1% (3 datapoints) 1387112 0.1% No Change
memtier_benchmark-1key-hash-1K-fields-hgetall 16217 +- 0.1% (3 datapoints) 18296 12.8% IMPROVEMENT
memtier_benchmark-1Mkeys-load-string-with-100B-values-pipeline-10 1144258 +- 0.5% (3 datapoints) 1137616 -0.6% No Change
memtier_benchmark-1key-list-1K-elements-lrange-all-elements 37094 +- 0.4% (3 datapoints) 37191 0.3% No Change
memtier_benchmark-1Mkeys-string-setrange-100B 216258 +- 0.3% (3 datapoints) 214450 -0.8% No Change
memtier_benchmark-10Kkeys-hash-hgetall-100-fields-100B-values 77327 +- 1.4% (3 datapoints) 87380 13.0% IMPROVEMENT
memtier_benchmark-100Kkeys-load-hash-50-fields-with-10B-values-long-expiration 22998 +- 0.1% (3 datapoints) 23000 0.0% No Change
memtier_benchmark-2keys-lua-eval-hset-expire 129946 +- 0.8% (3 datapoints) 129588 -0.3% No Change
memtier_benchmark-1key-set-100-elements-sismember-not-a-member 212533 +- 1.2% (3 datapoints) 215926 1.6% No Change
memtier_benchmark-1key-list-10K-elements-lpos-integer 16205 +- 0.3% (3 datapoints) 16398 1.2% No Change
memtier_benchmark-1key-list-100-elements-int-7bit-uint-lrange-all-elements-pipeline-10 322260 +- 0.6% (3 datapoints) 326157 1.2% No Change
memtier_benchmark-1key-zrank-100K-elements-pipeline-1 69783 +- 1.2% (3 datapoints) 68526 -1.8% No Change
memtier_benchmark-1Mkeys-4KiB-expire-use-case 211480 +- 0.4% (3 datapoints) 211525 0.0% No Change
memtier_benchmark-1key-1Billion-bits-bitmap-bitcount 3770 +- 0.1% (3 datapoints) 3779 0.2% No Change
memtier_benchmark-1Mkeys-generic-exists-pipeline-10 1513314 +- 0.3% (3 datapoints) 1516716 0.2% No Change
memtier_benchmark-1key-list-10K-elements-lindex-string-pipeline-10 521444 +- 0.3% (3 datapoints) 526321 0.9% No Change
memtier_benchmark-1key-list-10-elements-lrange-all-elements 208529 +- 0.4% (3 datapoints) 208194 -0.2% No Change
memtier_benchmark-1key-zset-1M-elements-zcard-pipeline-10 1515947 +- 0.1% (3 datapoints) 1530387 1.0% No Change
memtier_benchmark-1key-zset-600K-elements-zrangestore-1K-elements 5235 +- 0.4% (3 datapoints) 5277 0.8% No Change
memtier_benchmark-1key-zset-100-elements-zrangebyscore-all-elements-long-scores 89520 +- 1.8% (3 datapoints) 88734 -0.9% No Change
memtier_benchmark-100Kkeys-hash-hpexpire-50-fields-10B-values 32304 +- 0.0% (3 datapoints) 32251 -0.2% No Change
memtier_benchmark-100Kkeys-load-hash-20-fields-with-1B-values-pipeline-30 56759 +- 0.3% (3 datapoints) 56960 0.4% No Change
memtier_benchmark-1Mkeys-string-setget2000c-1KiB-pipeline-16 848511 +- 0.3% (3 datapoints) 848738 0.0% No Change
memtier_benchmark-100Kkeys-load-hash-50-fields-with-10B-values-short-expiration 23262 +- 0.4% (3 datapoints) 23249 -0.1% No Change
memtier_benchmark-1Mkeys-string-get-10B-pipeline-100 2847888 +- 0.1% (3 datapoints) 2866027 0.6% No Change
memtier_benchmark-100Kkeys-hash-hexpireat-5-fields-10B-values 165296 +- 0.4% (3 datapoints) 166005 0.4% No Change
memtier_benchmark-1Mkeys-10B-setex-expire-use-case 227569 +- 0.2% (3 datapoints) 227409 -0.1% No Change
memtier_benchmark-100Kkeys-hash-hgetex-50-fields-10B-values 23035 +- 0.0% (3 datapoints) 22954 -0.4% No Change
memtier_benchmark-1Mkeys-string-set-get-short-expiration-512B 556556 +- 0.2% (3 datapoints) 555645 -0.2% No Change
memtier_benchmark-1key-load-zset-with-5-elements-parsing-float-score 196016 +- 0.2% (3 datapoints) 195021 -0.5% No Change
memtier_benchmark-1Mkeys-string-get-10B-pipeline-500 3153392 +- 0.2% (3 datapoints) 3159806 0.2% No Change
memtier_benchmark-1Mkeys-string-append-1-100B 214398 +- 0.3% (3 datapoints) 214952 0.3% No Change
memtier_benchmark-1key-set-10-elements-smembers-pipeline-10 1111561 +- 0.3% (3 datapoints) 1108697 -0.3% No Change
memtier_benchmark-1key-hash-hscan-1K-fields-100B-values-cursor-count-1000 14302 +- 0.7% (3 datapoints) 14260 -0.3% No Change
memtier_benchmark-1key-geo-2-elements-geosearch-fromlonlat-withcoord 147362 +- 0.5% (3 datapoints) 146659 -0.5% No Change
memtier_benchmark-1key-zset-1K-elements-zrange-all-elements 10898 +- 0.2% (3 datapoints) 10837 -0.6% No Change
memtier_benchmark-1Mkeys-generic-scan-type-pipeline-10 702057 +- 4.5% (3 datapoints) 751349 7.0% IMPROVEMENT
memtier_benchmark-1Mkeys-load-string-with-1KiB-values-pipeline-10 821575 +- 0.2% (3 datapoints) 825999 0.5% No Change
memtier_benchmark-10Mkeys-load-hash-5-fields-with-100B-values-pipeline-10 522688 +- 0.6% (3 datapoints) 537363 2.8% No Change
memtier_benchmark-1key-set-100-elements-smembers 147675 +- 0.5% (3 datapoints) 147718 0.0% No Change
memtier_benchmark-1Mkeys-load-string-with-1KiB-values 189585 +- 0.6% (3 datapoints) 189881 0.2% No Change
memtier_benchmark-1Mkeys-string-get-1KiB 201393 +- 0.4% (3 datapoints) 207052 2.8% No Change
memtier_benchmark-1Mkeys-load-string-with-10B-values 208074 +- 1.3% (3 datapoints) 211005 1.4% No Change
memtier_benchmark-1Mkeys-string-setget200c-4KiB-pipeline-10 354983 +- 0.4% (3 datapoints) 352854 -0.6% No Change
memtier_benchmark-1key-set-100-elements-sscan 142812 +- 0.2% (3 datapoints) 141979 -0.6% No Change
memtier_benchmark-100Kkeys-hash-hpexpireat-50-fields-10B-values 33601 +- 0.1% (3 datapoints) 33531 -0.2% No Change
memtier_benchmark-1key-load-zset-with-5-elements-parsing-hexa-score 177705 +- 0.4% (3 datapoints) 177536 -0.1% No Change
memtier_benchmark-1key-list-10K-elements-lpos-string 18034 +- 0.1% (3 datapoints) 18039 0.0% No Change
memtier_benchmark-2keys-stream-5-entries-xread-all-entries 122058 +- 0.4% (3 datapoints) 122689 0.5% No Change
memtier_benchmark-1Mkeys-string-setget200c-1KiB-pipeline-1 206858 +- 0.1% (3 datapoints) 205770 -0.5% No Change
memtier_benchmark-1Mkeys-load-string-with-10B-values-pipeline-50 1838292 +- 0.9% (3 datapoints) 1862692 1.3% No Change
memtier_benchmark-1key-list-10K-elements-lindex-string 176725 +- 1.1% (3 datapoints) 177049 0.2% No Change
memtier_benchmark-1Mkeys-list-lpop-rpop-with-100B-values 215979 +- 0.1% (3 datapoints) 216596 0.3% No Change
memtier_benchmark-1key-load-hash-1K-fields-with-5B-values 7328 +- 0.2% (3 datapoints) 7364 0.5% No Change
memtier_benchmark-10Kkeys-load-list-with-10B-values-pipeline-50 1284178 +- 1.2% (3 datapoints) 1305971 1.7% No Change
memtier_benchmark-1Mkeys-load-hash-5-fields-with-1000B-values-pipeline-10 204699 +- 0.9% (3 datapoints) 207403 1.3% No Change
memtier_benchmark-1key-set-10-elements-smembers 212019 +- 0.4% (3 datapoints) 211167 -0.4% No Change
memtier_benchmark-1key-set-10-elements-smismember 220883 +- 0.8% (3 datapoints) 222226 0.6% No Change
memtier_benchmark-1key-geo-60M-elements-geosearch-fromlonlat-pipeline-10 1041504 +- 0.3% (3 datapoints) 1052440 1.1% No Change
memtier_benchmark-1key-zset-1M-elements-zrevrange-5-elements 210920 +- 0.8% (3 datapoints) 214822 1.8% No Change
memtier_benchmark-1Mkeys-string-set-with-ex-100B-pipeline-10 919298 +- 0.5% (3 datapoints) 931626 1.3% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-100B-expire-pipeline-10 978018 +- 0.8% (3 datapoints) 981353 0.3% No Change
memtier_benchmark-1Mkeys-load-string-with-20KiB-values 95406 +- 0.4% (3 datapoints) 95609 0.2% No Change
memtier_benchmark-1Mkeys-hash-hkeys-50-fields-with-10B-values-with-expiration-pipeline-10 332362 +- 0.2% (3 datapoints) 329555 -0.8% No Change
memtier_benchmark-1key-set-100-elements-smismember 204528 +- 0.4% (3 datapoints) 204233 -0.1% No Change
memtier_benchmark-1Mkeys-hash-hmget-5-fields-with-100B-values-pipeline-10 1075301 +- 0.6% (3 datapoints) 1075207 -0.0% No Change
memtier_benchmark-1Mkeys-generic-scan-cursor-pipeline-10 410604 +- 1.2% (3 datapoints) 415160 1.1% No Change
memtier_benchmark-10Mkeys-load-hash-5-fields-with-10B-values 172503 +- 0.9% (3 datapoints) 169106 -2.0% No Change
memtier_benchmark-1Mkeys-string-get-10B-pipeline-10 1378455 +- 0.2% (3 datapoints) 1380408 0.1% No Change
memtier_benchmark-100Kkeys-load-hash-5-fields-with-10B-values-expiration 150460 +- 1.1% (3 datapoints) 147959 -1.7% No Change
memtier_benchmark-1Mkeys-hash-hincrbyfloat 203530 +- 0.6% (3 datapoints) 204736 0.6% No Change
memtier_benchmark-1Mkeys-string-get-100B 224677 +- 0.6% (3 datapoints) 230976 2.8% No Change
memtier_benchmark-100Kkeys-hash-hexpireat-50-fields-10B-values 33288 +- 0.8% (3 datapoints) 33252 -0.1% No Change
memtier_benchmark-1Mkeys-string-setget200c-4KiB-pipeline-1 171846 +- 0.4% (3 datapoints) 171372 -0.3% No Change
memtier_benchmark-1key-zincrby-1M-elements-pipeline-1 65494 +- 0.6% (3 datapoints) 64823 -1.0% No Change
memtier_benchmark-1Mkeys-load-list-with-1KiB-values 140865 +- 0.3% (3 datapoints) 139680 -0.8% No Change
memtier_benchmark-1key-zset-10-elements-zrange-all-elements 150114 +- 0.1% (3 datapoints) 150648 0.4% No Change
memtier_benchmark-1Mkeys-string-append-1-100B-pipeline-10 1138075 +- 0.6% (3 datapoints) 1137167 -0.1% No Change
memtier_benchmark-1key-zset-1M-elements-zrevrange-withscores-5-elements-pipeline-10 883379 +- 0.2% (3 datapoints) 901526 2.1% No Change
memtier_benchmark-100Kkeys-hash-hexpire-5-fields-10B-values 165242 +- 0.4% (3 datapoints) 166747 0.9% No Change
memtier_benchmark-1Mkeys-generic-scan-count-10-incremental-iteration-high-cursor-count 175929 +- 0.3% (3 datapoints) 177005 0.6% No Change
memtier_benchmark-1key-zrevrangebyscore-256K-elements-pipeline-10 252323 +- 1.0% (3 datapoints) 254888 1.0% No Change
memtier_benchmark-100Kkeys-load-hash-5-fields-with-10B-values-short-expiration 140177 +- 0.6% (3 datapoints) 138192 -1.4% No Change
memtier_benchmark-1key-set-1K-elements-sscan-cursor-count-100 106921 +- 0.5% (3 datapoints) 106128 -0.7% No Change
memtier_benchmark-1Mkeys-10B-psetex-expire-use-case 227581 +- 0.3% (3 datapoints) 226805 -0.3% No Change
memtier_benchmark-1key-zrem-5M-elements-pipeline-1 64735 +- 0.7% (3 datapoints) 64349 -0.6% No Change
memtier_benchmark-10Mkeys-load-hash-5-fields-with-100B-values 159920 +- 0.6% (3 datapoints) 160088 0.1% No Change
memtier_benchmark-100Kkeys-hash-hgetex-5-fields-10B-values 154237 +- 0.8% (3 datapoints) 154444 0.1% No Change
memtier_benchmark-1Mkeys-generic-expireat-pipeline-10 1361902 +- 0.9% (3 datapoints) 1365702 0.3% No Change
memtier_benchmark-100Kkeys-load-hash-50-fields-with-1000B-values 26962 +- 2.2% (3 datapoints) 27429 1.7% No Change
memtier_benchmark-1Mkeys-load-string-mset-10-keys-with-100B-values 139590 +- 0.7% (3 datapoints) 138923 -0.5% No Change
memtier_benchmark-100Kkeys-load-hash-5-fields-with-1000B-values-expiration 118079 +- 0.4% (3 datapoints) 119104 0.9% No Change
memtier_benchmark-100Kkeys-load-hash-1-fields-with-10B-values-expiration 193302 +- 0.6% (3 datapoints) 191599 -0.9% No Change
memtier_benchmark-1Mkeys-generic-scan-count-500-incremental-iteration 18545 +- 4.8% (3 datapoints) 18655 0.6% No Change
memtier_benchmark-1key-zrevrank-1M-elements-pipeline-1 66886 +- 1.1% (3 datapoints) 66496 -0.6% No Change
memtier_benchmark-1key-list-10-elements-lrange-all-elements-pipeline-10 1006654 +- 0.1% (3 datapoints) 1011855 0.5% No Change
memtier_benchmark-1key-zset-listpack-zrank-100-elements-pipeline-1 201918 +- 0.2% (3 datapoints) 201141 -0.4% No Change
memtier_benchmark-1Mkeys-load-zset-listpack-with-100-elements-double-score 6413 +- 0.8% (3 datapoints) 6511 1.5% No Change
memtier_benchmark-1Mkeys-string-setrange-100B-pipeline-10 1136935 +- 1.1% (3 datapoints) 1147933 1.0% No Change
memtier_benchmark-1key-list-100-elements-llen-pipeline-10 1531416 +- 0.6% (3 datapoints) 1538555 0.5% No Change
memtier_benchmark-1Mkeys-string-setget2000c-1KiB-pipeline-10 710825 +- 0.4% (3 datapoints) 704733 -0.9% No Change
memtier_benchmark-1Mkeys-load-stream-1-fields-with-100B-values 159687 +- 0.4% (3 datapoints) 159790 0.1% No Change
memtier_benchmark-1Mkeys-hash-hkeys-5-fields-with-10B-values-with-expiration-pipeline-10 1015916 +- 0.9% (3 datapoints) 1028848 1.3% No Change
memtier_benchmark-1Mkeys-load-stream-1-fields-with-100B-values-pipeline-10 604017 +- 0.0% (3 datapoints) 604674 0.1% No Change
memtier_benchmark-1key-hash-1K-fields-hgetall-pipeline-10 15146 +- 0.7% (3 datapoints) 17665 16.6% IMPROVEMENT
memtier_benchmark-1key-zset-600K-elements-zrangestore-300K-elements 13 +- 0.1% (3 datapoints) 13 0.2% No Change
memtier_benchmark-1Mkeys-load-list-with-10B-values 200469 +- 0.5% (3 datapoints) 200013 -0.2% No Change
memtier_benchmark-1key-pfadd-4KB-values-pipeline-10 394283 +- 0.2% (3 datapoints) 396080 0.5% No Change
memtier_benchmark-1key-geo-60M-elements-geopos-pipeline-10 1575528 +- 0.1% (3 datapoints) 1573106 -0.2% No Change
memtier_benchmark-1Mkeys-load-string-with-10B-values-pipeline-10 1132525 +- 0.8% (3 datapoints) 1134881 0.2% No Change
memtier_benchmark-1Mkeys-hash-hkeys-5-fields-with-100B-values-with-expiration-pipeline-10 1041505 +- 3.2% (3 datapoints) 1004016 -3.6% REGRESSION
memtier_benchmark-1Mkeys-string-int-encoding-strlen-pipeline-10 1432075 +- 0.3% (3 datapoints) 1424245 -0.5% No Change
memtier_benchmark-1key-set-1K-elements-smembers 34057 +- 0.6% (3 datapoints) 33874 -0.5% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-100B-pipeline-10 1085175 +- 0.2% (3 datapoints) 1091419 0.6% No Change
memtier_benchmark-1key-geo-60M-elements-geopos 228587 +- 0.5% (3 datapoints) 227074 -0.7% No Change
memtier_benchmark-1Mkeys-string-incrby-pipeline-10 1304462 +- 0.7% (3 datapoints) 1331702 2.1% No Change
memtier_benchmark-100Kkeys-hash-hexpire-50-fields-10B-values 32312 +- 0.1% (3 datapoints) 32214 -0.3% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-512B 198609 +- 1.2% (3 datapoints) 196224 -1.2% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-32B-pipeline-10 1097568 +- 0.3% (3 datapoints) 1098902 0.1% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-100B-expire 197726 +- 0.3% (3 datapoints) 198067 0.2% No Change
memtier_benchmark-100Kkeys-load-hash-1-fields-with-1000B-values-expiration 173974 +- 1.1% (3 datapoints) 176231 1.3% No Change
memtier_benchmark-1Mkeys-string-setget200c-1KiB-pipeline-10 804322 +- 0.1% (3 datapoints) 806377 0.3% No Change
memtier_benchmark-1Mkeys-generic-pexpire-pipeline-10 1370644 +- 0.2% (3 datapoints) 1378216 0.6% No Change
memtier_benchmark-1Mkeys-load-stream-5-fields-with-100B-values 140880 +- 0.6% (3 datapoints) 140875 -0.0% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-100B 206540 +- 0.2% (3 datapoints) 210755 2.0% No Change
memtier_benchmark-1key-list-10K-elements-linsert-lrem-integer 18259 +- 0.3% (3 datapoints) 18001 -1.4% No Change
memtier_benchmark-1key-geo-60M-elements-geohash 228936 +- 0.7% (3 datapoints) 227693 -0.5% No Change
memtier_benchmark-1key-100M-bits-bitmap-bitcount 48569 +- 0.5% (3 datapoints) 48392 -0.4% No Change
memtier_benchmark-1key-list-1K-elements-lrange-all-elements-pipeline-10 35570 +- 0.1% (3 datapoints) 35684 0.3% No Change
memtier_benchmark-1Mkeys-string-setget200c-512B-pipeline-10 926205 +- 0.3% (3 datapoints) 929601 0.4% No Change
memtier_benchmark-1Mkeys-generic-scan-count-100-incremental-iteration 66000 +- 0.4% (3 datapoints) 65959 -0.1% No Change
memtier_benchmark-1key-zset-100-elements-zrangebyscore-all-elements 55544 +- 0.2% (3 datapoints) 55447 -0.2% No Change
memtier_benchmark-1Mkeys-load-set-intset-with-100-elements-pipeline-10 148432 +- 0.7% (3 datapoints) 149004 0.4% No Change
memtier_benchmark-1Mkeys-string-get-100B-pipeline-10 1347339 +- 1.3% (3 datapoints) 1349484 0.2% No Change
memtier_benchmark-1Mkeys-string-get-1KiB-pipeline-10 784271 +- 0.1% (3 datapoints) 781540 -0.3% No Change
memtier_benchmark-2keys-set-10-100-elements-sinter 126824 +- 1.7% (3 datapoints) 128126 1.0% No Change
memtier_benchmark-1key-set-200K-elements-sadd-constant 223460 +- 0.6% (3 datapoints) 223190 -0.1% No Change
memtier_benchmark-100Kkeys-load-hash-50-fields-with-100B-values 77965 +- 1.0% (3 datapoints) 77529 -0.6% No Change
memtier_benchmark-100Kkeys-hash-hpexpireat-5-fields-10B-values 168526 +- 0.3% (3 datapoints) 168580 0.0% No Change
memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-1KB 193864 +- 0.5% (3 datapoints) 193257 -0.3% No Change
memtier_benchmark-1Mkeys-load-stream-5-fields-with-100B-values-pipeline-10 366539 +- 0.5% (3 datapoints) 365776 -0.2% No Change
memtier_benchmark-1key-zrevrangebyscore-256K-elements-pipeline-1 129133 +- 0.5% (3 datapoints) 126529 -2.0% No Change
memtier_benchmark-1key-list-10K-elements-linsert-lrem-string 21303 +- 0.1% (3 datapoints) 21286 -0.1% No Change
memtier_benchmark-1Mkeys-hash-hexists 224772 +- 0.3% (3 datapoints) 223676 -0.5% No Change
memtier_benchmark-1Mkeys-hash-hget-hgetall-hkeys-hvals-with-100B-values 220008 +- 0.4% (3 datapoints) 220999 0.5% No Change
memtier_benchmark-1Mkeys-load-string-mset-10-keys-with-10B-values 146495 +- 0.3% (3 datapoints) 146135 -0.2% No Change
memtier_benchmark-1Kkeys-hash-listpack-500-fields-update-20-fields-with-1B-to-64B-values 82454 +- 0.5% (3 datapoints) 82497 0.1% No Change
memtier_benchmark-1Mkeys-load-set-intset-with-100-elements-19-digits-pipeline-10 66517 +- 0.2% (3 datapoints) 66781 0.4% No Change

@skaslev skaslev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me overall.

Added one question inline.

Comment thread src/t_hash.c Outdated

@fcostaoliveira fcostaoliveira left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Yes, we could take the fast path unconditionally — HKEYS and HVALS would also benefit from the prefetched dict entry lookup, even though they only emit keys or values. The Phase 2 value prefetch can be gated on flags & OBJ_HASH_VALUE as you suggest. I'll update the code to remove the (flags & OBJ_HASH_KEY) && (flags & OBJ_HASH_VALUE) gate and skip the value prefetch when only keys are requested.

For HGETALL on OBJ_ENCODING_HT when prefetch-batch-max-size > 0,
use a three-phase batched iteration instead of the generic per-entry
iterator:

Phase 1: Collect up to 16 dict entries via dictNext, prefetch each
  Entry struct (field SDS is embedded in Entry, so one prefetch
  warms both the Entry metadata and the field string data).

Phase 2: For each collected entry, call entryGetValue to resolve
  the value SDS pointer and prefetch the value data.  For entries
  with pointer-based values (Type 3, large values), this hides the
  latency of the separate heap allocation dereference.

Phase 3: Emit replies — all field and value data is cache-warm.
  addReplyBulkCBuffer calls operate on warm cache lines.

Profiling shows dictNext at 10.1% flat CPU for 1K-field HGETALL
(scattered heap allocations cause cache misses on every entry).
The batched approach overlaps prefetch latency with reply generation,
which consumes ~25% CPU and provides a natural prefetch window.

Respects prefetch-batch-max-size: when 0, falls back to the generic
hashTypeIterator path.  Skips expired fields like the generic path.
- Check server.allow_access_expired before skipping expired fields,
  matching hashTypeNext() behavior. Without this, count diverges from
  hashTypeLength() when expired access is allowed, triggering the
  serverAssert(count == length).
- Bound batch size by server.prefetch_batch_max_size (capped at 16)
  instead of ignoring the configured limit.
- Remove unused batch_de array (dead code).
- Replace server.prefetch_batch_max_size with a constant HGETALL_BATCH
  (16). The config is meant for cross-command key prefetch, not
  intra-command iteration. (sundb, ShooterIT)
- Remove the config gate — fast path activates on encoding == HT with
  both KEY and VALUE flags.
- Restructure with goto done to share cleanup between fast path and
  fallback, reducing duplication. (sundb)
… keys requested

Per review: the batched prefetch fast path was gated on HGETALL
(keys+values) only. HKEYS and HVALS also benefit from the Entry
struct prefetch. Remove the flags gate and conditionally:
- Skip Phase 2 value prefetch when only keys requested
- Emit key/value in Phase 3 based on the flags
@fcostaoliveira fcostaoliveira force-pushed the hgetall-batch-prefetch branch from 053973c to 50ea65c Compare April 15, 2026 22:49
@fcostaoliveira

Copy link
Copy Markdown
Collaborator Author

Addressed in 50ea65c — the batched prefetch fast path now runs for HKEYS and HVALS too (not just HGETALL). Phase 2 value prefetch is skipped when !(flags & OBJ_HASH_VALUE), and Phase 3 conditionally emits key/value based on flags.

Also rebased onto latest unstable (includes #15003 propagation fix, #14661 C fast_float, #14979 CoW dict dismiss, #14905 GCRA type).

Comment thread src/t_hash.c Outdated
Comment thread src/t_hash.c Outdated
@ShooterIT

ShooterIT commented Apr 20, 2026

Copy link
Copy Markdown
Member

Happy to follow up with that once this pattern is validated. For now keeping it scoped to HGETALL where the profiling data shows the biggest win (dictNext at 10.1% flat CPU).

i think this pattern is proven, a generic function may be better

Comment thread src/t_hash.c Outdated
Comment thread src/t_hash.c Outdated
Comment thread src/t_hash.c Outdated
Comment thread src/t_hash.c Outdated
- drop indent on `#define HGETALL_BATCH 16`
- collapse phase-1 batching into a single `while (batch_count < HGETALL_BATCH)`
  loop; tighter and easier to read.

No behavior change — same skip-expired semantics, same prefetch ordering.
- Move the per-entry expire check from Phase 1 into Phase 2. Phase 1 is
  now a pure pointer-fetch + `redis_prefetch_read`, so the prefetch is
  no longer redundant against an inline `entryGetExpiry` read on the
  same cache line.
- Cache the value SDS pointers extracted in Phase 2 into `batch_val[]`
  so Phase 3 doesn't call `entryGetValue` a second time.
- Compact the batch in place so Phase 3 only walks non-expired entries.
@fcostaoliveira

Copy link
Copy Markdown
Collaborator Author

Pushed b475e1c with both follow-ups, @sundb:

  1. Phase 1 is now a pure pointer-fetch + redis_prefetch_read(e) — no entryGetExpiry read on the same cache line, so the prefetch is no longer redundant in the skip_expired path.
  2. Phase 2 does the expire check, extracts the value, caches it into batch_val[HGETALL_BATCH], and prefetches the value SDS. The batch is compacted in place via valid_count, so Phase 3 only walks non-expired entries and avoids the second entryGetValue call.

Verified unit/type/hash and unit/expire pass, plus a quick manual smoke test with HPEXPIRE on a hashtable-encoded hash to confirm HGETALL/HKEYS/HVALS return the right counts after expiry.

Will re-trigger the x86 + ARM benchmark suite to confirm the prefetch improvement holds with the new ordering — posting numbers when they land.

@fcostaoliveira

Copy link
Copy Markdown
Collaborator Author

Re-benchmarked b475e1cca (with @sundb's round-2 suggestions applied) against unstable 247307de9 on oss-standalone topology.

x86 (x86-aws-m7i.metal-24xl-2) — 11 HGETALL/HKEYS/HVALS improvements, 0 regressions

Test unstable PR Δ
memtier_benchmark-10Kkeys-hash-hgetall-500-fields-100B-values 14,750 21,033 +42.6%
memtier_benchmark-10Kkeys-hash-hgetall-200-fields-100B-values 35,081 45,255 +29.0%
memtier_benchmark-10Kkeys-hash-hgetall-100-fields-100B-values 63,053 73,992 +17.3%
memtier_benchmark-1key-hash-1K-fields-hgetall-pipeline-10 16,003 18,398 +15.0%
memtier_benchmark-1key-hash-1K-fields-hgetall 16,357 18,762 +14.7%
memtier_benchmark-1Mkeys-hash-hget-hgetall-hkeys-hvals-with-100B-values 171,114 189,264 +10.6%
memtier_benchmark-1Mkeys-hash-hkeys-5-fields-with-100B-values-with-expiration-pipeline-10 806,716 858,329 +6.4%
memtier_benchmark-playbook-session-storage-1k-sessions 156,094 163,824 +5.0%
memtier_benchmark-session-caching-hash-100k-sessions 152,834 160,415 +5.0%
memtier_benchmark-1Mkeys-hash-hgetall-50-fields-10B-values 167,362 174,691 +4.4%
memtier_benchmark-100Kkeys-hash-hgetall-50-fields-100B-values 158,793 165,259 +4.1%

TMA funnel (Intel m7i, 10Kkeys-hgetall-200f-100B)

The Phase-1/Phase-2 reorder is producing the expected microarchitectural shift — Phase 1 is now a pure pointer-fetch + redis_prefetch_read(e), so the prefetches are no longer redundant against an inline expiry-check.

Pipeline slots unstable PR Δ
Retiring (useful work) 29.8% 34.7% +4.9%
Backend_Bound 52.3% 42.4% −9.9%
Memory_Bound 45.7% 36.4% −9.3%
DRAM_Bound 22.2% 9.8% −12.4%
└ MEM_Latency 38.0% 31.3% −6.7%
Bad_Speculation 4.4% 2.1% −2.3%

DRAM_Bound dropped by more than half — prefetches land the Entry structs and value SDS into cache before Phase 3 reads them.

ARM

Triggered on a secondary ARM runner where memtier_benchmark itself appears CPU-bound (HGETALL absolute throughput is roughly half of the primary runner's), so the server-side prefetch win is masked. Re-triggering on the primary ARM runner; will follow up with those numbers.

Comment thread src/t_hash.c
int skip_expired = !server.allow_access_expired;
dict *d = o->ptr;
dictIterator di;
dictInitSafeIterator(&di, d);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is dictInitSafeIterator used to prevent cache invalidation caused by rehashing?

@fcostaoliveira

Copy link
Copy Markdown
Collaborator Author

ARM follow-up — re-ran on the primary arm-aws-m8g.metal-24xl runner against unstable 247307de9.

ARM (arm-aws-m8g.metal-24xl) — 6 HGETALL/HKEYS improvements, 0 regressions

Test unstable PR Δ
memtier_benchmark-10Kkeys-hash-hgetall-500-fields-100B-values 15,799 23,553 +49.1%
memtier_benchmark-10Kkeys-hash-hgetall-200-fields-100B-values 43,965 54,192 +23.3%
memtier_benchmark-1key-hash-1K-fields-hgetall-pipeline-10 15,039 17,864 +18.8%
memtier_benchmark-10Kkeys-hash-hgetall-100-fields-100B-values 76,976 88,790 +15.3%
memtier_benchmark-1key-hash-1K-fields-hgetall 16,262 18,733 +15.2%
memtier_benchmark-1Mkeys-hash-hkeys-5-fields-with-100B-values-with-expiration-pipeline-10 1,037,583 1,097,135 +5.7%

Median improvement +17.1%, max +49.1%. Cross-arch story holds — same magnitude as x86, same direction (the prefetch is hiding the same DRAM-latency stall on Graviton). Confidence in b475e1cca is high.

@sundb sundb added this to Redis 8.8 Apr 29, 2026
@sundb sundb merged commit 48eaa75 into redis:unstable Apr 29, 2026
18 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Redis 8.8 Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants