From 1f03e60c2a96a92acae0e4d2fd604ab2c6d55473 Mon Sep 17 00:00:00 2001 From: unclejack Date: Wed, 17 Sep 2014 18:04:56 +0300 Subject: [PATCH 1/3] move stdcopy to pkg/stdcopy Docker-DCO-1.1-Signed-off-by: Cristian Staretu (github: unclejack) --- api/client/hijack.go | 3 ++- api/client/utils.go | 3 ++- api/server/server.go | 13 +++++++------ pkg/stdcopy/MAINTAINERS | 1 + {utils => pkg/stdcopy}/stdcopy.go | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 pkg/stdcopy/MAINTAINERS rename {utils => pkg/stdcopy}/stdcopy.go (99%) diff --git a/api/client/hijack.go b/api/client/hijack.go index a14376c79e..4aba842372 100644 --- a/api/client/hijack.go +++ b/api/client/hijack.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/api" "github.com/docker/docker/dockerversion" "github.com/docker/docker/pkg/log" + "github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/term" "github.com/docker/docker/utils" ) @@ -96,7 +97,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea if setRawTerminal && stdout != nil { _, err = io.Copy(stdout, br) } else { - _, err = utils.StdCopy(stdout, stderr, br) + _, err = stdcopy.StdCopy(stdout, stderr, br) } log.Debugf("[hijack] End of stdout") return err diff --git a/api/client/utils.go b/api/client/utils.go index 0937f88d33..b1fec647c4 100644 --- a/api/client/utils.go +++ b/api/client/utils.go @@ -22,6 +22,7 @@ import ( "github.com/docker/docker/dockerversion" "github.com/docker/docker/engine" "github.com/docker/docker/pkg/log" + "github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/term" "github.com/docker/docker/registry" "github.com/docker/docker/utils" @@ -174,7 +175,7 @@ func (cli *DockerCli) streamHelper(method, path string, setRawTerminal bool, in if setRawTerminal { _, err = io.Copy(stdout, resp.Body) } else { - _, err = utils.StdCopy(stdout, stderr, resp.Body) + _, err = stdcopy.StdCopy(stdout, stderr, resp.Body) } log.Debugf("[stream] End of stdout") return err diff --git a/api/server/server.go b/api/server/server.go index 8c5d89310e..74bebfde1d 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -28,6 +28,7 @@ import ( "github.com/docker/docker/pkg/listenbuffer" "github.com/docker/docker/pkg/log" "github.com/docker/docker/pkg/parsers" + "github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/systemd" "github.com/docker/docker/pkg/version" "github.com/docker/docker/registry" @@ -399,8 +400,8 @@ func getContainersLogs(eng *engine.Engine, version version.Version, w http.Respo outStream = utils.NewWriteFlusher(w) if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version.GreaterThanOrEqualTo("1.6") { - errStream = utils.NewStdWriter(outStream, utils.Stderr) - outStream = utils.NewStdWriter(outStream, utils.Stdout) + errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) + outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) } else { errStream = outStream } @@ -843,8 +844,8 @@ func postContainersAttach(eng *engine.Engine, version version.Version, w http.Re fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version.GreaterThanOrEqualTo("1.6") { - errStream = utils.NewStdWriter(outStream, utils.Stderr) - outStream = utils.NewStdWriter(outStream, utils.Stdout) + errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) + outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) } else { errStream = outStream } @@ -1091,8 +1092,8 @@ func postContainerExecStart(eng *engine.Engine, version version.Version, w http. fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") if !job.GetenvBool("Tty") && version.GreaterThanOrEqualTo("1.6") { - errStream = utils.NewStdWriter(outStream, utils.Stderr) - outStream = utils.NewStdWriter(outStream, utils.Stdout) + errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) + outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) } else { errStream = outStream } diff --git a/pkg/stdcopy/MAINTAINERS b/pkg/stdcopy/MAINTAINERS new file mode 100644 index 0000000000..6dde4769d7 --- /dev/null +++ b/pkg/stdcopy/MAINTAINERS @@ -0,0 +1 @@ +Cristian Staretu (@unclejack) diff --git a/utils/stdcopy.go b/pkg/stdcopy/stdcopy.go similarity index 99% rename from utils/stdcopy.go rename to pkg/stdcopy/stdcopy.go index 08263de0ff..b50c31dd49 100644 --- a/utils/stdcopy.go +++ b/pkg/stdcopy/stdcopy.go @@ -1,4 +1,4 @@ -package utils +package stdcopy import ( "encoding/binary" From 277aa9c67415b9b76ab17daea583b51f8560a6a5 Mon Sep 17 00:00:00 2001 From: unclejack Date: Wed, 17 Sep 2014 16:50:56 +0300 Subject: [PATCH 2/3] stdcopy: improve perf by avoiding buffer growth Docker-DCO-1.1-Signed-off-by: Cristian Staretu (github: unclejack) --- pkg/stdcopy/stdcopy.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pkg/stdcopy/stdcopy.go b/pkg/stdcopy/stdcopy.go index b50c31dd49..79e15bc852 100644 --- a/pkg/stdcopy/stdcopy.go +++ b/pkg/stdcopy/stdcopy.go @@ -29,14 +29,22 @@ type StdWriter struct { } func (w *StdWriter) Write(buf []byte) (n int, err error) { + var n1, n2 int if w == nil || w.Writer == nil { return 0, errors.New("Writer not instanciated") } binary.BigEndian.PutUint32(w.prefix[4:], uint32(len(buf))) - buf = append(w.prefix[:], buf...) - - n, err = w.Writer.Write(buf) - return n - StdWriterPrefixLen, err + n1, err = w.Writer.Write(w.prefix[:]) + if err != nil { + n = n1 - StdWriterPrefixLen + } else { + n2, err = w.Writer.Write(buf) + n = n1 + n2 - StdWriterPrefixLen + } + if n < 0 { + n = 0 + } + return } // NewStdWriter instanciates a new Writer. From 55cac6c9421702ca1e42b3e3f92266e865a5c769 Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Wed, 17 Sep 2014 19:24:07 +0400 Subject: [PATCH 3/3] Benchmark for StdWriter.Write Signed-off-by: Alexandr Morozov --- pkg/stdcopy/stdcopy_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 pkg/stdcopy/stdcopy_test.go diff --git a/pkg/stdcopy/stdcopy_test.go b/pkg/stdcopy/stdcopy_test.go new file mode 100644 index 0000000000..14e6ed3115 --- /dev/null +++ b/pkg/stdcopy/stdcopy_test.go @@ -0,0 +1,20 @@ +package stdcopy + +import ( + "bytes" + "io/ioutil" + "testing" +) + +func BenchmarkWrite(b *testing.B) { + w := NewStdWriter(ioutil.Discard, Stdout) + data := []byte("Test line for testing stdwriter performance\n") + data = bytes.Repeat(data, 100) + b.SetBytes(int64(len(data))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := w.Write(data); err != nil { + b.Fatal(err) + } + } +}