Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TBS: validate pebble options for performance #15568

Open
carsonip opened this issue Feb 5, 2025 · 3 comments · May be fixed by #15664
Open

TBS: validate pebble options for performance #15568

carsonip opened this issue Feb 5, 2025 · 3 comments · May be fixed by #15664
Assignees

Comments

@carsonip
Copy link
Member

carsonip commented Feb 5, 2025

Follow-up from #15235

When developing #15235 , the pebble options were picked based on inaccurate benchmarks. Now that benchmarks are fixed, we should revisit the pebble options to ensure that reasonable values are used, and performance is good, as some options cannot be edited once the database is created.

Benchmark results under different options should be included in this issue to support the final option values selected for 9.0 release.

@carsonip carsonip changed the title TBS: validate pebble options performance TBS: validate pebble options for performance Feb 5, 2025
@carsonip carsonip self-assigned this Feb 6, 2025
@carsonip
Copy link
Member Author

carsonip commented Feb 6, 2025

Methodology

Ran a bunch of experiments using Github actions benchmark workflow on branch bench-pebble-options. They all run a standalone apm server on AWS with gp3 disk on minimum throughput sending to moxy. Sampling rate = 0.1.

In each run (a different commit), 1 variable is changed compared to the baseline (the options that are used on main now). Specifically, we will change each variable to baseline / 2 and baseline * 2 and observe any changes in benchmark.

Raw benchmark results are attached at the bottom, and their run history can be found in Github actions benchmark workflow

Results

Only useful comparisons are highlighted.

8mb event db memtable (baseline=16mb)

                      │ baseline.txt │          8mb-memtable.txt           │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   2.567k ± 18%        ~ (p=0.065 n=6)
