Skip to content

Commit e342c25

Browse files
committed
initial release 0.1.0
1 parent 5a2dd67 commit e342c25

File tree

18 files changed

+3514
-177
lines changed

18 files changed

+3514
-177
lines changed

.github/workflows/test.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
on: [push, pull_request]
2+
name: Test
3+
jobs:
4+
test:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Install Go
8+
uses: actions/setup-go@v4
9+
with:
10+
go-version: '^1.21.0'
11+
- name: Checkout code
12+
uses: actions/checkout@v3
13+
- uses: actions/cache@v3
14+
with:
15+
path: ~/go/pkg/mod
16+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
17+
restore-keys: |
18+
${{ runner.os }}-go-
19+
- name: Test
20+
run: make test

LICENSE

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
VERSION=$(shell cat VERSION)
2+
LDFLAGS=-ldflags "-X main.version=$(VERSION)"
3+
4+
.PHONY: build
5+
build:
6+
go build $(LDFLAGS) -trimpath -o go-sysbench cmd/go-sysbench/main.go
7+
8+
.PHONY: lint
9+
lint:
10+
golangci-lint run -v
11+
12+
.PHONY: test
13+
test:
14+
go test -coverprofile=coverage.txt -covermode=atomic -v -race ./...

README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# go-sysbench
2+
3+
[![Go Report Card](https://goreportcard.com/badge/github.com/samitani/go-sysbench)](https://goreportcard.com/report/github.com/samitani/go-sysbench)
4+
[![License](https://img.shields.io/badge/license-GPLv2-blue.svg)](LICENSE)
5+
6+
Yet another sysbench written in Golang
7+
8+
`go-sysbench` runs the same SQL as `sysbench` and reports the results in the same format as `sysbench`.
9+
`go-sysbench` cannot do as many things as `sysbench`, but it offers more customizability for those who are familiar with Golang.
10+
11+
I would like to thank Peter Zaitsev, Alexy Kopytov and contributors for inventing great tool [sysbench](https://github.com/akopytov/sysbench).
12+
13+
## Usage
14+
15+
### Install
16+
17+
```
18+
go install github.com/samitani/go-sysbench/cmd/go-sysbench@latest
19+
```
20+
21+
### Run benchmark
22+
1. Create a database to run benchmark.
23+
```
24+
mysql> CREATE DATABASE sbtest;
25+
```
26+
2. Execute prepare command to create tables and records.
27+
```
28+
$ go-sysbench --tables=1 --mysql-user=appuser --mysql-password=Password --time=360 --threads=5 --table_size=10000 --report-interval=1 --histogram=on oltp_read_write prepare
29+
```
30+
3. Run benchmark
31+
In this example, It will run the benchmark for 360 seconds with 5 threads.
32+
```
33+
$ go-sysbench --tables=1 --mysql-user=appuser --mysql-password=Password --time=360 --threads=5 --table_size=10000 --report-interval=1 --histogram=on oltp_read_write run
34+
```
35+
36+
### Options
37+
38+
```
39+
Usage:
40+
go-sysbench [options]... [oltp_read_only|oltp_read_write] [prepare|run]
41+
42+
Application Options:
43+
--version show version
44+
--tables= number of tables (default: 1)
45+
--table_size= number of rows per table (default: 10000)
46+
--table-size= alias of --table_size
47+
--db-driver=[mysql|pgsql|spanner] specifies database driver to use (default: mysql)
48+
--db-ps-mode=[auto|disable] prepared statements usage mode (default: auto)
49+
--threads= number of threads to use (default: 1)
50+
--events= limit for total number of events (default: 0)
51+
--time= limit for total execution time in seconds (default: 10)
52+
--report-interval= periodically report intermediate statistics with a specified interval in seconds. 0 disables intermediate reports (default: 0)
53+
--histogram=[on|off] print latency histogram in report (default: off)
54+
--percentile= percentile to calculate in latency statistics (1-100) (default: 95)
55+
56+
MySQL:
57+
--mysql-host= MySQL server host (default: localhost)
58+
--mysql-port= MySQL server port (default: 3306)
59+
--mysql-user= MySQL user (default: sbtest)
60+
--mysql-password= MySQL password [$MYSQL_PWD]
61+
--mysql-db= MySQL database name (default: sbtest)
62+
--mysql-ssl=[on|off] use SSL connections (default: off)
63+
--mysql-ignore-errors= list of errors to ignore, or "all" (default: 1213,1020,1205)
64+
65+
PostgreSQL:
66+
--pgsql-host= PostgreSQL server host (default: localhost)
67+
--pgsql-port= PostgreSQL server port (default: 5432)
68+
--pgsql-user= PostgreSQL user (default: sbtest)
69+
--pgsql-password= PostgreSQL password [$PGPASSWORD]
70+
--pgsql-db= PostgreSQL database name (default: sbtest)
71+
--pgsql-ssl=[on|off] use SSL connections (default: off)
72+
--pgsql-ignore-errors= list of errors to ignore, or "all" (default: 40P01,23505,40001)
73+
74+
Spanner:
75+
--spanner-project= Spanner Google Cloud project name
76+
--spanner-instance= Spanner instance id
77+
--spanner-db= Spanner database name (default: sbtest)
78+
79+
Help Options:
80+
-h, --help Show this help message
81+
```
82+
83+
## Incompatibility with sysbench
84+
85+
* `go-sysbench` supports only `oltp_read_only` and `oltp_read_write` database benchmarks. Linux benchmarks such as `fileio`, `cpu`, `memory` are not supported.
86+
* Some options are not implemented. See Options section above.
87+
* Number of reconnects is not reported.
88+
* Lua scripts is not supported. To customize the benchmark scenario, you have to edit the code directly.
89+
90+
## Additional feature
91+
92+
### Google Cloud Spanner
93+
94+
`go-sysbench` supports Google Cloud Spanner with Google Standard SQL.
95+
Cloud Spanner is prone to lock contention. You need to increase the number of records to avoid lock contention.
96+
```
97+
$ gcloud auth login --update-adc
98+
$ go-sysbench oltp_read_write run --db-driver=spanner --spanner-project=YOUR-PROJECT --spanner-instance=YOUR-INSTANCE-NAME --table_size=1000000
99+
```
100+
101+
In Spanner benchmark, `ErrAbortedDueToConcurrentModification` error is ignored.

VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.1.0

benchmark/benchmark.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package benchmark
2+
3+
import (
4+
"context"
5+
"fmt"
6+
)
7+
8+
const (
9+
DBDriverMySQL = "mysql"
10+
DBDriverPgSQL = "pgsql"
11+
DBDriverSpanner = "spanner"
12+
)
13+
14+
type (
15+
Benchmark interface {
16+
// initialize before both Prepare and Event
17+
Init(context.Context) error
18+
// finalize after both Prepare and Event
19+
Done() error
20+
// when prepare command is issued
21+
Prepare(context.Context) error
22+
// when run command is issued, PreEvent() is called once in a benchmark
23+
PreEvent(context.Context) error
24+
// when run command is issued, Event() is called in a loop
25+
Event(context.Context) (numReads, numWrites, numOthers, numIgnoredErros uint64, err error)
26+
}
27+
CommonOpts struct {
28+
Tables int `long:"tables" description:"number of tables" default:"1"`
29+
TableSize int `long:"table_size" description:"number of rows per table" default:"10000"`
30+
TableSizeP int `long:"table-size" description:"alias of --table_size"`
31+
DBDriver string `long:"db-driver" choice:"mysql" choice:"pgsql" choice:"spanner" description:"specifies database driver to use" default:"mysql"` //nolint:staticcheck
32+
DBPreparedStmt string `long:"db-ps-mode" choice:"auto" choice:"disable" description:"prepared statements usage mode" default:"auto"` //nolint:staticcheck
33+
}
34+
BenchmarkOpts struct {
35+
CommonOpts
36+
MySQLOpts `group:"MySQL" description:"MySQL options"`
37+
PgSQLOpts `group:"PostgreSQL" description:"PostgreSQL options"`
38+
SpannerOpts `group:"Spanner" description:"Google Cloud Spanner options"`
39+
}
40+
)
41+
42+
func BenchmarkFactory(testname string, opt *BenchmarkOpts) (Benchmark, error) {
43+
if opt.TableSizeP != 0 {
44+
opt.TableSize = opt.TableSizeP
45+
}
46+
47+
if testname == NameOLTPReadOnly {
48+
return newOLTPBench(opt, rwModeReadOnly), nil
49+
} else if testname == NameOLTPReadWrite {
50+
return newOLTPBench(opt, rwModeReadWrite), nil
51+
}
52+
return nil, fmt.Errorf("Unknown benchmark: %s", testname)
53+
54+
}
55+
56+
func BenchmarkNames() []string {
57+
return []string{NameOLTPReadOnly, NameOLTPReadWrite}
58+
}

0 commit comments

Comments
 (0)