go-ethereum/accounts
Alexander Yastrebov a00430d4aa accounts/keystore: use map instead of slice to keep all accounts
After profiling geth startup times for #16874
it turned out that most of the time was spent resizing accounts slice
for ordered insertion.

This change uses map to track all accounts instead of slice to improve performance.

geth startup time using keystore with one million accounts reduced from
23 minutes to 2.5 minutes.

Benchmarks show relatively-small overhead increase for small keystores and large
decrease for huge:
```
goos: linux
goarch: amd64
pkg: github.com/ethereum/go-ethereum/accounts/keystore
                                  │      HEAD~1       │                  HEAD                   │
                                  │      sec/op       │    sec/op      vs base                  │
Add/preload=10-8                         1.030µ ±  5%    1.447µ ±  7%    +40.51% (p=0.000 n=10)
Add/preload=100-8                        1.109µ ±  4%    1.463µ ±  3%    +31.88% (p=0.000 n=10)
Add/preload=1000-8                       1.860µ ±  3%    1.477µ ±  5%    -20.57% (p=0.000 n=10)
Add/preload=1000000-8                 5177.640µ ±  2%    1.654µ ± 11%    -99.97% (p=0.000 n=10)
Find/preload=10/by_address-8             23.70n ±  1%    23.88n ±  3%          ~ (p=0.271 n=10)
Find/preload=10/by_path-8                50.43n ±  2%    39.88n ±  5%    -20.94% (p=0.000 n=10)
Find/preload=10/ambiguous-8              323.6n ±  1%   1049.0n ±  3%   +224.17% (p=0.000 n=10)
Find/preload=100/by_address-8            23.69n ±  1%    23.63n ±  6%          ~ (p=0.739 n=10)
Find/preload=100/by_path-8              362.70n ±  1%    37.84n ±  3%    -89.57% (p=0.000 n=10)
Find/preload=100/ambiguous-8             2.683µ ±  2%   19.235µ ±  2%   +617.05% (p=0.000 n=10)
Find/preload=1000/by_address-8           26.45n ±  1%    27.73n ±  2%     +4.82% (p=0.000 n=10)
Find/preload=1000/by_path-8            3211.00n ±  3%    38.22n ±  8%    -98.81% (p=0.000 n=10)
Find/preload=1000/ambiguous-8            26.14µ ±  2%   263.59µ ±  1%   +908.41% (p=0.000 n=10)
Find/preload=1000000/by_address-8        26.47n ±  4%    26.41n ±  1%          ~ (p=0.566 n=10)
Find/preload=1000000/by_path-8      3683325.50n ±  4%    44.09n ± 45%   -100.00% (p=0.000 n=10)
Find/preload=1000000/ambiguous-8         39.68m ± 14%   819.48m ±  7%  +1965.01% (p=0.000 n=10)
geomean                                  2.346µ          791.4n          -66.27%

                                  │     HEAD~1     │                   HEAD                    │
                                  │      B/op      │      B/op       vs base                   │
Add/preload=10-8                      643.0 ± 0%        662.0 ±  0%    +2.95% (p=0.000 n=10)
Add/preload=100-8                     643.0 ± 0%        662.0 ±  0%    +2.95% (p=0.000 n=10)
Add/preload=1000-8                    584.0 ± 5%        662.0 ±  0%   +13.36% (p=0.000 n=10)
Add/preload=1000000-8                 88.00 ± 0%       662.00 ± 17%  +652.27% (p=0.000 n=10)
Find/preload=10/by_address-8          0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=10/by_path-8             0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=10/ambiguous-8           624.0 ± 0%       1200.0 ±  0%   +92.31% (p=0.000 n=10)
Find/preload=100/by_address-8         0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=100/by_path-8            0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=100/ambiguous-8        6.047Ki ± 0%     12.047Ki ±  0%   +99.22% (p=0.000 n=10)
Find/preload=1000/by_address-8        0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=1000/by_path-8           0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=1000/ambiguous-8       56.05Ki ± 0%     112.05Ki ±  0%   +99.92% (p=0.000 n=10)
Find/preload=1000000/by_address-8     0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=1000000/by_path-8        0.000 ± 0%        0.000 ±  0%         ~ (p=1.000 n=10) ¹
Find/preload=1000000/ambiguous-8    53.41Mi ± 0%     106.81Mi ±  0%  +100.00% (p=0.000 n=10)
geomean                                          ²                    +36.09%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                  │    HEAD~1    │                 HEAD                  │
                                  │  allocs/op   │ allocs/op   vs base                   │
Add/preload=10-8                    3.000 ± 0%     4.000 ± 0%   +33.33% (p=0.000 n=10)
Add/preload=100-8                   3.000 ± 0%     4.000 ± 0%   +33.33% (p=0.000 n=10)
Add/preload=1000-8                  3.000 ± 0%     4.000 ± 0%   +33.33% (p=0.000 n=10)
Add/preload=1000000-8               2.000 ± 0%     4.000 ± 0%  +100.00% (p=0.000 n=10)
Find/preload=10/by_address-8        0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=10/by_path-8           0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=10/ambiguous-8         2.000 ± 0%     3.000 ± 0%   +50.00% (p=0.000 n=10)
Find/preload=100/by_address-8       0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=100/by_path-8          0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=100/ambiguous-8        2.000 ± 0%     3.000 ± 0%   +50.00% (p=0.000 n=10)
Find/preload=1000/by_address-8      0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=1000/by_path-8         0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=1000/ambiguous-8       2.000 ± 0%     3.000 ± 0%   +50.00% (p=0.000 n=10)
Find/preload=1000000/by_address-8   0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=1000000/by_path-8      0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=10) ¹
Find/preload=1000000/ambiguous-8    2.000 ± 0%     3.000 ± 0%   +50.00% (p=0.000 n=10)
geomean                                        ²                +21.97%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean
```

Updates #16874
2025-09-26 18:29:20 +02:00
..
abi accounts/abi/bind: fix data race in TestWaitDeployedCornerCases (#32740) 2025-09-24 20:05:14 -06:00
external all: implement eip-7702 set code tx (#30078) 2024-12-16 11:29:37 +01:00
keystore accounts/keystore: use map instead of slice to keep all accounts 2025-09-26 18:29:20 +02:00
scwallet fixes missing protection of nil pointer dereference in scwallet (#32186) 2025-08-21 09:41:54 +02:00
usbwallet accounts/usbwallet: correct version comparison logic (#32417) 2025-08-21 16:18:52 +02:00
accounts.go all: fix some typos in comments and names (#31023) 2025-01-14 14:16:15 +01:00
accounts_test.go accounts: run tests in parallel (#28544) 2023-12-04 14:55:06 +01:00
errors.go accounts: fix typo in comments (#24805) 2022-05-03 08:49:41 +02:00
hd.go build: upgrade to go 1.19 (#25726) 2022-09-10 13:25:40 +02:00
hd_test.go accounts: run tests in parallel (#28544) 2023-12-04 14:55:06 +01:00
manager.go accounts: fix data race when closing manager (#31982) 2025-06-17 14:44:51 +02:00
sort.go accounts, console: frendly card errors, support pin unblock 2019-04-08 13:19:37 +02:00
url.go build: upgrade to go 1.19 (#25726) 2022-09-10 13:25:40 +02:00
url_test.go accounts: run tests in parallel (#28544) 2023-12-04 14:55:06 +01:00