diff options
| author | INADA Naoki <songofacandy@gmail.com> | 2015-01-23 20:02:37 +0900 |
|---|---|---|
| committer | Mikio Hara <mikioh.mikioh@gmail.com> | 2015-01-24 09:56:25 +0000 |
| commit | 1b61a97811626d4c7a8332c107f1e091253d1b2e (patch) | |
| tree | 9002287335392b34c69efa92cc023ea3a49be835 /src/database/sql/sql_test.go | |
| parent | 3acb9fd98e41014b3958cd11ba599385c4eab9cc (diff) | |
| download | go-1b61a97811626d4c7a8332c107f1e091253d1b2e.tar.xz | |
database/sql: reduce lock contention in Stmt.connStmt
Previouslly, Stmt.connStmt calls DB.connIfFree on each Stmt.css.
Since Stmt.connStmt locks Stmt.mu, a concurrent use of Stmt causes lock
contention on Stmt.mu.
Additionally, DB.connIfFree locks DB.mu which is shared by DB.addDep and
DB.removeDep.
This change removes DB.connIfFree and makes use of a first unused
connection in idle connection pool to reduce lock contention
without making it complicated.
Fixes #9484
On EC2 c3.8xlarge (E5-2680 v2 @ 2.80GHz * 32 vCPU):
benchmark old ns/op new ns/op delta
BenchmarkManyConcurrentQuery-8 40249 34721 -13.73%
BenchmarkManyConcurrentQuery-16 45610 40176 -11.91%
BenchmarkManyConcurrentQuery-32 109831 43179 -60.69%
benchmark old allocs new allocs delta
BenchmarkManyConcurrentQuery-8 25 25 +0.00%
BenchmarkManyConcurrentQuery-16 25 25 +0.00%
BenchmarkManyConcurrentQuery-32 25 25 +0.00%
benchmark old bytes new bytes delta
BenchmarkManyConcurrentQuery-8 3980 3969 -0.28%
BenchmarkManyConcurrentQuery-16 3980 3982 +0.05%
BenchmarkManyConcurrentQuery-32 3993 3990 -0.08%
Change-Id: Ic96296922c465bac38a260018c58324dae1531d9
Reviewed-on: https://go-review.googlesource.com/2207
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Diffstat (limited to 'src/database/sql/sql_test.go')
| -rw-r--r-- | src/database/sql/sql_test.go | 78 |
1 files changed, 28 insertions, 50 deletions
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index 34efdf254c..60bdefa076 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -1764,56 +1764,6 @@ func doConcurrentTest(t testing.TB, ct concurrentTest) { wg.Wait() } -func manyConcurrentQueries(t testing.TB) { - maxProcs, numReqs := 16, 500 - if testing.Short() { - maxProcs, numReqs = 4, 50 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) - - db := newTestDB(t, "people") - defer closeDB(t, db) - - stmt, err := db.Prepare("SELECT|people|name|") - if err != nil { - t.Fatal(err) - } - defer stmt.Close() - - var wg sync.WaitGroup - wg.Add(numReqs) - - reqs := make(chan bool) - defer close(reqs) - - for i := 0; i < maxProcs*2; i++ { - go func() { - for range reqs { - rows, err := stmt.Query() - if err != nil { - t.Errorf("error on query: %v", err) - wg.Done() - continue - } - - var name string - for rows.Next() { - rows.Scan(&name) - } - rows.Close() - - wg.Done() - } - }() - } - - for i := 0; i < numReqs; i++ { - reqs <- true - } - - wg.Wait() -} - func TestIssue6081(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) @@ -1985,3 +1935,31 @@ func BenchmarkConcurrentRandom(b *testing.B) { doConcurrentTest(b, ct) } } + +func BenchmarkManyConcurrentQueries(b *testing.B) { + b.ReportAllocs() + // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required. + const parallelism = 16 + + db := newTestDB(b, "magicquery") + defer closeDB(b, db) + db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism) + + stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") + if err != nil { + b.Fatal(err) + } + defer stmt.Close() + + b.SetParallelism(parallelism) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + rows, err := stmt.Query("sleep", 1) + if err != nil { + b.Error(err) + return + } + rows.Close() + } + }) +} |
