github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/accounts/benchmark_manager_test.go (about) 1 package accounts 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strconv" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 //func BenchmarkAccountSignScaling(b *testing.B) { 15 // var cases = []struct { 16 // dir string 17 // numKeyFiles int 18 // resetAll, resetCache bool 19 // }{ 20 // // You can use resetCache: false to save some time if you've already run the benchmark. 21 // // Note that if you make any changes to the structure of the cachedb you'll need to 22 // // dump and reinitialize accounts.db. 23 // {dir: "benchmark_keystore100", numKeyFiles: 100, resetAll: false, resetCache: true}, 24 // //{dir: "benchmark_keystore100", numKeyFiles: 100, resetAll: false, resetCache: false}, 25 // {dir: "benchmark_keystore500", numKeyFiles: 500, resetAll: false, resetCache: true}, 26 // //{dir: "benchmark_keystore500", numKeyFiles: 500, resetAll: false, resetCache: false}, 27 // {dir: "benchmark_keystore1k", numKeyFiles: 1000, resetAll: false, resetCache: true}, 28 // //{dir: "benchmark_keystore1k", numKeyFiles: 1000, resetAll: false, resetCache: false}, 29 // {dir: "benchmark_keystore5k", numKeyFiles: 5000, resetAll: false, resetCache: true}, 30 // //{dir: "benchmark_keystore5k", numKeyFiles: 5000, resetAll: false, resetCache: false}, 31 // {dir: "benchmark_keystore10k", numKeyFiles: 10000, resetAll: false, resetCache: true}, 32 // //{dir: "benchmark_keystore10k", numKeyFiles: 10000, resetAll: false, resetCache: false}, 33 // {dir: "benchmark_keystore20k", numKeyFiles: 20000, resetAll: false, resetCache: true}, 34 // //{dir: "benchmark_keystore20k", numKeyFiles: 20000, resetAll: false, resetCache: false}, 35 // {dir: "benchmark_keystore100k", numKeyFiles: 100000, resetAll: false, resetCache: true}, 36 // //{dir: "benchmark_keystore100k", numKeyFiles: 100000, resetAll: false, resetCache: false}, 37 // {dir: "benchmark_keystore500k", numKeyFiles: 500000, resetAll: false, resetCache: true}, 38 // //{dir: "benchmark_keystore500k", numKeyFiles: 500000, resetAll: false, resetCache: false}, 39 // } 40 // 41 // for _, c := range cases { 42 // b.Run(fmt.Sprintf("KeyFiles#:%v, CacheFromScratch:%v", c.numKeyFiles, c.resetCache), func(b *testing.B) { 43 // am := setupBenchmarkAccountFlowFast(filepath.Join("testdata", c.dir), c.numKeyFiles, c.resetAll, c.resetCache, b) 44 // benchmarkAccountSignFast(am.keyStore.baseDir, am, c.numKeyFiles-1, b) 45 // am = nil 46 // }) 47 // } 48 //} 49 // 50 //func BenchmarkAccountFlowScaling(b *testing.B) { 51 // var cases = []struct { 52 // dir string 53 // numKeyFiles int 54 // resetAll, resetCache bool 55 // }{ 56 // {dir: "benchmark_keystore100", numKeyFiles: 100, resetAll: false, resetCache: true}, 57 // //{dir: "benchmark_keystore100", numKeyFiles: 100, resetAll: false, resetCache: false}, 58 // {dir: "benchmark_keystore500", numKeyFiles: 500, resetAll: false, resetCache: true}, 59 // //{dir: "benchmark_keystore500", numKeyFiles: 500, resetAll: false, resetCache: false}, 60 // {dir: "benchmark_keystore1k", numKeyFiles: 1000, resetAll: false, resetCache: true}, 61 // //{dir: "benchmark_keystore1k", numKeyFiles: 1000, resetAll: false, resetCache: false}, 62 // {dir: "benchmark_keystore5k", numKeyFiles: 5000, resetAll: false, resetCache: true}, 63 // //{dir: "benchmark_keystore5k", numKeyFiles: 5000, resetAll: false, resetCache: false}, 64 // {dir: "benchmark_keystore10k", numKeyFiles: 10000, resetAll: false, resetCache: true}, 65 // //{dir: "benchmark_keystore10k", numKeyFiles: 10000, resetAll: false, resetCache: false}, 66 // {dir: "benchmark_keystore20k", numKeyFiles: 20000, resetAll: false, resetCache: true}, 67 // //{dir: "benchmark_keystore20k", numKeyFiles: 20000, resetAll: false, resetCache: false}, 68 // {dir: "benchmark_keystore100k", numKeyFiles: 100000, resetAll: false, resetCache: true}, 69 // //{dir: "benchmark_keystore100k", numKeyFiles: 100000, resetAll: false, resetCache: false}, 70 // {dir: "benchmark_keystore500k", numKeyFiles: 500000, resetAll: false, resetCache: true}, 71 // //{dir: "benchmark_keystore500k", numKeyFiles: 500000, resetAll: false, resetCache: false}, 72 // } 73 // 74 // for _, c := range cases { 75 // b.Run(fmt.Sprintf("KeyFiles#:%v, CacheFromScratch:%v", c.numKeyFiles, c.resetCache), func(b *testing.B) { 76 // am := setupBenchmarkAccountFlowFast(filepath.Join("testdata", c.dir), c.numKeyFiles, c.resetAll, c.resetCache, b) 77 // benchmarkAccountFlowFast(filepath.Join("testdata", c.dir), am, b) 78 // am = nil 79 // }) 80 // } 81 //} 82 // 83 //// Signing an account requires finding the keyfile. 84 //func testAccountSign(am *Manager, account Account, dir string) error { 85 // if _, err := am.SignWithPassphrase(account.Address, "foo", testSigData); err != nil { 86 // return err 87 // } 88 // return nil 89 //} 90 // 91 func testAccountFlow(am *Manager, dir string) error { 92 93 // Create. 94 a, err := am.NewAccount("foo") 95 if err != nil { 96 return err 97 } 98 p, e := filepath.Abs(dir) 99 if e != nil { 100 return fmt.Errorf("could not determine absolute path for temp dir: %v", e) 101 } 102 if !strings.HasPrefix(a.File, p+"/") { 103 return fmt.Errorf("account file %s doesn't have dir prefix; %v", a.File, p) 104 } 105 stat, err := os.Stat(a.File) 106 if err != nil { 107 return fmt.Errorf("account file %s doesn't exist (%v)", a.File, err) 108 } 109 if runtime.GOOS != "windows" && stat.Mode() != 0600 { 110 return fmt.Errorf("account file has wrong mode: got %o, want %o", stat.Mode(), 0600) 111 } 112 if !am.HasAddress(a.Address) { 113 return fmt.Errorf("HasAddres(%x) should've returned true", a.Address) 114 } 115 116 // Update. 117 if err := am.Update(a, "foo", "bar"); err != nil { 118 return fmt.Errorf("Update error: %v", err) 119 } 120 121 // Sign with passphrase. 122 _, err = am.SignWithPassphrase(a.Address, "bar", testSigData) // testSigData is an empty [32]byte established in manager_test.go 123 if err != nil { 124 return fmt.Errorf("should be able to sign from account: %v", err) 125 } 126 127 // Delete. 128 if err := am.DeleteAccount(a, "bar"); err != nil { 129 return fmt.Errorf("DeleteAccount error: %v", err) 130 } 131 if _, err := os.Stat(a.File); err == nil || !os.IsNotExist(err) { 132 return fmt.Errorf("account file %s should be gone after DeleteAccount", a.File) 133 } 134 if am.HasAddress(a.Address) { 135 return fmt.Errorf("HasAddress(%x) should've returned true after DeleteAccount", a.Address) 136 } 137 return nil 138 } 139 140 // 141 //func createTestAccount(am *Manager, dir string) error { 142 // a, err := am.NewAccount("foo") 143 // if err != nil { 144 // return err 145 // } 146 // p, e := filepath.Abs(dir) 147 // if e != nil { 148 // return fmt.Errorf("could not determine absolute path for temp dir: %v", e) 149 // } 150 // if !strings.HasPrefix(a.File, p+"/") { 151 // return fmt.Errorf("account file %s doesn't have dir prefix; %v", a.File, p) 152 // } 153 // stat, err := os.Stat(a.File) 154 // if err != nil { 155 // return fmt.Errorf("account file %s doesn't exist (%v)", a.File, err) 156 // } 157 // if runtime.GOOS != "windows" && stat.Mode() != 0600 { 158 // return fmt.Errorf("account file has wrong mode: got %o, want %o", stat.Mode(), 0600) 159 // } 160 // if !am.HasAddress(a.Address) { 161 // return fmt.Errorf("HasAddres(%x) should've returned true", a.Address) 162 // } 163 // return nil 164 //} 165 // 166 //func getRandomIntN(n int) int { 167 // rand.Seed(time.Now().UTC().UnixNano()) 168 // return int(rand.Int31n(int32(n))) 169 //} 170 // 171 //// Test benchmark for CRUSD/account; create, update, sign, delete. 172 //// Runs against setting of 10, 100, 1000, 10k, (100k, 1m) _existing_ accounts. 173 //func benchmarkAccountSignFast(dir string, am *Manager, accountsN int, b *testing.B) { 174 // for i := 0; i < b.N; i++ { 175 // j := getRandomIntN(accountsN) 176 // b.Logf("signing with account index: %v", j) 177 // account, e := am.AccountByIndex(j) 178 // j = 0 179 // if e != nil { 180 // b.Fatal(e) 181 // } 182 // if e := testAccountSign(am, account, dir); e != nil { 183 // b.Fatalf("error signing with account: %v", e) 184 // } 185 // } 186 //} 187 // 188 //func getFSvsCacheAccountN(dir string, ac *addrCache, b *testing.B) (fN, acN int) { 189 // 190 // files, err := ioutil.ReadDir(ac.keydir) 191 // if err != nil { 192 // b.Fatalf("readdir: %v", err) 193 // } 194 // 195 // acN = len(ac.accounts()) 196 // fN = len(files) - 1 // - 1 because accounts.db is there too 197 // 198 // return fN, acN 199 //} 200 // 201 //func setupBenchmarkAccountFlowFast(dir string, n int, resetAll, resetCache bool, b *testing.B) { 202 // // Optionally: don't remove so we can compound accounts more quickly. 203 // if resetAll { 204 // b.Log("removing testdata keystore") 205 // os.RemoveAll(dir) 206 // } else if resetCache { 207 // b.Log("removing existing cache") 208 // os.Remove(filepath.Join(dir, "accounts.db")) // Remove cache db so we have to set up (scan()) every time. 209 // } else { 210 // b.Log("using existing cache and keystore") 211 // } 212 // 213 // // Ensure any removed dir exists. 214 // if e := os.MkdirAll(dir, os.ModePerm); e != nil { 215 // b.Fatalf("could not mkdir -p '%v': %v", dir, e) 216 // } 217 // 218 // files, err := ioutil.ReadDir(dir) 219 // if err != nil { 220 // b.Fatalf("readdir: %v", err) 221 // } 222 // 223 // ks, e := newKeyStore(dir, veryLightScryptN, veryLightScryptP) 224 // if e != nil { 225 // b.Fatalf("keystore: %v", e) 226 // } 227 // 228 // for i := len(files); i < n+1; i++ { 229 // _, _, err := storeNewKey(ks, "foo") 230 // if err != nil { 231 // b.Fatalf("storenewkey: %v", err) 232 // } 233 // } 234 // ks = nil 235 // files = nil 236 // // 237 // //manStart := time.Now() 238 // //am, err := NewManager(dir, veryLightScryptN, veryLightScryptP) 239 // //if err != nil { 240 // // b.Fatal(err) 241 // //} 242 // // 243 // //am.get.watcher.running = true // cache.watcher.running = true // prevent unexpected reloads 244 // // 245 // //b.Logf("setup time for manager: %v", time.Since(manStart)) 246 // // 247 // //fsN, acN := getFSvsCacheAccountN(dir, am.cache, b) 248 // // 249 // //if acN > fsN { // Can allow greater number of keyfiles, in the case that there are invalids or dupes. 250 // // b.Errorf("accounts/files count mismatch: keyfiles: %v, accounts: %v", fsN, acN) 251 // //} else { 252 // // b.Logf("files: %v, accounts: %v", fsN, acN) 253 // //} 254 // // 255 // //b.Logf("setup time for manager: %v", time.Since(manStart)) 256 // // 257 // //b.ResetTimer() // _benchmark_ timer, not setup timer. 258 // // 259 // //return am 260 //} 261 // 262 //// Test benchmark for CRUSD/account; create, update, sign, delete. 263 //// Runs against setting of 10, 100, 1000, 10k, (100k, 1m) _existing_ accounts. 264 //func benchmarkAccountFlowFast(dir string, am *Manager, b *testing.B) { 265 // for i := 0; i < b.N; i++ { 266 // if e := testAccountFlow(am, dir); e != nil { 267 // b.Fatalf("error setting up account: %v", e) 268 // } 269 // } 270 //} 271 272 func BenchmarkManager_SignWithPassphrase(b *testing.B) { 273 var cases = []struct { 274 numKeyFiles int 275 wantCacheDB, resetCacheDB bool 276 }{ 277 // You can use resetCache: false to save some time if you've already run the benchmark. 278 // Note that if you make any changes to the structure of the cachedb you'll need to 279 // dump and reinitialize accounts.db. 280 {numKeyFiles: 100, wantCacheDB: false, resetCacheDB: false}, 281 {numKeyFiles: 100, wantCacheDB: true, resetCacheDB: false}, 282 {numKeyFiles: 500, wantCacheDB: false, resetCacheDB: false}, 283 {numKeyFiles: 500, wantCacheDB: true, resetCacheDB: false}, 284 {numKeyFiles: 1000, wantCacheDB: false, resetCacheDB: false}, 285 {numKeyFiles: 1000, wantCacheDB: true, resetCacheDB: false}, 286 {numKeyFiles: 5000, wantCacheDB: false, resetCacheDB: false}, 287 {numKeyFiles: 5000, wantCacheDB: true, resetCacheDB: false}, 288 {numKeyFiles: 10000, wantCacheDB: false, resetCacheDB: false}, 289 {numKeyFiles: 10000, wantCacheDB: true, resetCacheDB: false}, 290 {numKeyFiles: 20000, wantCacheDB: false, resetCacheDB: false}, 291 {numKeyFiles: 20000, wantCacheDB: true, resetCacheDB: false}, 292 {numKeyFiles: 100000, wantCacheDB: false, resetCacheDB: false}, 293 {numKeyFiles: 100000, wantCacheDB: true, resetCacheDB: false}, 294 //{numKeyFiles: 200000, wantCacheDB: false, resetCacheDB: false}, 295 {numKeyFiles: 200000, wantCacheDB: true, resetCacheDB: false}, 296 //{numKeyFiles: 500000, wantCacheDB: false, resetCacheDB: false}, 297 {numKeyFiles: 500000, wantCacheDB: true, resetCacheDB: false}, 298 } 299 300 for _, c := range cases { 301 b.Run(fmt.Sprintf("CRUSD:KeyFiles#:%v,DB:%v,reset:%v", c.numKeyFiles, c.wantCacheDB, c.resetCacheDB), func(b *testing.B) { 302 benchmarkManager_SignWithPassphrase(c.numKeyFiles, c.wantCacheDB, c.resetCacheDB, b) 303 }) 304 } 305 } 306 307 func benchmarkManager_SignWithPassphrase(n int, wantcachedb bool, resetcachedb bool, b *testing.B) { 308 309 // 20000 -> 20k 310 staticKeyFilesResourcePath := strconv.Itoa(n) 311 if strings.HasSuffix(staticKeyFilesResourcePath, "000") { 312 staticKeyFilesResourcePath = strings.TrimSuffix(staticKeyFilesResourcePath, "000") 313 staticKeyFilesResourcePath += "k" 314 } 315 316 staticKeyFilesResourcePath = filepath.Join("testdata", "benchmark_keystore"+staticKeyFilesResourcePath) 317 318 if !wantcachedb { 319 p, e := filepath.Abs(staticKeyFilesResourcePath) 320 if e != nil { 321 b.Fatal(e) 322 } 323 staticKeyFilesResourcePath = p 324 } 325 326 start := time.Now() 327 am, me := NewManager(staticKeyFilesResourcePath, veryLightScryptN, veryLightScryptP, wantcachedb) 328 if me != nil { 329 b.Fatal(me) 330 } 331 elapsed := time.Since(start) 332 b.Logf("establishing manager for %v accs: %v", n, elapsed) 333 334 accs := am.Accounts() 335 if !wantcachedb { 336 am.ac.getWatcher().running = true 337 } 338 if len(accs) == 0 { 339 b.Fatal("no accounts") 340 } 341 342 // Set up 1 DNE and 3 existing accs. 343 // Using the last accs because they should take the longest to iterate to. 344 var signAccounts []Account 345 signAccounts = accs[(len(accs) - 4):] 346 accs = nil 347 348 b.ResetTimer() // _benchmark_ timer, not setup timer. 349 350 for i := 0; i < b.N; i++ { 351 for _, a := range signAccounts { 352 if _, e := am.SignWithPassphrase(a.Address, "foo", testSigData); e != nil { 353 b.Errorf("signing with passphrase: %v", e) 354 } 355 } 356 } 357 am.ac.close() 358 am = nil 359 } 360 361 func BenchmarkManagerCRUSD(b *testing.B) { 362 var cases = []struct { 363 numKeyFiles int 364 wantCacheDB, resetCacheDB bool 365 }{ 366 // You can use resetCache: false to save some time if you've already run the benchmark. 367 // Note that if you make any changes to the structure of the cachedb you'll need to 368 // dump and reinitialize accounts.db. 369 {numKeyFiles: 100, wantCacheDB: false, resetCacheDB: false}, 370 {numKeyFiles: 100, wantCacheDB: true, resetCacheDB: false}, 371 {numKeyFiles: 500, wantCacheDB: false, resetCacheDB: false}, 372 {numKeyFiles: 500, wantCacheDB: true, resetCacheDB: false}, 373 {numKeyFiles: 1000, wantCacheDB: false, resetCacheDB: false}, 374 {numKeyFiles: 1000, wantCacheDB: true, resetCacheDB: false}, 375 {numKeyFiles: 5000, wantCacheDB: false, resetCacheDB: false}, 376 {numKeyFiles: 5000, wantCacheDB: true, resetCacheDB: false}, 377 {numKeyFiles: 10000, wantCacheDB: false, resetCacheDB: false}, 378 {numKeyFiles: 10000, wantCacheDB: true, resetCacheDB: false}, 379 {numKeyFiles: 20000, wantCacheDB: false, resetCacheDB: false}, 380 {numKeyFiles: 20000, wantCacheDB: true, resetCacheDB: false}, 381 {numKeyFiles: 100000, wantCacheDB: false, resetCacheDB: false}, 382 {numKeyFiles: 100000, wantCacheDB: true, resetCacheDB: false}, 383 {numKeyFiles: 200000, wantCacheDB: false, resetCacheDB: false}, 384 {numKeyFiles: 200000, wantCacheDB: true, resetCacheDB: false}, 385 {numKeyFiles: 500000, wantCacheDB: false, resetCacheDB: false}, 386 {numKeyFiles: 500000, wantCacheDB: true, resetCacheDB: false}, 387 } 388 389 for _, c := range cases { 390 b.Run(fmt.Sprintf("CRUSD:KeyFiles#:%v,DB:%v,reset:%v", c.numKeyFiles, c.wantCacheDB, c.resetCacheDB), func(b *testing.B) { 391 benchmarkManager_CRUSD(c.numKeyFiles, c.wantCacheDB, c.resetCacheDB, b) 392 }) 393 } 394 } 395 396 func benchmarkManager_CRUSD(n int, wantcachedb bool, resetcachedb bool, b *testing.B) { 397 398 // 20000 -> 20k 399 staticKeyFilesResourcePath := strconv.Itoa(n) 400 if strings.HasSuffix(staticKeyFilesResourcePath, "000") { 401 staticKeyFilesResourcePath = strings.TrimSuffix(staticKeyFilesResourcePath, "000") 402 staticKeyFilesResourcePath += "k" 403 } 404 405 staticKeyFilesResourcePath = filepath.Join("testdata", "benchmark_keystore"+staticKeyFilesResourcePath) 406 407 if !wantcachedb { 408 p, e := filepath.Abs(staticKeyFilesResourcePath) 409 if e != nil { 410 b.Fatal(e) 411 } 412 staticKeyFilesResourcePath = p 413 } 414 415 if resetcachedb { 416 os.Remove(filepath.Join(staticKeyFilesResourcePath, "accounts.db")) 417 } 418 419 start := time.Now() 420 am, me := NewManager(staticKeyFilesResourcePath, veryLightScryptN, veryLightScryptP, wantcachedb) 421 if !wantcachedb { 422 am.ac.getWatcher().running = true 423 } 424 425 if me != nil { 426 b.Fatal(me) 427 } 428 elapsed := time.Since(start) 429 b.Logf("establishing manager for %v accs: %v", n, elapsed) 430 431 b.ResetTimer() // _benchmark_ timer, not setup timer. 432 433 for i := 0; i < b.N; i++ { 434 if e := testAccountFlow(am, staticKeyFilesResourcePath); e != nil { 435 b.Errorf("account flow (CRUSD): %v (db: %v)", e, wantcachedb) 436 } 437 } 438 am.ac.close() 439 am = nil 440 }