Commit f72c4971 authored by Kirill Smelkov's avatar Kirill Smelkov

X fstail: Reduce allocations

name      old time/op    new time/op    delta
FsTail-4     166µs ± 0%     107µs ± 1%  -35.54%  (p=0.008 n=5+5)

name      old alloc/op   new alloc/op   delta
FsTail-4    28.1kB ± 0%    12.6kB ± 0%  -54.95%  (p=0.008 n=5+5)

name      old allocs/op  new allocs/op  delta
FsTail-4       671 ± 0%        78 ± 0%  -88.38%  (p=0.008 n=5+5)
parent b1f25716
......@@ -120,28 +120,18 @@ func fsTail(w io.Writer, path string, ntxn int) (err error) {
// print information about read txn record
xbuf.Reset()
xbuf .S(txnh.Tid.Time()) .S("hash=") .X(sha1.Sum(data))
dataSha1 := sha1.Sum(data)
xbuf .V(txnh.Tid.Time()) .S(": hash=") .Xb(dataSha1[:])
// fstail.py uses repr to print user/description:
// https://github.com/zopefoundation/ZODB/blob/5.2.0-4-g359f40ec7/src/ZODB/scripts/fstail.py#L39
xbuf .S("\nuser=") .Qpyb(txnh.User) .S(" description=") .Qpyb(txnh.Description)
// https://github.com/zopefoundation/ZODB/blob/5.2.0-5-g6047e2fae/src/ZODB/scripts/fstail.py#L39
xbuf .S("\nuser=") .Qbpy(txnh.User) .S(" description=") .Qbpy(txnh.Description)
// NOTE in zodb/py .length is len - 8, in zodb/go - whole txn record length
xbuf .S(" length=") .D(txnh.Len - 8)
xbuf .S(" offset=") .D(txnh.Pos) .S(" (+") .D(txnh.HeaderLen()) .S(")\n\n")
xbuf .S(" length=") .D64(txnh.Len - 8)
xbuf .S(" offset=") .D64(txnh.Pos) .S(" (+") .D64(txnh.HeaderLen()) .S(")\n\n")
// // print information about read txn record
// _, err = fmt.Fprintf(w, "%s: hash=%x\nuser=%s description=%s length=%d offset=%d (+%d)\n\n",
// txnh.Tid.Time(), sha1.Sum(data),
//
// // fstail.py uses repr to print user/description:
// // https://github.com/zopefoundation/ZODB/blob/5.2.0-4-g359f40ec7/src/ZODB/scripts/fstail.py#L39
// pyQuoteBytes(txnh.User), pyQuoteBytes(txnh.Description),
//
// // NOTE in zodb/py .length is len - 8, in zodb/go - whole txn record length
// txnh.Len - 8,
//
// txnh.Pos, txnh.HeaderLen())
_, err = w.Write(xbuf.Bytes())
if err != nil {
break
......
......@@ -73,7 +73,7 @@ func Append(b []byte, x Stringer) []byte {
}
// V, similarly to %v, adds x formatted by default rules
// XXX -> v(interface {}) ?
// XXX -> V(interface {}) ?
func (b *Buffer) V(x Stringer) *Buffer {
*b = Append(*b, x)
return b
......@@ -118,6 +118,12 @@ func (b *Buffer) D(i int) *Buffer {
return b
}
// D64 appends int64 formatted by %d
func (b *Buffer) D64(i int64) *Buffer {
*b = strconv.AppendInt(*b, i, 10)
return b
}
// X appends int formatted by %x
func (b *Buffer) X(i int) *Buffer {
*b = strconv.AppendInt(*b, int64(i), 16)
......
......@@ -23,13 +23,25 @@ var testv = []struct {format, xformatMeth string; value interface{}} {
{"%x", "Xb", []byte("hexstring")},
{"%x", "Xs", "stringhex"},
{"%d", "D", 12765},
{"%d", "D64", int64(12764)},
{"%x", "X", 12789},
{"%016x", "X016", uint64(124)},
// TODO .V
{"%v", "V", &stringerTest{}},
}
type stringerTest struct {
}
func (s *stringerTest) String() string {
return string(s.XFmtString(nil))
}
func (s *stringerTest) XFmtString(b []byte) []byte {
return append(b, `stringer test`...)
}
// verify formatting result is the same in between std fmt and xfmt
func TestXFmt(t *testing.T) {
buf := &Buffer{}
......@@ -111,8 +123,11 @@ func BenchmarkXFmt(b *testing.B) {
case string: methProxy = func(buf *Buffer, v interface{}) { meth.(func (*Buffer, string) *Buffer)(buf, v.(string)) }
case []byte: methProxy = func(buf *Buffer, v interface{}) { meth.(func (*Buffer, []byte) *Buffer)(buf, v.([]byte)) }
case int: methProxy = func(buf *Buffer, v interface{}) { meth.(func (*Buffer, int) *Buffer)(buf, v.(int)) }
case int64: methProxy = func(buf *Buffer, v interface{}) { meth.(func (*Buffer, int64) *Buffer)(buf, v.(int64)) }
case uint64: methProxy = func(buf *Buffer, v interface{}) { meth.(func (*Buffer, uint64) *Buffer)(buf, v.(uint64)) }
case *stringerTest: methProxy = func(buf *Buffer, v interface{}) { meth.(func (*Buffer, Stringer) *Buffer)(buf, v.(Stringer)) }
default:
b.Fatalf("TODO add support for %T", tt.value)
}
......
......@@ -15,8 +15,12 @@ type TimeStamp struct {
}
func (t TimeStamp) String() string {
return string(t.XFmtString(nil))
}
func (t TimeStamp) XFmtString(b []byte) []byte {
// NOTE UTC() in case we get TimeStamp with modified from-outside location
return t.UTC().Format("2006-01-02 15:04:05.000000")
return t.UTC().AppendFormat(b, "2006-01-02 15:04:05.000000")
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment