From fdbbb066ed86a08c39ac6195548054435406b60d Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Sat, 26 Feb 2011 16:42:49 +1100 Subject: [PATCH] compress/lzw: don't use a closure in NewReader, which avoids having to move some variables from the stack to the heap. Sorted benchmark runs on my 2007-era Mac Mini (GOARCH=amd64, GOOS=linux): Before: lzw.BenchmarkDecoder 2000 878176 ns/op lzw.BenchmarkDecoder 2000 878415 ns/op lzw.BenchmarkDecoder 2000 880352 ns/op lzw.BenchmarkDecoder 2000 898445 ns/op lzw.BenchmarkDecoder 2000 901728 ns/op After: lzw.BenchmarkDecoder 2000 859065 ns/op lzw.BenchmarkDecoder 2000 859402 ns/op lzw.BenchmarkDecoder 2000 860035 ns/op lzw.BenchmarkDecoder 2000 860555 ns/op lzw.BenchmarkDecoder 2000 861109 ns/op The ratio of before/after median times is 1.024. The runtime.MemStats.Mallocs delta per loop drops from 109 to 104. R=r, r2, dfc CC=golang-dev https://golang.org/cl/4253043 --- src/pkg/compress/lzw/reader.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/pkg/compress/lzw/reader.go b/src/pkg/compress/lzw/reader.go index 9838acd4ea..8a540cbe6a 100644 --- a/src/pkg/compress/lzw/reader.go +++ b/src/pkg/compress/lzw/reader.go @@ -76,7 +76,15 @@ func (d *decoder) readMSB() (uint16, os.Error) { // decode decompresses bytes from r and writes them to pw. // read specifies how to decode bytes into codes. // litWidth is the width in bits of literal codes. -func decode(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os.Error), litWidth uint) os.Error { +func decode(r io.Reader, read func(*decoder) (uint16, os.Error), litWidth int, pw *io.PipeWriter) { + br, ok := r.(io.ByteReader) + if !ok { + br = bufio.NewReader(r) + } + pw.CloseWithError(decode1(pw, br, read, uint(litWidth))) +} + +func decode1(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os.Error), litWidth uint) os.Error { const ( maxWidth = 12 invalidCode = 0xffff @@ -197,12 +205,6 @@ func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser { pw.CloseWithError(fmt.Errorf("lzw: litWidth %d out of range", litWidth)) return pr } - go func() { - br, ok := r.(io.ByteReader) - if !ok { - br = bufio.NewReader(r) - } - pw.CloseWithError(decode(pw, br, read, uint(litWidth))) - }() + go decode(r, read, litWidth, pw) return pr }