Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(181)

Side by Side Diff: src/pkg/testing/benchmark.go

Issue 96910043: code review 96910043: testing: RunParallel and SetParallelism are misleading. (Closed)
Patch Set: diff -r 7f529f73708a http://code.google.com/p/go Created 9 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/sync/waitgroup_test.go ('k') | src/pkg/testing/benchmark_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package testing 5 package testing
6 6
7 import ( 7 import (
8 "flag" 8 "flag"
9 "fmt" 9 "fmt"
10 "os" 10 "os"
(...skipping 25 matching lines...) Expand all
36 type B struct { 36 type B struct {
37 common 37 common
38 N int 38 N int
39 previousN int // number of iterations in the previous r un 39 previousN int // number of iterations in the previous r un
40 previousDuration time.Duration // total duration of the previous run 40 previousDuration time.Duration // total duration of the previous run
41 benchmark InternalBenchmark 41 benchmark InternalBenchmark
42 bytes int64 42 bytes int64
43 timerOn bool 43 timerOn bool
44 showAllocResult bool 44 showAllocResult bool
45 result BenchmarkResult 45 result BenchmarkResult
46 » parallelism int // RunParallel creates parallelism*GOMAXPROCS gorou tines 46 » concurrency int // RunConcurrent creates concurrency*GOMAXPROCS gor outines
47 // The initial states of memStats.Mallocs and memStats.TotalAlloc. 47 // The initial states of memStats.Mallocs and memStats.TotalAlloc.
48 startAllocs uint64 48 startAllocs uint64
49 startBytes uint64 49 startBytes uint64
50 // The net total of this test after being run. 50 // The net total of this test after being run.
51 netAllocs uint64 51 netAllocs uint64
52 netBytes uint64 52 netBytes uint64
53 } 53 }
54 54
55 // StartTimer starts timing a test. This function is called automatically 55 // StartTimer starts timing a test. This function is called automatically
56 // before a benchmark starts, but it can also used to resume timing after 56 // before a benchmark starts, but it can also used to resume timing after
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 } 111 }
112 112
113 // runN runs a single benchmark for the specified number of iterations. 113 // runN runs a single benchmark for the specified number of iterations.
114 func (b *B) runN(n int) { 114 func (b *B) runN(n int) {
115 benchmarkLock.Lock() 115 benchmarkLock.Lock()
116 defer benchmarkLock.Unlock() 116 defer benchmarkLock.Unlock()
117 // Try to get a comparable environment for each run 117 // Try to get a comparable environment for each run
118 // by clearing garbage from previous runs. 118 // by clearing garbage from previous runs.
119 runtime.GC() 119 runtime.GC()
120 b.N = n 120 b.N = n
121 » b.parallelism = 1 121 » b.concurrency = 1
122 b.ResetTimer() 122 b.ResetTimer()
123 b.StartTimer() 123 b.StartTimer()
124 b.benchmark.F(b) 124 b.benchmark.F(b)
125 b.StopTimer() 125 b.StopTimer()
126 b.previousN = n 126 b.previousN = n
127 b.previousDuration = b.duration 127 b.previousDuration = b.duration
128 } 128 }
129 129
130 func min(x, y int) int { 130 func min(x, y int) int {
131 if x > y { 131 if x > y {
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 if b.output[j] == '\n' { 343 if b.output[j] == '\n' {
344 nlCount++ 344 nlCount++
345 if nlCount >= maxNewlines { 345 if nlCount >= maxNewlines {
346 b.output = append(b.output[:j], "\n\t... [output truncated]\n"...) 346 b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
347 break 347 break
348 } 348 }
349 } 349 }
350 } 350 }
351 } 351 }
352 352
353 // A PB is used by RunParallel for running parallel benchmarks. 353 // A PB is used by RunConcurrent for running parallel benchmarks.
354 type PB struct { 354 type PB struct {
355 globalN *uint64 // shared between all worker goroutines iteration counte r 355 globalN *uint64 // shared between all worker goroutines iteration counte r
356 grain uint64 // acquire that many iterations from globalN at once 356 grain uint64 // acquire that many iterations from globalN at once
357 cache uint64 // local cache of acquired iterations 357 cache uint64 // local cache of acquired iterations
358 bN uint64 // total number of iterations to execute (b.N) 358 bN uint64 // total number of iterations to execute (b.N)
359 } 359 }
360 360
361 // Next reports whether there are more iterations to execute. 361 // Next reports whether there are more iterations to execute.
362 func (pb *PB) Next() bool { 362 func (pb *PB) Next() bool {
363 if pb.cache == 0 { 363 if pb.cache == 0 {
364 n := atomic.AddUint64(pb.globalN, pb.grain) 364 n := atomic.AddUint64(pb.globalN, pb.grain)
365 if n <= pb.bN { 365 if n <= pb.bN {
366 pb.cache = pb.grain 366 pb.cache = pb.grain
367 } else if n < pb.bN+pb.grain { 367 } else if n < pb.bN+pb.grain {
368 pb.cache = pb.bN + pb.grain - n 368 pb.cache = pb.bN + pb.grain - n
369 } else { 369 } else {
370 return false 370 return false
371 } 371 }
372 } 372 }
373 pb.cache-- 373 pb.cache--
374 return true 374 return true
375 } 375 }
376 376
377 // RunParallel runs a benchmark in parallel. 377 // RunConcurrent distributes benchmark runs among a set of goroutines.
378 // It creates multiple goroutines and distributes b.N iterations among them. 378 // RunConcurrent measures how a benchmark scales with increasing concurrecy. It
379 // The number of goroutines defaults to GOMAXPROCS. To increase parallelism for 379 // is usually used with the go test -cpu flag to measure scaling with increasing
380 // non-CPU-bound benchmarks, call SetParallelism before RunParallel. 380 // parallelism.
381 // RunParallel is usually used with the go test -cpu flag. 381 //
382 // By default, RunConcurrent creates GOMAXPROCS goroutines and distributes b.N
383 // iterations among them. The number of goroutines can be changed by calling
384 // SetConcurrency before running RunConcurrent.
382 // 385 //
383 // The body function will be run in each goroutine. It should set up any 386 // The body function will be run in each goroutine. It should set up any
384 // goroutine-local state and then iterate until pb.Next returns false. 387 // goroutine-local state and then iterate until pb.Next returns false.
385 // It should not use the StartTimer, StopTimer, or ResetTimer functions, 388 // It should not use the StartTimer, StopTimer, or ResetTimer functions,
386 // because they have global effect. 389 // because they have global effect.
387 func (b *B) RunParallel(body func(*PB)) { 390 func (b *B) RunConcurrent(body func(*PB)) {
388 // Calculate grain size as number of iterations that take ~100µs. 391 // Calculate grain size as number of iterations that take ~100µs.
389 // 100µs is enough to amortize the overhead and provide sufficient 392 // 100µs is enough to amortize the overhead and provide sufficient
390 // dynamic load balancing. 393 // dynamic load balancing.
391 grain := uint64(0) 394 grain := uint64(0)
392 if b.previousN > 0 && b.previousDuration > 0 { 395 if b.previousN > 0 && b.previousDuration > 0 {
393 grain = 1e5 * uint64(b.previousN) / uint64(b.previousDuration) 396 grain = 1e5 * uint64(b.previousN) / uint64(b.previousDuration)
394 } 397 }
395 if grain < 1 { 398 if grain < 1 {
396 grain = 1 399 grain = 1
397 } 400 }
398 // We expect the inner loop and function call to take at least 10ns, 401 // We expect the inner loop and function call to take at least 10ns,
399 // so do not do more than 100µs/10ns=1e4 iterations. 402 // so do not do more than 100µs/10ns=1e4 iterations.
400 if grain > 1e4 { 403 if grain > 1e4 {
401 grain = 1e4 404 grain = 1e4
402 } 405 }
403 406
404 n := uint64(0) 407 n := uint64(0)
405 » numProcs := b.parallelism * runtime.GOMAXPROCS(0) 408 » numProcs := b.concurrency * runtime.GOMAXPROCS(0)
406 var wg sync.WaitGroup 409 var wg sync.WaitGroup
407 wg.Add(numProcs) 410 wg.Add(numProcs)
408 for p := 0; p < numProcs; p++ { 411 for p := 0; p < numProcs; p++ {
409 go func() { 412 go func() {
410 defer wg.Done() 413 defer wg.Done()
411 pb := &PB{ 414 pb := &PB{
412 globalN: &n, 415 globalN: &n,
413 grain: grain, 416 grain: grain,
414 bN: uint64(b.N), 417 bN: uint64(b.N),
415 } 418 }
416 body(pb) 419 body(pb)
417 }() 420 }()
418 } 421 }
419 wg.Wait() 422 wg.Wait()
420 if n <= uint64(b.N) && !b.Failed() { 423 if n <= uint64(b.N) && !b.Failed() {
421 » » b.Fatal("RunParallel: body exited without pb.Next() == false") 424 » » b.Fatal("RunConcurrent: body exited without pb.Next() == false")
422 } 425 }
423 } 426 }
424 427
425 // SetParallelism sets the number of goroutines used by RunParallel to p*GOMAXPR OCS. 428 // SetConcurrency sets the number of goroutines used by RunConcurrent to
426 // There is usually no need to call SetParallelism for CPU-bound benchmarks. 429 // p*GOMAXPROCS. There is usually no need to call SetConcurrency for CPU-bound
427 // If p is less than 1, this call will have no effect. 430 // benchmarks. If p is less than 1, this call will have no effect.
428 func (b *B) SetParallelism(p int) { 431 func (b *B) SetConcurrency(p int) {
429 if p >= 1 { 432 if p >= 1 {
430 » » b.parallelism = p 433 » » b.concurrency = p
431 } 434 }
432 } 435 }
433 436
434 // Benchmark benchmarks a single function. Useful for creating 437 // Benchmark benchmarks a single function. Useful for creating
435 // custom benchmarks that do not use the "go test" command. 438 // custom benchmarks that do not use the "go test" command.
436 func Benchmark(f func(b *B)) BenchmarkResult { 439 func Benchmark(f func(b *B)) BenchmarkResult {
437 b := &B{ 440 b := &B{
438 common: common{ 441 common: common{
439 signal: make(chan interface{}), 442 signal: make(chan interface{}),
440 }, 443 },
441 benchmark: InternalBenchmark{"", f}, 444 benchmark: InternalBenchmark{"", f},
442 } 445 }
443 return b.run() 446 return b.run()
444 } 447 }
OLDNEW
« no previous file with comments | « src/pkg/sync/waitgroup_test.go ('k') | src/pkg/testing/benchmark_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b