Skip to content

Commit 7d4e4f9

Browse files
committed
Buffer writes to output files to reduce syscalls
1 parent ceb6d75 commit 7d4e4f9

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

internal/clientcli/output.go

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,62 @@
11
package clientcli
22

33
import (
4+
"bufio"
45
"io"
56
"os"
67
"path/filepath"
8+
9+
"go.uber.org/multierr"
710
)
811

12+
const outputBufferSize = 1024 * 1024
13+
914
type OutputFile struct {
1015
path string
1116

12-
w io.WriteCloser
13-
needClose bool
17+
w io.Writer
18+
close func() error
1419
}
1520

1621
func NewOutputFile(path string) (*OutputFile, error) {
22+
f := &OutputFile{}
23+
1724
switch path {
1825
case "":
19-
return &OutputFile{}, nil
26+
// Use remote filename
2027

2128
case "-":
22-
return &OutputFile{
23-
w: os.Stdout,
24-
}, nil
29+
f.w = os.Stdout
30+
31+
default:
32+
fh, err := os.Create(path)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
f.setup(fh)
2538
}
2639

27-
fh, err := os.Create(path)
28-
if err != nil {
29-
return nil, err
40+
return f, nil
41+
}
42+
43+
func (f *OutputFile) setup(w io.WriteCloser) {
44+
if f.w != nil {
45+
return
3046
}
3147

32-
return &OutputFile{
33-
w: fh,
34-
needClose: true,
35-
}, nil
48+
buf := bufio.NewWriterSize(w, outputBufferSize)
49+
50+
f.w = buf
51+
f.close = func() (err error) {
52+
defer multierr.AppendInvoke(&err, multierr.Close(w))
53+
54+
return buf.Flush()
55+
}
3656
}
3757

58+
// Open returns a writer. If a path was given to [NewOutputFile] the hint is
59+
// unused. Otherwise it's used to create a new file.
3860
func (f *OutputFile) Open(hint string) (io.Writer, error) {
3961
if f.w != nil {
4062
return f.w, nil
@@ -47,15 +69,14 @@ func (f *OutputFile) Open(hint string) (io.Writer, error) {
4769
return nil, err
4870
}
4971

50-
f.w = fh
51-
f.needClose = true
72+
f.setup(fh)
5273

5374
return f.w, nil
5475
}
5576

5677
func (f *OutputFile) Close() error {
57-
if f.w != nil && f.needClose {
58-
return f.w.Close()
78+
if f.close != nil {
79+
return f.close()
5980
}
6081

6182
return nil

0 commit comments

Comments
 (0)