You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This feature is needed to get acceptable performance out of several eth_* methods. There's a draft #6720 but some additional considerations might be needed.
Benchmark Results: SQL vs. In-Memory Implementation for eth_getLogs
I ran load tests using oha (1000 sequential requests, 500-epoch range) against three configurations. Here's a summary of the key metrics:
Configuration
Avg (ms)
p50 (ms)
p95 (ms)
p99 (ms)
Req/sec
main (with cache)
47.88
37.17
106.30
122.87
20.88
main (no cache)
60.99
66.12
78.25
90.18
16.39
sql
61.31
58.46
84.40
92.11
16.31
Findings
The SQL implementation performs on par with main when the in-memory cache is disabled — both averaging ~61 ms with throughput around 16.3 req/sec. This confirms that the SQL approach does not offer a performance improvement over the existing implementation.
The main branch with cache enabled significantly outperforms SQL across most percentiles, particularly at the median (p50: 37 ms vs. 58 ms) and throughput (20.9 vs. 16.3 req/sec). It is worth noting that SQL wins slightly at p99 (92 ms vs. 123 ms), suggesting more consistent tail behaviour, but this comes at the cost of a considerably worse median. The cache accelerates repeated data loading for the same tipset and has a modest memory footprint (~100 MiB), so it is doing real work at low cost.
Conclusion
Since the SQL implementation merely matches the no-cache baseline without providing any measurable gain, and the existing in-memory cache already delivers substantially better median latency and throughput at negligible memory overhead, I don't think the current approach — a direct translation from Lotus — justifies proceeding further.
I'd suggest we close this out unless there is a compelling reason to prefer SQL beyond what is already covered by the current implementation.
# main
Success rate: 100.00%30s 40s 50s 60s 70s ││0.0222 0.0378 0.0535 0.0691 0.0847 0.1004 0.1160 │
Total:────────47898.2750 ms──────────────────────────────┘└──────────────────────────────────────────────────────────┘
Slowest: 163.6199 ms
Fastest: 22.2065 ms
Average: 47.8814 ms
Requests/sec: 20.8776
Total data: 1.92 GiB
Size/request: 1.97 MiB
Size/sec: 41.14 MiB
Response time histogram:
22.206 ms [1] |
36.348 ms [332] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
50.489 ms [352] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
64.631 ms [127] |■■■■■■■■■■■
78.772 ms [125] |■■■■■■■■■■■
92.913 ms [11] |■
107.055 ms [3] |
121.196 ms [37] |■■■
135.337 ms [6] |
149.479 ms [3] |
163.620 ms [3] |
Response time distribution:
10.00% in 31.8534 ms
25.00% in 35.8801 ms
50.00% in 37.1716 ms
75.00% in 61.2324 ms
90.00% in 71.9983 ms
95.00% in 106.3030 ms
99.00% in 122.8681 ms
99.90% in 163.6199 ms
99.99% in 163.6199 ms
# main - no cache
Success rate:m100.00% 4m 5m 6m 7m 8m ││0.0244 0.0382 0.0520 0.0657 0.0795 0.0933 0.1071 │
Total:────────61008.7898 ms──────────────────────────────┘└──────────────────────────────────────────────────────────┘
Slowest: 119.6616 ms
Fastest: 24.3998 ms
Average: 60.9914 ms
Requests/sec: 16.3911
Total data: 1.92 GiB
Size/request: 1.97 MiB
Size/sec: 32.30 MiB
Response time histogram:
24.400 ms [1] |
33.926 ms [31] |■■
43.452 ms [247] |■■■■■■■■■■■■■■■■■■
52.978 ms [4] |
62.505 ms [28] |■■
72.031 ms [430] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
81.557 ms [234] |■■■■■■■■■■■■■■■■■
91.083 ms [16] |■
100.609 ms [3] |
110.135 ms [3] |
119.662 ms [3] |
Response time distribution:
10.00% in 37.8355 ms
25.00% in 40.1914 ms
50.00% in 66.1160 ms
75.00% in 72.4119 ms
90.00% in 75.6998 ms
95.00% in 78.2507 ms
99.00% in 90.1752 ms
99.90% in 119.6616 ms
99.99% in 119.6616 ms
# SQL
Success rate:m100.00% 4m 5m 6m 7m 8m ││0.0421 0.0531 0.0641 0.0751 0.0861 0.0971 0.1081 │
Total:────────61328.7609 ms──────────────────────────────┘└──────────────────────────────────────────────────────────┘
Slowest: 117.0995 ms
Fastest: 42.0620 ms
Average: 61.3127 ms
Requests/sec: 16.3056
Total data: 1.92 GiB
Size/request: 1.97 MiB
Size/sec: 32.13 MiB
Response time histogram:
42.062 ms [1] |
49.566 ms [48] |■■■■
57.069 ms [341] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
64.573 ms [361] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
72.077 ms [74] |■■■■■■
79.581 ms [68] |■■■■■■
87.084 ms [77] |■■■■■■
94.588 ms [23] |■■
102.092 ms [3] |
109.596 ms [3] |
117.099 ms [1] |
Response time distribution:
10.00% in 51.2401 ms
25.00% in 53.1988 ms
50.00% in 58.4605 ms
75.00% in 64.3683 ms
90.00% in 79.9259 ms
95.00% in 84.4036 ms
99.00% in 92.1129 ms
99.90% in 117.0995 ms
99.99% in 117.0995 ms
Activity
eth_*methods performance #7008LesnyRumcajs commentedon Jun 18, 2026
@hanabi1224 please write down your findings here.
hanabi1224 commentedon Jun 24, 2026
(co-authored by Claude Code)
Benchmark Results: SQL vs. In-Memory Implementation for
eth_getLogsI ran load tests using
oha(1000 sequential requests, 500-epoch range) against three configurations. Here's a summary of the key metrics:main(with cache)main(no cache)sqlFindings
The SQL implementation performs on par with
mainwhen the in-memory cache is disabled — both averaging ~61 ms with throughput around 16.3 req/sec. This confirms that the SQL approach does not offer a performance improvement over the existing implementation.The
mainbranch with cache enabled significantly outperforms SQL across most percentiles, particularly at the median (p50: 37 ms vs. 58 ms) and throughput (20.9 vs. 16.3 req/sec). It is worth noting that SQL wins slightly at p99 (92 ms vs. 123 ms), suggesting more consistent tail behaviour, but this comes at the cost of a considerably worse median. The cache accelerates repeated data loading for the same tipset and has a modest memory footprint (~100 MiB), so it is doing real work at low cost.Conclusion
Since the SQL implementation merely matches the no-cache baseline without providing any measurable gain, and the existing in-memory cache already delivers substantially better median latency and throughput at negligible memory overhead, I don't think the current approach — a direct translation from Lotus — justifies proceeding further.
I'd suggest we close this out unless there is a compelling reason to prefer SQL beyond what is already covered by the current implementation.
Raw
ohabenchmark result:{
"method": "eth_getLogs",
"params": [
{
"fromBlock": "0x39e6a8",
"toBlock": "0x39e6da"
}
],
"id": 328,
"jsonrpc": "2.0"
}
hanabi1224 commentedon Jun 24, 2026
As discussed, the SQL is intended to be used for a larger range (like 2-month-worth epochs) with a strict filter. Will benchmark that scenario again.
LesnyRumcajs commentedon Jun 24, 2026
Yeah, and the methods affected are not only
eth_getLogsbut others ~eth.*filter.*LesnyRumcajs commentedon Jun 24, 2026
All in all, an SQL (or not, it's not set in stone) might have to be used to address expensive calls, for smaller ones we're probably good right now.
Kind of like
std::sort- use different algorithms for different collection sizes :)