TracesAgentGo-512       3.591k ± 27%   2.762k ± 59%        ~ (p=0.180 n=6)
TracesAgentNodeJS-512   1272.0 ± 53%    980.0 ± 51%  -22.96% (p=0.002 n=6)
TracesAgentPython-512   2.127k ± 27%   1.771k ± 39%        ~ (p=0.310 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.532k ± 21%        ~ (p=0.974 n=6)
geomean                 2.212k         1.799k        -18.65%

                      │        baseline.txt        │                 8mb-memtable.txt                  │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base               │
TracesAgentAll-512                    25.00k ± 25%                 20.27k ± 15%  -18.91% (p=0.004 n=6)
TracesAgentGo-512                     21.20k ± 47%                 19.70k ± 51%        ~ (p=0.818 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 12.79k ± 65%        ~ (p=0.065 n=6)
TracesAgentPython-512                 14.64k ± 25%                 12.90k ± 29%        ~ (p=0.240 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 17.67k ± 34%        ~ (p=0.485 n=6)
geomean                               18.37k                       16.34k        -11.07%

                      │ baseline.txt │          8mb-memtable.txt           │
                      │   max_rss    │   max_rss     vs base               │
TracesAgentAll-512      1.241G ± 11%   1.109G ±  6%  -10.63% (p=0.026 n=6)
TracesAgentGo-512       1.214G ±  7%   1.194G ± 14%        ~ (p=0.394 n=6)
TracesAgentNodeJS-512   1.233G ±  4%   1.204G ± 14%        ~ (p=0.589 n=6)
TracesAgentPython-512   1.352G ± 10%   1.390G ± 11%        ~ (p=0.485 n=6)
TracesAgentRuby-512     1.334G ± 26%   1.217G ±  9%   -8.83% (p=0.026 n=6)
geomean                 1.274G         1.219G         -4.27%

32mb event db memtable (baseline=16mb)

                      │ baseline.txt │          32mb-memtable.txt          │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   2.825k ± 87%        ~ (p=0.589 n=6)
TracesAgentGo-512       3.591k ± 27%   2.856k ± 57%        ~ (p=0.180 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.246k ± 32%        ~ (p=0.732 n=6)
TracesAgentPython-512   2.127k ± 27%   2.498k ± 37%        ~ (p=0.310 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.776k ± 29%  +11.25% (p=0.041 n=6)
geomean                 2.212k         2.137k         -3.37%

                      │        baseline.txt        │                 32mb-memtable.txt                 │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base               │
TracesAgentAll-512                    25.00k ± 25%                 28.37k ± 20%        ~ (p=0.240 n=6)
TracesAgentGo-512                     21.20k ± 47%                 22.56k ± 19%        ~ (p=0.240 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 16.75k ± 23%        ~ (p=0.485 n=6)
TracesAgentPython-512                 14.64k ± 25%                 16.65k ± 27%  +13.70% (p=0.041 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 17.28k ± 36%        ~ (p=0.180 n=6)
geomean                               18.37k                       19.85k         +8.08%

                      │ baseline.txt │          32mb-memtable.txt          │
                      │   max_rss    │   max_rss     vs base               │
TracesAgentAll-512      1.241G ± 11%   1.290G ± 13%        ~ (p=0.589 n=6)
TracesAgentGo-512       1.214G ±  7%   1.347G ±  7%  +10.95% (p=0.009 n=6)
TracesAgentNodeJS-512   1.233G ±  4%   1.290G ±  7%   +4.58% (p=0.004 n=6)
TracesAgentPython-512   1.352G ± 10%   1.508G ±  5%  +11.54% (p=0.009 n=6)
TracesAgentRuby-512     1.334G ± 26%   1.452G ± 15%        ~ (p=0.485 n=6)
geomean                 1.274G         1.375G         +7.94%

8kb event db block size (baseline=16kb)

                      │ baseline.txt │            8kb-block.txt            │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   2.860k ± 39%        ~ (p=0.485 n=6)
TracesAgentGo-512       3.591k ± 27%   2.853k ± 43%  -20.53% (p=0.026 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.128k ± 13%  -11.32% (p=0.015 n=6)
TracesAgentPython-512   2.127k ± 27%   1.534k ± 31%  -27.88% (p=0.041 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.376k ± 33%        ~ (p=0.818 n=6)
geomean                 2.212k         1.810k        -18.16%

                      │        baseline.txt        │                  8kb-block.txt                   │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 24.64k ± 13%       ~ (p=0.699 n=6)
TracesAgentGo-512                     21.20k ± 47%                 20.55k ± 17%       ~ (p=0.937 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 14.96k ± 26%       ~ (p=0.240 n=6)
TracesAgentPython-512                 14.64k ± 25%                 13.74k ± 24%       ~ (p=0.485 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 18.25k ± 20%       ~ (p=0.485 n=6)
geomean                               18.37k                       18.02k        -1.91%

                      │ baseline.txt │            8kb-block.txt             │
                      │ tbs_lsm_size │ tbs_lsm_size   vs base               │
TracesAgentAll-512      8.720G ± 70%   10.121G ± 69%        ~ (p=0.589 n=6)
TracesAgentGo-512       15.96G ± 30%    17.97G ± 27%        ~ (p=0.240 n=6)
TracesAgentNodeJS-512   15.67G ± 29%    19.90G ± 23%  +27.03% (p=0.041 n=6)
TracesAgentPython-512   20.34G ± 23%    23.67G ± 22%        ~ (p=0.240 n=6)
TracesAgentRuby-512     20.42G ± 16%    19.61G ± 19%        ~ (p=0.699 n=6)
geomean                 15.54G          17.58G        +13.15%

32kb event db block size (baseline=16kb)

                      │ baseline.txt │           32kb-block.txt            │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   3.034k ± 47%        ~ (p=0.818 n=6)
TracesAgentGo-512       3.591k ± 27%   3.143k ± 48%        ~ (p=0.589 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.246k ± 54%        ~ (p=0.310 n=6)
TracesAgentPython-512   2.127k ± 27%   1.653k ± 23%  -22.31% (p=0.041 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.609k ± 39%        ~ (p=0.699 n=6)
geomean                 2.212k         1.995k         -9.82%

                      │        baseline.txt        │                  32kb-block.txt                  │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 25.53k ± 29%       ~ (p=0.485 n=6)
TracesAgentGo-512                     21.20k ± 47%                 22.12k ± 34%       ~ (p=0.180 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 16.11k ± 18%       ~ (p=0.589 n=6)
TracesAgentPython-512                 14.64k ± 25%                 15.76k ± 21%       ~ (p=0.180 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 18.64k ± 29%       ~ (p=0.132 n=6)
geomean                               18.37k                       19.29k        +5.01%

                      │ baseline.txt │           32kb-block.txt            │
                      │ tbs_lsm_size │ tbs_lsm_size  vs base               │
TracesAgentAll-512      8.720G ± 70%   6.888G ± 67%        ~ (p=0.485 n=6)
TracesAgentGo-512       15.96G ± 30%   11.03G ± 29%        ~ (p=0.065 n=6)
TracesAgentNodeJS-512   15.67G ± 29%   13.19G ± 26%        ~ (p=0.132 n=6)
TracesAgentPython-512   20.34G ± 23%   17.15G ± 27%        ~ (p=0.180 n=6)
TracesAgentRuby-512     20.42G ± 16%   14.73G ± 16%  -27.87% (p=0.002 n=6)
geomean                 15.54G         12.04G        -22.50%

1mb decision db memtable (baseline=2mb)

                      │ baseline.txt │      1mb-decision-memtable.txt      │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   3.336k ± 25%        ~ (p=0.699 n=6)
TracesAgentGo-512       3.591k ± 27%   2.890k ± 36%        ~ (p=0.180 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.147k ± 35%        ~ (p=0.093 n=6)
TracesAgentPython-512   2.127k ± 27%   1.722k ± 22%        ~ (p=0.093 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.534k ± 45%        ~ (p=0.699 n=6)
geomean                 2.212k         1.964k        -11.20%

                      │        baseline.txt        │            1mb-decision-memtable.txt             │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 24.37k ± 21%       ~ (p=0.589 n=6)
TracesAgentGo-512                     21.20k ± 47%                 20.45k ± 22%       ~ (p=0.818 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 14.97k ± 24%       ~ (p=0.394 n=6)
TracesAgentPython-512                 14.64k ± 25%                 14.32k ±  9%       ~ (p=0.485 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 18.32k ± 17%       ~ (p=0.589 n=6)
geomean                               18.37k                       18.13k        -1.31%

4mb decision db memtable (baseline=2mb)

                      │ baseline.txt │      4mb-decision-memtable.txt      │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   1.941k ± 62%  -43.14% (p=0.026 n=6)
TracesAgentGo-512       3.591k ± 27%   1.621k ± 32%  -54.84% (p=0.002 n=6)
TracesAgentNodeJS-512   1272.0 ± 53%    869.5 ± 21%  -31.65% (p=0.002 n=6)
TracesAgentPython-512   2127.0 ± 27%    977.6 ± 55%  -54.04% (p=0.002 n=6)
TracesAgentRuby-512     1596.0 ± 59%    984.3 ± 29%        ~ (p=0.065 n=6)
geomean                 2.212k         1.214k        -45.13%

                      │        baseline.txt        │             4mb-decision-memtable.txt             │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base               │
TracesAgentAll-512                    25.00k ± 25%                 16.57k ± 81%  -33.73% (p=0.041 n=6)
TracesAgentGo-512                     21.20k ± 47%                 11.53k ± 15%  -45.59% (p=0.002 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 10.26k ± 13%  -37.27% (p=0.002 n=6)
TracesAgentPython-512                14.644k ± 25%                 9.614k ± 27%  -34.35% (p=0.002 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 11.86k ± 48%  -28.08% (p=0.026 n=6)
geomean                               18.37k                       11.74k        -36.07%

1kb decision db block size (baseline=2kb)

                      │ baseline.txt │       1kb-decision-block.txt        │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   3.020k ± 12%        ~ (p=0.485 n=6)
TracesAgentGo-512       3.591k ± 27%   3.130k ± 41%        ~ (p=0.937 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.192k ± 26%        ~ (p=0.132 n=6)
TracesAgentPython-512   2.127k ± 27%   1.554k ± 53%        ~ (p=0.093 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.450k ± 37%        ~ (p=0.937 n=6)
geomean                 2.212k         1.909k        -13.67%

                      │        baseline.txt        │              1kb-decision-block.txt              │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 24.86k ± 14%       ~ (p=0.937 n=6)
TracesAgentGo-512                     21.20k ± 47%                 21.99k ± 18%       ~ (p=0.485 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 14.86k ± 40%       ~ (p=0.589 n=6)
TracesAgentPython-512                 14.64k ± 25%                 14.27k ± 15%       ~ (p=0.937 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 19.56k ± 24%       ~ (p=0.093 n=6)
geomean                               18.37k                       18.67k        +1.61%

                      │ baseline.txt │       1kb-decision-block.txt       │
                      │ tbs_lsm_size │ tbs_lsm_size  vs base              │
TracesAgentAll-512      8.720G ± 70%   7.676G ± 70%       ~ (p=0.818 n=6)
TracesAgentGo-512       15.96G ± 30%   15.06G ± 25%       ~ (p=0.699 n=6)
TracesAgentNodeJS-512   15.67G ± 29%   16.18G ± 24%       ~ (p=1.000 n=6)
TracesAgentPython-512   20.34G ± 23%   19.87G ± 21%       ~ (p=0.818 n=6)
TracesAgentRuby-512     20.42G ± 16%   16.93G ± 21%       ~ (p=0.065 n=6)
geomean                 15.54G         14.45G        -7.03%

4kb decision db block size (baseline=2kb)

                      │ baseline.txt │       4kb-decision-block.txt       │
                      │  events/sec  │  events/sec   vs base              │
TracesAgentAll-512      3.413k ± 36%   3.739k ± 25%       ~ (p=0.937 n=6)
TracesAgentGo-512       3.591k ± 27%   3.438k ± 28%       ~ (p=0.818 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.216k ± 50%       ~ (p=0.485 n=6)
TracesAgentPython-512   2.127k ± 27%   1.857k ± 90%       ~ (p=0.310 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.581k ± 57%       ~ (p=0.974 n=6)
geomean                 2.212k         2.150k        -2.81%

                      │        baseline.txt        │              4kb-decision-block.txt              │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 24.47k ± 30%       ~ (p=0.818 n=6)
TracesAgentGo-512                     21.20k ± 47%                 20.23k ± 14%       ~ (p=0.818 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 15.58k ± 25%       ~ (p=0.589 n=6)
TracesAgentPython-512                 14.64k ± 25%                 13.89k ± 41%       ~ (p=0.699 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 16.71k ± 36%       ~ (p=0.818 n=6)
geomean                               18.37k                       17.81k        -3.08%

16mb decision db cache (baseline=8mb)

                      │ baseline.txt │      16MB-decision-cache.txt       │
                      │  events/sec  │  events/sec   vs base              │
TracesAgentAll-512      3.413k ± 36%   3.563k ± 27%       ~ (p=0.937 n=6)
TracesAgentGo-512       3.591k ± 27%   3.672k ± 17%       ~ (p=1.000 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.191k ± 51%       ~ (p=0.132 n=6)
TracesAgentPython-512   2.127k ± 27%   1.913k ± 22%       ~ (p=0.180 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.692k ± 42%       ~ (p=0.394 n=6)
geomean                 2.212k         2.191k        -0.94%

                      │        baseline.txt        │             16MB-decision-cache.txt              │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 24.90k ± 23%       ~ (p=0.937 n=6)
TracesAgentGo-512                     21.20k ± 47%                 22.97k ± 15%       ~ (p=0.485 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 14.83k ± 30%       ~ (p=0.394 n=6)
TracesAgentPython-512                 14.64k ± 25%                 15.60k ± 13%       ~ (p=0.589 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 19.60k ± 15%       ~ (p=0.132 n=6)
geomean                               18.37k                       19.18k        +4.41%

                      │ baseline.txt │      16MB-decision-cache.txt       │
                      │   max_rss    │   max_rss     vs base              │
TracesAgentAll-512      1.241G ± 11%   1.191G ± 27%       ~ (p=0.937 n=6)
TracesAgentGo-512       1.214G ±  7%   1.333G ± 15%  +9.84% (p=0.009 n=6)
TracesAgentNodeJS-512   1.233G ±  4%   1.255G ±  5%       ~ (p=0.485 n=6)
TracesAgentPython-512   1.352G ± 10%   1.485G ±  8%  +9.84% (p=0.026 n=6)
TracesAgentRuby-512     1.334G ± 26%   1.388G ± 10%       ~ (p=0.699 n=6)
geomean                 1.274G         1.327G        +4.16%

decision db compression enabled (baseline=disabled)

                      │ baseline.txt │      compression-decision.txt       │
                      │  events/sec  │  events/sec   vs base               │
TracesAgentAll-512      3.413k ± 36%   3.079k ± 26%        ~ (p=0.485 n=6)
TracesAgentGo-512       3.591k ± 27%   3.293k ± 34%        ~ (p=0.485 n=6)
TracesAgentNodeJS-512   1.272k ± 53%   1.124k ± 14%  -11.64% (p=0.015 n=6)
TracesAgentPython-512   2.127k ± 27%   1.790k ± 31%        ~ (p=0.132 n=6)
TracesAgentRuby-512     1.596k ± 59%   1.353k ± 29%        ~ (p=0.699 n=6)
geomean                 2.212k         1.942k        -12.21%

                      │        baseline.txt        │             compression-decision.txt             │
                      │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-512                    25.00k ± 25%                 22.82k ± 37%       ~ (p=0.240 n=6)
TracesAgentGo-512                     21.20k ± 47%                 18.90k ± 21%       ~ (p=0.310 n=6)
TracesAgentNodeJS-512                 16.35k ± 26%                 14.20k ± 17%       ~ (p=0.132 n=6)
TracesAgentPython-512                 14.64k ± 25%                 13.43k ± 39%       ~ (p=0.394 n=6)
TracesAgentRuby-512                   16.49k ± 40%                 17.47k ± 17%       ~ (p=0.937 n=6)
geomean                               18.37k                       17.04k        -7.23%

                      │ baseline.txt │      compression-decision.txt       │
                      │ tbs_lsm_size │ tbs_lsm_size  vs base               │
TracesAgentAll-512      8.720G ± 70%   6.529G ± 84%        ~ (p=0.485 n=6)
TracesAgentGo-512       15.96G ± 30%   12.25G ± 31%        ~ (p=0.093 n=6)
TracesAgentNodeJS-512   15.67G ± 29%   15.12G ± 21%        ~ (p=0.394 n=6)
TracesAgentPython-512   20.34G ± 23%   16.44G ± 29%        ~ (p=0.093 n=6)
TracesAgentRuby-512     20.42G ± 16%   18.88G ± 35%        ~ (p=0.240 n=6)
geomean                 15.54G         13.03G        -16.15%

Conclusion

For this dataset and setup (AWS with gp3 disk on minimum throughput), the current baseline appears to be perform reasonably well, as no options tested so far gives a significant boost to the numbers.

Some no-gos shown in this exercise

  • Increasing decision db memtable size kills the performance (-45% event rate, -36% intake event rate). This is expected as it is the hot path, and as there is no memtable bloom filter, memtables need to be scanned for each event for a decision. However, decreasing the decision db memtable size doesn't seem to give any benefit.
  • Compression on decision db: again, as this is in the hot path, decompression overhead adds up, for a minimal reduction in database size. The reduction (-16%) in database size needs to be viewed in conjunction with intake event rate (-7%), as less is admitted to the database. The net reduction in database size is then merely 9%.

Other trade-offs

  • A bigger event db memtable gives higher intake event rate but memory usage will increase accordingly and a slight reduction in event rate (read path).
  • A bigger event db block size gives better intake event rate (+5%), likely benefiting from better compression (-22% in db size). This yields a net -27% in database size normalized. This results in a penalty in event rate on the read path (-9%).
    • This is highly dependent on avg trace size (number of events in a trace * avg event size). When block size >> avg trace size, disk reads will start to contain data in the same block but from other traces, which is wasteful as disk throughput can otherwise be used for other writes / reads, not to mention the decompression overhead.
    • I'm open to increasing the block size to 32KB, as RocksDB wiki also mentions 16-32KB block size for production use cases.
    • Note: Compression ratio may be lower in practice, as the canned data used in benchmarks are highly repetitive.
    • All read vs write perf tradeoffs should be based on the fact that 0.1 sampling rate is used in this experiment which may be higher than most TBS setups. Therefore, any write perf gain for a read perf loss on top of the current numbers should turn out to be beneficial.
  • 8MB->16MB decision cache seems to be a fair trade between intake event rate and memory usage. Let me double check if this can be changed without recreating database. This seems to be a good candidate for an option that scales proportionally to system memory, as a cache miss in the hot path can be detrimental to throughput. Ideally the decisions are entirely in-memory.
    • Although this cache size option is not tested for event db, the auto scaling idea applies to event db as well for read path performance.

Raw benchmark results

1kb-decision-block.txt
1mb-decision-memtable.txt
4kb-decision-block.txt
4mb-decision-memtable.txt
8kb-block.txt
8mb-memtable.txt
16MB-decision-cache.txt
32kb-block.txt
32mb-memtable.txt
baseline.txt
compression-decision.txt

@simitt
Copy link
Contributor

simitt commented Feb 6, 2025

Agree with your analysis - none of the changes suggest it would be worth to change the default.

@carsonip
Copy link
Member Author

Methodology

Tested with local nvme disk using 32GB memory c6id instances this time instead of the slowest gp3 EBS disk. Baseline = main running in this setup.

Results

scaling cache size to 16MB per GB of system memory (spread between 2 databases) (baseline=8MB fixed per DB)

As the instance is 32GB, it means 32*16MB - 16MB (baseline) = 496MB extra memory used. The memory increase is expected. However, the throughput gain isn't significant.

                       │  baseline.txt  │             16mbpergb.txt             │
                       │ max_heap_alloc │ max_heap_alloc  vs base               │
TracesAgentAll-2048         2.677G ± 3%     3.356G ± 10%  +25.40% (p=0.002 n=6)
TracesAgentGo-2048          2.837G ± 6%     3.534G ±  2%  +24.58% (p=0.002 n=6)
TracesAgentNodeJS-2048      3.038G ± 3%     3.589G ±  4%  +18.14% (p=0.002 n=6)
TracesAgentPython-2048      3.174G ± 1%     3.886G ±  5%  +22.41% (p=0.002 n=6)
TracesAgentRuby-2048        2.958G ± 7%     3.542G ±  8%  +19.76% (p=0.002 n=6)
geomean                     2.932G          3.578G        +22.03%

                       │ baseline.txt │            16mbpergb.txt            │
                       │   max_rss    │   max_rss     vs base               │
TracesAgentAll-2048       3.143G ± 5%   3.938G ± 11%  +25.28% (p=0.002 n=6)
TracesAgentGo-2048        3.199G ± 5%   4.100G ±  2%  +28.18% (p=0.002 n=6)
TracesAgentNodeJS-2048    3.465G ± 5%   4.359G ±  3%  +25.79% (p=0.002 n=6)
TracesAgentPython-2048    3.749G ± 5%   4.423G ±  4%  +17.97% (p=0.002 n=6)
TracesAgentRuby-2048      3.470G ± 2%   4.277G ±  4%  +23.26% (p=0.002 n=6)
geomean                   3.398G        4.216G        +24.05%

                       │        baseline.txt        │                  16mbpergb.txt                   │
                       │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-2048                    51.07k ± 12%                 45.01k ± 22%       ~ (p=0.180 n=6)
TracesAgentGo-2048                     41.94k ± 14%                 50.33k ± 43%       ~ (p=0.065 n=6)
TracesAgentNodeJS-2048                 25.80k ± 69%                 29.25k ± 23%       ~ (p=0.240 n=6)
TracesAgentPython-2048                 24.57k ± 82%                 25.67k ± 19%       ~ (p=0.589 n=6)
TracesAgentRuby-2048                   37.42k ± 32%                 41.64k ± 73%       ~ (p=0.394 n=6)
geomean                                34.77k                       37.16k        +6.87%

                       │ baseline.txt │            16mbpergb.txt            │
                       │  events/sec  │  events/sec   vs base               │
TracesAgentAll-2048      5.646k ± 69%   5.162k ± 29%        ~ (p=0.180 n=6)
TracesAgentGo-2048       5.022k ± 36%   7.217k ± 18%  +43.69% (p=0.015 n=6)
TracesAgentNodeJS-2048   2.394k ± 21%   2.509k ± 18%        ~ (p=0.180 n=6)
TracesAgentPython-2048   1.833k ± 89%   1.849k ± 65%        ~ (p=0.699 n=6)
TracesAgentRuby-2048     3.285k ± 24%   3.470k ± 39%        ~ (p=0.818 n=6)
geomean                  3.329k         3.594k         +7.96%

force write parallelism (baseline=disabled)

No gains on the write path.

                       │        baseline.txt        │               writeparallelism.txt               │
                       │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-2048                    51.07k ± 12%                 45.75k ± 24%       ~ (p=0.180 n=6)
TracesAgentGo-2048                     41.94k ± 14%                 45.39k ± 16%       ~ (p=0.310 n=6)
TracesAgentNodeJS-2048                 25.80k ± 69%                 28.27k ± 63%       ~ (p=0.132 n=6)
TracesAgentPython-2048                 24.57k ± 82%                 23.49k ± 90%       ~ (p=0.589 n=6)
TracesAgentRuby-2048                   37.42k ± 32%                 34.62k ± 36%       ~ (p=0.818 n=6)
geomean                                34.77k                       34.34k        -1.23%

                       │ baseline.txt │        writeparallelism.txt        │
                       │  events/sec  │  events/sec   vs base              │
TracesAgentAll-2048      5.646k ± 69%   5.123k ± 34%       ~ (p=0.240 n=6)
TracesAgentGo-2048       5.022k ± 36%   5.088k ± 35%       ~ (p=0.937 n=6)
TracesAgentNodeJS-2048   2.394k ± 21%   2.514k ± 24%       ~ (p=0.132 n=6)
TracesAgentPython-2048   1.833k ± 89%   2.647k ± 57%       ~ (p=0.589 n=6)
TracesAgentRuby-2048     3.285k ± 24%   3.277k ± 22%       ~ (p=0.937 n=6)
geomean                  3.329k         3.556k        +6.81%

event db 32kb block size (baseline=16kb block size)

Consistent with gp3 testing. Increasing from 16kb to 32kb seems to be beneficial.

                       │ baseline.txt │            32kbblock.txt            │
                       │  events/sec  │  events/sec   vs base               │
TracesAgentAll-2048      5.646k ± 69%   6.979k ± 31%        ~ (p=0.394 n=6)
TracesAgentGo-2048       5.022k ± 36%   4.806k ± 33%        ~ (p=0.589 n=6)
TracesAgentNodeJS-2048   2.394k ± 21%   2.316k ± 22%        ~ (p=1.000 n=6)
TracesAgentPython-2048   1.833k ± 89%   2.856k ± 65%        ~ (p=0.310 n=6)
TracesAgentRuby-2048     3.285k ± 24%   3.545k ± 29%        ~ (p=1.000 n=6)
geomean                  3.329k         3.794k        +13.97%

                       │        baseline.txt        │                  32kbblock.txt                   │
                       │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base              │
TracesAgentAll-2048                    51.07k ± 12%                 53.32k ± 33%       ~ (p=0.818 n=6)
TracesAgentGo-2048                     41.94k ± 14%                 38.41k ± 35%       ~ (p=0.589 n=6)
TracesAgentNodeJS-2048                 25.80k ± 69%                 27.88k ± 72%       ~ (p=0.331 n=6)
TracesAgentPython-2048                 24.57k ± 82%                 25.21k ± 61%       ~ (p=0.699 n=6)
TracesAgentRuby-2048                   37.42k ± 32%                 42.10k ± 28%       ~ (p=0.240 n=6)
geomean                                34.77k                       36.02k        +3.59%

                       │ baseline.txt │           32kbblock.txt            │
                       │ tbs_lsm_size │ tbs_lsm_size  vs base              │
TracesAgentAll-2048      14.01G ± 84%   13.67G ± 81%       ~ (p=0.699 n=6)
TracesAgentGo-2048       27.33G ± 23%   27.25G ± 30%       ~ (p=0.699 n=6)
TracesAgentNodeJS-2048   32.50G ± 31%   27.30G ± 34%       ~ (p=0.180 n=6)
TracesAgentPython-2048   30.97G ± 26%   26.27G ± 27%       ~ (p=0.240 n=6)
TracesAgentRuby-2048     31.80G ± 30%   28.31G ± 31%       ~ (p=0.310 n=6)
geomean                  26.16G         23.75G        -9.20%

partitions per ttl = 2 (baseline=1)

This is a little surprising and unintuitive. I wonder if it is just the variance. Not planning to change it without understanding the benchmark.

                       │ baseline.txt │             ppttl2.txt             │
                       │  events/sec  │  events/sec   vs base              │
TracesAgentAll-2048      5.646k ± 69%   5.487k ± 19%       ~ (p=0.589 n=6)
TracesAgentGo-2048       5.022k ± 36%   6.010k ±  8%       ~ (p=0.240 n=6)
TracesAgentNodeJS-2048   2.394k ± 21%   2.694k ± 32%       ~ (p=0.180 n=6)
TracesAgentPython-2048   1.833k ± 89%   2.359k ± 41%       ~ (p=0.818 n=6)
TracesAgentRuby-2048     3.285k ± 24%   2.732k ± 65%       ~ (p=0.180 n=6)
geomean                  3.329k         3.561k        +6.97%

                       │        baseline.txt        │                    ppttl2.txt                     │
                       │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base               │
TracesAgentAll-2048                    51.07k ± 12%                 45.15k ± 33%        ~ (p=0.240 n=6)
TracesAgentGo-2048                     41.94k ± 14%                 54.06k ± 36%  +28.92% (p=0.002 n=6)
TracesAgentNodeJS-2048                 25.80k ± 69%                 30.31k ± 44%  +17.49% (p=0.041 n=6)
TracesAgentPython-2048                 24.57k ± 82%                 26.35k ± 26%        ~ (p=0.394 n=6)
TracesAgentRuby-2048                   37.42k ± 32%                 37.37k ± 62%        ~ (p=1.000 n=6)
geomean                                34.77k                       37.37k         +7.47%

                       │ baseline.txt │             ppttl2.txt             │
                       │ tbs_lsm_size │ tbs_lsm_size  vs base              │
TracesAgentAll-2048      14.01G ± 84%   14.65G ± 80%       ~ (p=0.937 n=6)
TracesAgentGo-2048       27.33G ± 23%   25.41G ± 15%       ~ (p=0.394 n=6)
TracesAgentNodeJS-2048   32.50G ± 31%   28.09G ± 16%       ~ (p=0.180 n=6)
TracesAgentPython-2048   30.97G ± 26%   30.42G ± 12%       ~ (p=1.000 n=6)
TracesAgentRuby-2048     31.80G ± 30%   25.49G ± 24%       ~ (p=0.180 n=6)
geomean                  26.16G         24.09G        -7.92%

Bonus: 8.18 badger comparisons

Adding some badger comparisons to check for regression with fast disk, high spec setup, in this case, 32GB apm-server with local NVMe ssd.

badger 8.18 to main baseline

Great improvement in max_rss (-88%) and disk (107GB -> 26GB). intake event rate in pebble is slower than in badger (-13%), supposedly due to disk IO being used for reads (+8%).

                       │   8.18.txt    │            baseline.txt             │
                       │  events/sec   │  events/sec   vs base               │
TracesAgentAll-2048      5.620k ± 101%   5.646k ± 69%        ~ (p=0.937 n=6)
TracesAgentGo-2048       3.810k ±   6%   5.022k ± 36%  +31.82% (p=0.002 n=6)
TracesAgentNodeJS-2048   1.911k ±   9%   2.394k ± 21%  +25.31% (p=0.041 n=6)
TracesAgentPython-2048   3.483k ±  28%   1.833k ± 89%  -47.37% (p=0.015 n=6)
TracesAgentRuby-2048     1.950k ±  18%   3.285k ± 24%  +68.53% (p=0.002 n=6)
geomean                  3.081k          3.329k         +8.04%

                       │          8.18.txt          │                   baseline.txt                    │
                       │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base               │
TracesAgentAll-2048                    53.14k ± 60%                 51.07k ± 12%        ~ (p=0.937 n=6)
TracesAgentGo-2048                     37.84k ± 26%                 41.94k ± 14%        ~ (p=0.310 n=6)
TracesAgentNodeJS-2048                 50.24k ± 18%                 25.80k ± 69%  -48.65% (p=0.002 n=6)
TracesAgentPython-2048                 27.72k ± 50%                 24.57k ± 82%        ~ (p=0.093 n=6)
TracesAgentRuby-2048                   37.36k ± 25%                 37.42k ± 32%        ~ (p=0.589 n=6)
geomean                                40.17k                       34.77k        -13.45%

                       │    8.18.txt    │             baseline.txt              │
                       │ max_heap_alloc │ max_heap_alloc  vs base               │
TracesAgentAll-2048        4.773G ± 42%      2.677G ± 3%  -43.92% (p=0.002 n=6)
TracesAgentGo-2048         5.565G ±  7%      2.837G ± 6%  -49.03% (p=0.002 n=6)
TracesAgentNodeJS-2048     6.028G ±  7%      3.038G ± 3%  -49.61% (p=0.002 n=6)
TracesAgentPython-2048     5.726G ±  6%      3.174G ± 1%  -44.56% (p=0.002 n=6)
TracesAgentRuby-2048       5.659G ± 10%      2.958G ± 7%  -47.73% (p=0.002 n=6)
geomean                    5.534G            2.932G       -47.02%

                       │   8.18.txt    │            baseline.txt            │
                       │    max_rss    │   max_rss    vs base               │
TracesAgentAll-2048      26.858G ± 13%   3.143G ± 5%  -88.30% (p=0.002 n=6)
TracesAgentGo-2048       29.573G ±  2%   3.199G ± 5%  -89.18% (p=0.002 n=6)
TracesAgentNodeJS-2048   30.085G ±  2%   3.465G ± 5%  -88.48% (p=0.002 n=6)
TracesAgentPython-2048   25.383G ± 26%   3.749G ± 5%  -85.23% (p=0.002 n=6)
TracesAgentRuby-2048     29.609G ±  3%   3.470G ± 2%  -88.28% (p=0.002 n=6)
geomean                   28.24G         3.398G       -87.97%

                       │   8.18.txt   │            baseline.txt             │
                       │ tbs_lsm_size │ tbs_lsm_size  vs base               │
TracesAgentAll-2048      21.09G ± 61%   14.01G ± 84%        ~ (p=0.394 n=6)
TracesAgentGo-2048       26.77G ±  5%   27.33G ± 23%        ~ (p=0.937 n=6)
TracesAgentNodeJS-2048   25.05G ±  9%   32.50G ± 31%        ~ (p=0.065 n=6)
TracesAgentPython-2048   24.38G ± 14%   30.97G ± 26%  +27.02% (p=0.041 n=6)
TracesAgentRuby-2048     25.29G ± 14%   31.80G ± 30%        ~ (p=0.093 n=6)
geomean                  24.44G         26.16G         +7.03%

                       │   8.18.txt    │               baseline.txt                │
                       │ tbs_vlog_size │ tbs_vlog_size  vs base                    │
TracesAgentAll-2048       56.49G ± 62%      0.00G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentGo-2048        66.46G ± 28%      0.00G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentNodeJS-2048    89.43G ± 29%      0.00G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentPython-2048    128.0G ± 14%       0.0G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentRuby-2048      96.78G ± 22%      0.00G ± 0%  -100.00% (p=0.002 n=6)
geomean                   83.91G                        ?                      ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean

badger 8.18 to main with 32kb block size

32kb block size means more efficient disk IO, which makes up a bit for the write path regression (+23% on events/s, -10% on intake event rate). Same memory gains and even bigger disk usage improvement.

                       │   8.18.txt    │            32kbblock.txt            │
                       │  events/sec   │  events/sec   vs base               │
TracesAgentAll-2048      5.620k ± 101%   6.979k ± 31%        ~ (p=0.699 n=6)
TracesAgentGo-2048       3.810k ±   6%   4.806k ± 33%  +26.13% (p=0.002 n=6)
TracesAgentNodeJS-2048   1.911k ±   9%   2.316k ± 22%  +21.22% (p=0.041 n=6)
TracesAgentPython-2048   3.483k ±  28%   2.856k ± 65%        ~ (p=0.180 n=6)
TracesAgentRuby-2048     1.950k ±  18%   3.545k ± 29%  +81.82% (p=0.002 n=6)
geomean                  3.081k          3.794k        +23.13%

                       │          8.18.txt          │                   32kbblock.txt                   │
                       │ intake_events_accepted/sec │ intake_events_accepted/sec  vs base               │
TracesAgentAll-2048                    53.14k ± 60%                 53.32k ± 33%        ~ (p=0.818 n=6)
TracesAgentGo-2048                     37.84k ± 26%                 38.41k ± 35%        ~ (p=0.699 n=6)
TracesAgentNodeJS-2048                 50.24k ± 18%                 27.88k ± 72%  -44.50% (p=0.009 n=6)
TracesAgentPython-2048                 27.72k ± 50%                 25.21k ± 61%        ~ (p=0.310 n=6)
TracesAgentRuby-2048                   37.36k ± 25%                 42.10k ± 28%        ~ (p=0.132 n=6)
geomean                                40.17k                       36.02k        -10.34%


                       │   8.18.txt    │           32kbblock.txt            │
                       │    max_rss    │   max_rss    vs base               │
TracesAgentAll-2048      26.858G ± 13%   3.115G ± 9%  -88.40% (p=0.002 n=6)
TracesAgentGo-2048       29.573G ±  2%   3.297G ± 9%  -88.85% (p=0.002 n=6)
TracesAgentNodeJS-2048   30.085G ±  2%   3.524G ± 5%  -88.29% (p=0.002 n=6)
TracesAgentPython-2048   25.383G ± 26%   3.713G ± 3%  -85.37% (p=0.002 n=6)
TracesAgentRuby-2048     29.609G ±  3%   3.513G ± 5%  -88.13% (p=0.002 n=6)
geomean                   28.24G         3.426G       -87.87%

                       │   8.18.txt   │           32kbblock.txt            │
                       │ tbs_lsm_size │ tbs_lsm_size  vs base              │
TracesAgentAll-2048      21.09G ± 61%   13.67G ± 81%       ~ (p=0.240 n=6)
TracesAgentGo-2048       26.77G ±  5%   27.25G ± 30%       ~ (p=0.937 n=6)
TracesAgentNodeJS-2048   25.05G ±  9%   27.30G ± 34%       ~ (p=0.310 n=6)
TracesAgentPython-2048   24.38G ± 14%   26.27G ± 27%       ~ (p=0.818 n=6)
TracesAgentRuby-2048     25.29G ± 14%   28.31G ± 31%       ~ (p=0.485 n=6)
geomean                  24.44G         23.75G        -2.81%

                       │   8.18.txt    │               32kbblock.txt               │
                       │ tbs_vlog_size │ tbs_vlog_size  vs base                    │
TracesAgentAll-2048       56.49G ± 62%      0.00G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentGo-2048        66.46G ± 28%      0.00G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentNodeJS-2048    89.43G ± 29%      0.00G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentPython-2048    128.0G ± 14%       0.0G ± 0%  -100.00% (p=0.002 n=6)
TracesAgentRuby-2048      96.78G ± 22%      0.00G ± 0%  -100.00% (p=0.002 n=6)
geomean                   83.91G                        ?                      ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean

Conclusion

Badger comparison shows a minor regression on intake event rate (write path) in 32GB apm-server using NVMe SSDs.

16kb->32kb event db block size seems to be the only option that is worth changing at the moment.

I did not look into actual bottlenecks as the benchmarks are run on AWS. It could be a follow up task to study CPU / disk utilization, profiles and pebble metrics (cache hit rate etc). This task focuses on shipping with good enough defaults that will give us reasonable performance and ensure there is no significant perf regression compared to badger.

Raw benchmark results

16mbpergb.txt
32kbblock.txt
baseline.txt
writeparallelism.txt
8.18.txt

@carsonip carsonip linked a pull request Feb 11, 2025 that will close this issue
2 tasks
@carsonip carsonip reopened this Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants