两个小实例测试

ab压测

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    "strings"
    "sync"
    "time"
)

var usage = `Usage: %s [options]
Options are:
    -n number     Number of requests to perform
    -c concurrency  Number of multiple requests to make at a time
    -t timeout      Seconds to max. wait for each response
    -m method       Method name
`

var (
    number int
    concurrency int
    timeout int
    method string
    url string
)

func init() {
    flag.Usage = func() {
        fmt.Fprintf(os.Stderr, usage, os.Args[0])
    }

    flag.IntVar(&number, "n", 1000, "")
    flag.IntVar(&concurrency, "c", 10, "")
    flag.IntVar(&timeout, "t", 1, "")
    flag.StringVar(&method, "m", "GET", "")

    if flag.NArg() != 1 {
        exit("Invalid url")
    }

    method = strings.ToUpper(method)
    url = flag.Args()[0]

    if method != "GET" {
        exit("Invalid method")
    }

    if number < 1 || concurrency < 1 {
        exit("-n and -c cannot be smaller than 1.")
    }

    if number < concurrency {
        exit("-n cannot be less than -c.")
    }
}

type benchmark struct {
    number int
    concurrency int
    timeout int
    method string
    url string
    duration chan time.Duration
    start time.Time
    end time.Time
}

func (b *benchmark) run() {
    b.duration = make(chan time.Duration, b.number)
    b.start = time.Now()
    b.runWorks()
    b.end = time.Now()

    b.report()
}

func (b *benchmark) runWorks() {
    var wg sync.WaitGroup

    wg.Add(b.concurrency)

    for i := 0; i < b.concurrency; i++ {
        go func() {
            defer wg.Done()
            b.runWork(b.number / b.concurrency)
        }()
    }

    wg.Wait()
    close(b.duration)
}

func (b *benchmark) runWork(num int) {
    client := &http.Client{
        Timeout:time.Duration(b.timeout) * time.Second,
    }

    for i := 0; i < num; i++ {
        b.request(client)
    }
}

func (b *benchmark) request(client *http.Client) {
    req, err := http.NewRequest(b.method, b.url, nil)

    if err != nil {
        log.Fatal(req)
    }

    start := time.Now()
    client.Do(req)
    end := time.Now()

    b.duration <- end.Sub(start)
}

func (b *benchmark) report() {
    sum := 0.0
    num := float64(len(b.duration))

    for duration := range b.duration {
        sum += duration.Seconds()
    }

    rps := int(num / b.end.Sub(b.start).Seconds())
    tpr := sum / num * 1000

    fmt.Printf("rps: %d [#/sec]
", rps)
    fmt.Printf("tpr: %.3f [ms]
", tpr)
}

func exit(msg string) {
    flag.Usage()
    fmt.Fprintln(os.Stderr, "
[ERROR] " + msg)
    os.Exit(1)
}

func main() {
    b := benchmark{
        number:      number,
        concurrency: concurrency,
        timeout:     timeout,
        method:      method,
        url:         url,
    }

    b.run()
}

数据库sql测试

package main

import (
    "database/sql"
    "fmt"
    "github.com/spf13/cobra"
    "github.com/spf13/viper"
    "log"
    "os"
    "sync"
    "time"
)

var db *sql.DB
var number, concurrency int

var cmd = &cobra.Command{
    Use:    "benchmark sql",
    Short:    "a sql benchmark tool",
    Args:     func(cmd *cobra.Command, args []string) error {
        if len(args) != 1 {
            cmd.Usage()
            os.Exit(1)
        }
        return nil
    },
    Run:     func(cmd *cobra.Command, args []string) {
        b := benchmark{
            sql:args[0],
            number:number,
            concurrency:concurrency,
        }
        b.run()
    },
}

func init() {
    cobra.OnInitialize(config)

    cmd.Flags().IntVarP(&number, "number", "n", 100, "number")
    cmd.Flags().IntVarP(&concurrency, "concurrency", "c", 1, "concurrency")
    cmd.Flags().SortFlags = false
}

func config() {
    viper.AddConfigPath(".")
    viper.SetConfigName("db")
    viper.SetConfigType("toml")

    err := viper.ReadInConfig()
    if err != nil {
        log.Fatal(err)
    }

    driver := viper.GetString("driver")
    dsn := viper.GetString("dsn")

    db, err = sql.Open(driver, dsn)
    if err != nil {
        log.Fatal(err)
    }
}

type benchmark struct {
    sql string
    number int
    concurrency int
    duration chan time.Duration
    start time.Time
    end time.Time
}

func (b *benchmark) run() {
    b.duration = make(chan time.Duration, b.number)
    b.start = time.Now()
    b.runWorkers()
    b.end = time.Now()
    b.report()
}

func (b *benchmark) runWorkers() {
    var wg sync.WaitGroup
    wg.Add(b.concurrency)

    for i := 0; i < b.concurrency; i++ {
        go func() {
            defer wg.Done()
            b.runWorker(b.number / b.concurrency)
        }()
    }

    wg.Wait()
    close(b.duration)
}

func (b *benchmark) runWorker(num int) {
    for i := 0; i < num; i++ {
        start := time.Now()
        b.request()
        end := time.Now()
        b.duration <- end.Sub(start)
    }
}

func (b *benchmark) request() {
    if _, err := db.Exec(b.sql); err != nil {
        log.Fatalln(err)
    }
}

func (b *benchmark) report() {
    sum := 0.0
    num := float64(len(b.duration))

    for duration := range b.duration {
        sum += duration.Seconds()
    }

    qps := int(num / b.end.Sub(b.start).Seconds())
    tpq := sum / num * 1000

    fmt.Printf("qps: %d [#/sec]
", qps)
    fmt.Printf("tpq: %.3f [ms]
", tpq)
}

轮子一堆,我们没必要面面俱到,当一个组装工也是不错的,说实话,我认为多数人的智商就不要自己写轮子,不如学点方法论。

两个都是学习自火丁笔记

https://blog.huoding.com/2017/06/09/623

https://blog.huoding.com/2019/08/21/768

end

一个没有高级趣味的人。 email:hushui502@gmail.com
原文地址:https://www.cnblogs.com/CherryTab/p/12827726.html