Skip to content

Commit

Permalink
interp: reuse copy buffers for pipes
Browse files Browse the repository at this point in the history
Practically no effect on time/op and allocs/op, but the amount of space
allocated per benchmark run gets dramatically reduced.

name   old time/op    new time/op    delta
Run-8    1.46ms ± 1%    1.45ms ± 1%     ~     (p=0.180 n=6+6)

name   old alloc/op   new alloc/op   delta
Run-8     179kB ± 0%      80kB ± 0%  -55.17%  (p=0.002 n=6+6)

name   old allocs/op  new allocs/op  delta
Run-8     1.03k ± 0%     1.04k ± 0%   +0.78%  (p=0.004 n=6+5)
  • Loading branch information
mvdan committed Dec 20, 2018
1 parent dffd4f7 commit 329a2c6
Showing 1 changed file with 25 additions and 5 deletions.
30 changes: 25 additions & 5 deletions interp/interp.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,23 @@ type Runner struct {
// On Windows, the kill signal is always sent immediately,
// because Go doesn't currently support sending Interrupt on Windows.
KillTimeout time.Duration

// So that we can get io.Copy to reuse the same buffer within a runner.
// For example, this saves an allocation for every shell pipe, since
// io.PipeReader does not implement io.WriterTo.
bufCopier bufCopier
}

type bufCopier struct {
io.Reader
buf []byte
}

func (r *bufCopier) WriteTo(w io.Writer) (n int64, err error) {
if r.buf == nil {
r.buf = make([]byte, 32*1024)
}
return io.CopyBuffer(w, r.Reader, r.buf)
}

func (r *Runner) optByFlag(flag string) *bool {
Expand Down Expand Up @@ -491,10 +508,11 @@ func (r *Runner) Reset() {
KillTimeout: r.KillTimeout,

// emptied below, to reuse the space
Vars: r.Vars,
cmdVars: r.cmdVars,
dirStack: r.dirStack[:0],
usedNew: r.usedNew,
Vars: r.Vars,
cmdVars: r.cmdVars,
dirStack: r.dirStack[:0],
usedNew: r.usedNew,
bufCopier: r.bufCopier,
}
if r.Vars == nil {
r.Vars = make(map[string]expand.Variable)
Expand Down Expand Up @@ -530,6 +548,7 @@ func (r *Runner) Reset() {
r.KillTimeout = 2 * time.Second
}
r.didReset = true
r.bufCopier.Reader = nil
}

func (r *Runner) modCtx(ctx context.Context) context.Context {
Expand Down Expand Up @@ -764,7 +783,8 @@ func (r *Runner) cmd(ctx context.Context, cm syntax.Command) {
} else {
r2.Stderr = r.Stderr
}
r.Stdin = pr
r.bufCopier.Reader = pr
r.Stdin = &r.bufCopier
var wg sync.WaitGroup
wg.Add(1)
go func() {
Expand Down

0 comments on commit 329a2c6

Please sign in to comment.