libtsdb / libtsdb-go

Building blocks for Time Series Database (TSDB) in Go
MIT License
9 stars 2 forks source link

Benchmark encoder against strings.Join style implementation #20

Open at15 opened 6 years ago

at15 commented 6 years ago

When working on gommon errors, came back to hashicorp/go-multierrors and they use strings.Join https://github.com/hashicorp/go-multierror/blob/master/format.go#L26:20 and the implementation is a bit different style compared to how we write encoder

func Join(a []string, sep string) string {
    switch len(a) {
    case 0:
        return ""
    case 1:
        return a[0]
    case 2:
        // Special case for common small values.
        // Remove if golang.org/issue/6714 is fixed
        return a[0] + sep + a[1]
    case 3:
        // Special case for common small values.
        // Remove if golang.org/issue/6714 is fixed
        return a[0] + sep + a[1] + sep + a[2]
    }
    n := len(sep) * (len(a) - 1)
    for i := 0; i < len(a); i++ {
        n += len(a[i])
    }

    b := make([]byte, n)
    bp := copy(b, a[0])
    for _, s := range a[1:] {
        bp += copy(b[bp:], sep)
        bp += copy(b[bp:], s)
    }
    return string(b)
}

https://github.com/libtsdb/libtsdb-go/blob/master/libtsdb/common/influxdb/encoder.go

func (e *Encoder) WritePointIntTagged(p *pb.PointIntTagged) {
    e.Buf = append(e.Buf, p.Name...)
    e.Buf = append(e.Buf, ',')
    for _, tag := range p.Tags {
        e.Buf = append(e.Buf, tag.K...)
        e.Buf = append(e.Buf, '=')
        e.Buf = append(e.Buf, tag.V...)
        e.Buf = append(e.Buf, ',')
    }
    e.Buf[len(e.Buf)-1] = ' '
    e.Buf = append(e.Buf, e.DefaultField...)
    e.Buf = append(e.Buf, '=')
    e.Buf = strconv.AppendInt(e.Buf, p.Point.V, 10)
    e.Buf = append(e.Buf, ' ')
    e.Buf = strconv.AppendInt(e.Buf, p.Point.T, 10)
    e.Buf = append(e.Buf, '\n')
}

not sure which one is faster, my implementation is likely to have more allocation because the slice is large enough ... though in our case since clients are not thread safe and use just one large slice as buffer, it's pretty likely no allocation will happen ....

at15 commented 4 years ago

It is a good use case for benchhub, so just keep it open for now ... I always spend so much time on micro optimizing ... meh.