Skip to content

Commit

Permalink
use table output for better user experience (#130)
Browse files Browse the repository at this point in the history
* add support for output style

* update go.mod
  • Loading branch information
sillydong authored Aug 16, 2022
1 parent 9eabfb9 commit 062d2d7
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 47 deletions.
36 changes: 25 additions & 11 deletions ch/workload.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ch

import (
"bytes"
"context"
"database/sql"
"fmt"
Expand All @@ -10,6 +9,7 @@ import (
"time"

"github.com/pingcap/go-tpc/pkg/measurement"
"github.com/pingcap/go-tpc/pkg/util"
"github.com/pingcap/go-tpc/pkg/workload"
"github.com/pingcap/go-tpc/tpch"
"github.com/pingcap/go-tpc/tpch/dbgen"
Expand All @@ -35,6 +35,9 @@ type Config struct {
CreateTiFlashReplica bool
AnalyzeTable analyzeConfig
RefreshConnWait time.Duration

// output style
OutputStyle string
}

type chState struct {
Expand Down Expand Up @@ -214,7 +217,7 @@ func (w Workloader) Check(ctx context.Context, threadID int) error {
return nil
}

func outputRtMeasurement(prefix string, opMeasurement map[string]*measurement.Histogram) {
func outputRtMeasurement(outputStyle string, prefix string, opMeasurement map[string]*measurement.Histogram) {
keys := make([]string, len(opMeasurement))
var i = 0
for k := range opMeasurement {
Expand All @@ -223,27 +226,38 @@ func outputRtMeasurement(prefix string, opMeasurement map[string]*measurement.Hi
}
sort.Strings(keys)

lines := [][]string{}
for _, op := range keys {
hist := opMeasurement[op]
if !hist.Empty() {
fmt.Printf("%s%-6s - %s\n", prefix, strings.ToUpper(op), chSummary(hist))
line := []string{prefix, strings.ToUpper(op)}
line = append(line, chSummary(hist)...)
lines = append(lines, line)
}
}
switch outputStyle {
case util.OutputStylePlain:
util.RenderString("%s%-6s - %s\n", []string{"Prefix", "Operation", "Count", "Sum(ms)", "Avg(ms)"}, lines)
case util.OutputStyleTable:
util.RenderTable([]string{"Prefix", "Operation", "Count", "Sum(ms)", "Avg(ms)"}, lines)
case util.OutputStyleJson:
util.RenderJson([]string{"Prefix", "Operation", "Count", "Sum(ms)", "Avg(ms)"}, lines)

}
}

func chSummary(h *measurement.Histogram) string {
func chSummary(h *measurement.Histogram) []string {
res := h.GetInfo()

buf := new(bytes.Buffer)
buf.WriteString(fmt.Sprintf("Count: %d, ", res.Count))
buf.WriteString(fmt.Sprintf("Sum(ms): %.1f, ", res.Sum))
buf.WriteString(fmt.Sprintf("Avg(ms): %.1f", res.Avg))

return buf.String()
return []string{
util.IntToString(res.Count),
util.FloatToOneString(res.Sum),
util.FloatToOneString(res.Avg),
}
}

func (w Workloader) OutputStats(ifSummaryReport bool) {
w.measurement.Output(ifSummaryReport, outputRtMeasurement)
w.measurement.Output(ifSummaryReport, w.cfg.OutputStyle, outputRtMeasurement)
if ifSummaryReport {
var count int64
var elapsed float64
Expand Down
2 changes: 2 additions & 0 deletions cmd/go-tpc/ch_benchmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ func executeCH(action string) {
openDB()
defer closeDB()

tpccConfig.OutputStyle = outputStyle
tpccConfig.DBName = dbName
tpccConfig.Threads = threads
tpccConfig.Isolation = isolationLevel
chConfig.OutputStyle = outputStyle
chConfig.DBName = dbName
chConfig.QueryNames = strings.Split(chConfig.RawQueries, ",")

Expand Down
3 changes: 3 additions & 0 deletions cmd/go-tpc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"syscall"
"time"

"github.com/pingcap/go-tpc/pkg/util"
"github.com/spf13/cobra"

// mysql package
Expand All @@ -36,6 +37,7 @@ var (
metricsAddr string
maxProcs int
connParams string
outputStyle string

globalDB *sql.DB
globalCtx context.Context
Expand Down Expand Up @@ -113,6 +115,7 @@ func main() {
2: ReadCommitted, 3: WriteCommitted, 4: RepeatableRead,
5: Snapshot, 6: Serializable, 7: Linerizable`)
rootCmd.PersistentFlags().StringVar(&connParams, "conn-params", "", "session variables")
rootCmd.PersistentFlags().StringVar(&outputStyle, "output", util.OutputStylePlain, "output style, valid values can be { plain | table | json }")

cobra.EnablePrefixMatching = true

Expand Down
1 change: 1 addition & 0 deletions cmd/go-tpc/rawsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func execRawsql(action string) {
os.Exit(1)
}

rawsqlConfig.OutputStyle = outputStyle
rawsqlConfig.DBName = dbName
rawsqlConfig.QueryNames = strings.Split(queryFiles, ",")
rawsqlConfig.Queries = make(map[string]string, len(rawsqlConfig.QueryNames))
Expand Down
1 change: 1 addition & 0 deletions cmd/go-tpc/tpcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func executeTpcc(action string) {
openDB()
defer closeDB()

tpccConfig.OutputStyle = outputStyle
tpccConfig.DBName = dbName
tpccConfig.Threads = threads
tpccConfig.Isolation = isolationLevel
Expand Down
1 change: 1 addition & 0 deletions cmd/go-tpc/tpch.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func executeTpch(action string) {
os.Exit(1)
}

tpchConfig.OutputStyle = outputStyle
tpchConfig.DBName = dbName
tpchConfig.PrepareThreads = threads
tpchConfig.QueryNames = strings.Split(tpchConfig.RawQueries, ",")
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/HdrHistogram/hdrhistogram-go v1.0.0
github.com/go-sql-driver/mysql v1.5.0
github.com/jedib0t/go-pretty v4.3.0+incompatible
github.com/olekukonko/tablewriter v0.0.5
github.com/prometheus/client_golang v0.9.3
github.com/spf13/cobra v1.0.0
github.com/stretchr/testify v1.6.1
Expand All @@ -22,7 +23,7 @@ require (
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/mattn/go-runewidth v0.0.7 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.3.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
Expand Down Expand Up @@ -270,6 +270,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
github.com/nishanths/exhaustive v0.0.0-20200811152831-6cf413ae40e0/go.mod h1:wBEpHwM2OdmeNpdCvRPUlkEbBuaFmcK4Wv8Q7FuGW3c=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
Expand Down
30 changes: 15 additions & 15 deletions pkg/measurement/hist.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package measurement

import (
"bytes"
"fmt"
"sync"
"time"

"github.com/HdrHistogram/hdrhistogram-go"
"github.com/pingcap/go-tpc/pkg/util"
)

type Histogram struct {
Expand Down Expand Up @@ -56,22 +56,22 @@ func (h *Histogram) Empty() bool {
return h.TotalCount() == 0
}

func (h *Histogram) Summary() string {
func (h *Histogram) Summary() []string {
res := h.GetInfo()
buf := new(bytes.Buffer)
buf.WriteString(fmt.Sprintf("Takes(s): %.1f, ", res.Elapsed))
buf.WriteString(fmt.Sprintf("Count: %d, ", res.Count))
buf.WriteString(fmt.Sprintf("TPM: %.1f, ", res.Ops*60))
buf.WriteString(fmt.Sprintf("Sum(ms): %.1f, ", res.Sum))
buf.WriteString(fmt.Sprintf("Avg(ms): %.1f, ", res.Avg))
buf.WriteString(fmt.Sprintf("50th(ms): %.1f, ", res.P50))
buf.WriteString(fmt.Sprintf("90th(ms): %.1f, ", res.P90))
buf.WriteString(fmt.Sprintf("95th(ms): %.1f, ", res.P95))
buf.WriteString(fmt.Sprintf("99th(ms): %.1f, ", res.P99))
buf.WriteString(fmt.Sprintf("99.9th(ms): %.1f, ", res.P999))
buf.WriteString(fmt.Sprintf("Max(ms): %.1f", res.Max))

return buf.String()
return []string{
util.FloatToOneString(res.Elapsed),
util.IntToString(res.Count),
util.FloatToOneString(res.Ops * 60),
util.FloatToOneString(res.Sum),
util.FloatToOneString(res.Avg),
util.FloatToOneString(res.P50),
util.FloatToOneString(res.P90),
util.FloatToOneString(res.P95),
util.FloatToOneString(res.P99),
util.FloatToOneString(res.P999),
util.FloatToOneString(res.Max),
}
}

func (h *Histogram) GetInfo() HistInfo {
Expand Down
2 changes: 1 addition & 1 deletion pkg/measurement/hist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ func TestHist(t *testing.T) {
}
h.Measure(time.Minute * 9)
h.Measure(time.Minute * 8)
t.Logf(h.Summary())
t.Logf("%+v", h.Summary())
}
6 changes: 3 additions & 3 deletions pkg/measurement/measure.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,18 @@ func (m *Measurement) getOpName() []string {
}

// Output prints the measurement summary.
func (m *Measurement) Output(ifSummaryReport bool, outputFunc func(string, map[string]*Histogram)) {
func (m *Measurement) Output(ifSummaryReport bool, outputStyle string, outputFunc func(string, string, map[string]*Histogram)) {
if ifSummaryReport {
m.RLock()
defer m.RUnlock()
outputFunc("[Summary] ", m.OpSumMeasurement)
outputFunc(outputStyle, "[Summary] ", m.OpSumMeasurement)
return
}
// Clear current measure data every time
var opCurMeasurement = m.takeCurMeasurement()
m.RLock()
defer m.RUnlock()
outputFunc("[Current] ", opCurMeasurement)
outputFunc(outputStyle, "[Current] ", opCurMeasurement)
}

// EnableWarmUp sets whether to enable warm-up.
Expand Down
86 changes: 86 additions & 0 deletions pkg/util/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package util

import (
"bytes"
"encoding/json"
"fmt"
"os"
"strings"

"github.com/olekukonko/tablewriter"
)

// output style
const (
OutputStylePlain = "plain"
OutputStyleTable = "table"
OutputStyleJson = "json"
)

func RenderString(format string, headers []string, values [][]string) {
if len(values) == 0 {
return
}
if len(headers) == 0 {
for _, value := range values {
args := make([]interface{}, len(value))
for i, v := range value {
args[i] = v
}
fmt.Printf(format, args...)
}
return
}

buf := new(bytes.Buffer)
for _, value := range values {
args := make([]string, len(headers)-2)
for i, header := range headers[2:] {
args[i] = header + ": " + value[i+2]
}
buf.WriteString(fmt.Sprintf(format, value[0], value[1], strings.Join(args, ", ")))
}
fmt.Print(buf.String())
}

func RenderTable(headers []string, values [][]string) {
if len(values) == 0 {
return
}
tb := tablewriter.NewWriter(os.Stdout)
tb.SetHeader(headers)
tb.AppendBulk(values)
tb.Render()
}

func RenderJson(headers []string, values [][]string) {
if len(values) == 0 {
return
}
data := make([]map[string]string, 0, len(values))
for _, value := range values {
line := make(map[string]string, 0)
for i, header := range headers {
line[header] = value[i]
}
data = append(data, line)
}
outStr, err := json.Marshal(data)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(outStr))
}

func IntToString(i int64) string {
return fmt.Sprintf("%d", i)
}

func FloatToOneString(f float64) string {
return fmt.Sprintf("%.1f", f)
}

func FloatToTwoString(f float64) string {
return fmt.Sprintf("%.2f", f)
}
19 changes: 16 additions & 3 deletions rawsql/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type Config struct {
QueryNames []string
ExecExplainAnalyze bool
RefreshWait time.Duration

// output style
OutputStyle string
}

type rawsqlState struct {
Expand Down Expand Up @@ -117,7 +120,7 @@ func (w *Workloader) Run(ctx context.Context, threadID int) error {
return nil
}

func outputMeasurement(prefix string, opMeasurement map[string]*measurement.Histogram) {
func outputMeasurement(outputStyle string, prefix string, opMeasurement map[string]*measurement.Histogram) {
keys := make([]string, len(opMeasurement))
var i = 0
for k := range opMeasurement {
Expand All @@ -126,16 +129,26 @@ func outputMeasurement(prefix string, opMeasurement map[string]*measurement.Hist
}
sort.Strings(keys)

lines := [][]string{}
for _, op := range keys {
hist := opMeasurement[op]
if !hist.Empty() {
fmt.Printf("%s%s: %.2fs\n", prefix, strings.ToUpper(op), float64(hist.GetInfo().Avg)/1000)
lines = append(lines, []string{prefix, strings.ToUpper(op), util.FloatToTwoString(float64(hist.GetInfo().Avg)/1000) + "s"})
}
}

switch outputStyle {
case util.OutputStylePlain:
util.RenderString("%s%s: %s\n", nil, lines)
case util.OutputStyleTable:
util.RenderTable([]string{"Prefix", "Operation", "Avg(s)"}, lines)
case util.OutputStyleJson:
util.RenderJson([]string{"Prefix", "Operation", "Avg(s)"}, lines)
}
}

func (w *Workloader) OutputStats(ifSummaryReport bool) {
w.measurement.Output(ifSummaryReport, outputMeasurement)
w.measurement.Output(ifSummaryReport, w.cfg.OutputStyle, outputMeasurement)
}

func (w *Workloader) DBName() string {
Expand Down
Loading

0 comments on commit 062d2d7

Please sign in to comment.