From 28882bbd339ac72b06e0b022311a30a7eef89e46 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 18 May 2013 15:28:27 -0700 Subject: [PATCH] compress/flate: faster version of forwardCopy benchmark old ns/op new ns/op delta BenchmarkDecodeDigitsSpeed1e4 197767 203490 +2.89% BenchmarkDecodeDigitsSpeed1e5 1873969 1912761 +2.07% BenchmarkDecodeDigitsSpeed1e6 18922760 19021056 +0.52% BenchmarkDecodeDigitsDefault1e4 194975 197054 +1.07% BenchmarkDecodeDigitsDefault1e5 1704262 1719988 +0.92% BenchmarkDecodeDigitsDefault1e6 16618354 16351957 -1.60% BenchmarkDecodeDigitsCompress1e4 195281 194626 -0.34% BenchmarkDecodeDigitsCompress1e5 1694364 1702372 +0.47% BenchmarkDecodeDigitsCompress1e6 16463347 16492126 +0.17% BenchmarkDecodeTwainSpeed1e4 200653 200127 -0.26% BenchmarkDecodeTwainSpeed1e5 1861385 1759632 -5.47% BenchmarkDecodeTwainSpeed1e6 18255769 17186679 -5.86% BenchmarkDecodeTwainDefault1e4 189080 185157 -2.07% BenchmarkDecodeTwainDefault1e5 1559222 1461465 -6.27% BenchmarkDecodeTwainDefault1e6 14792125 13879051 -6.17% BenchmarkDecodeTwainCompress1e4 188881 185151 -1.97% BenchmarkDecodeTwainCompress1e5 1537031 1456945 -5.21% BenchmarkDecodeTwainCompress1e6 14805972 13405094 -9.46% BenchmarkPaeth 4 4 -0.89% BenchmarkDecodeGray 964679 937244 -2.84% BenchmarkDecodeNRGBAGradient 3753769 3646416 -2.86% BenchmarkDecodeNRGBAOpaque 3165856 2981300 -5.83% BenchmarkDecodePaletted 713950 691984 -3.08% BenchmarkDecodeRGB 3051718 2924260 -4.18% R=nigeltao, bradfitz CC=golang-dev, raph https://golang.org/cl/9425046 --- src/pkg/compress/flate/copy.go | 27 +++++++++++++++++++++------ src/pkg/compress/flate/copy_test.go | 10 ++++++---- src/pkg/compress/flate/inflate.go | 2 +- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/pkg/compress/flate/copy.go b/src/pkg/compress/flate/copy.go index 06e5d2e66d9..a3200a8f49e 100644 --- a/src/pkg/compress/flate/copy.go +++ b/src/pkg/compress/flate/copy.go @@ -6,12 +6,27 @@ package flate // forwardCopy is like the built-in copy function except that it always goes // forward from the start, even if the dst and src overlap. -func forwardCopy(dst, src []byte) int { - if len(src) > len(dst) { - src = src[:len(dst)] +// It is equivalent to: +// for i := 0; i < n; i++ { +// mem[dst+i] = mem[src+i] +// } +func forwardCopy(mem []byte, dst, src, n int) { + if dst <= src { + copy(mem[dst:dst+n], mem[src:src+n]) + return } - for i, x := range src { - dst[i] = x + for { + if dst >= src+n { + copy(mem[dst:dst+n], mem[src:src+n]) + return + } + // There is some forward overlap. The destination + // will be filled with a repeated pattern of mem[src:src+k]. + // We copy one instance of the pattern here, then repeat. + // Each time around this loop k will double. + k := dst - src + copy(mem[dst:dst+k], mem[src:src+k]) + n -= k + dst += k } - return len(src) } diff --git a/src/pkg/compress/flate/copy_test.go b/src/pkg/compress/flate/copy_test.go index a9281d446e9..2011b1547c9 100644 --- a/src/pkg/compress/flate/copy_test.go +++ b/src/pkg/compress/flate/copy_test.go @@ -30,10 +30,12 @@ func TestForwardCopy(t *testing.T) { } for _, tc := range testCases { b := []byte("0123456789") - dst := b[tc.dst0:tc.dst1] - src := b[tc.src0:tc.src1] - n := forwardCopy(dst, src) - got := string(dst[:n]) + n := tc.dst1 - tc.dst0 + if tc.src1-tc.src0 < n { + n = tc.src1 - tc.src0 + } + forwardCopy(b, tc.dst0, tc.src0, n) + got := string(b[tc.dst0 : tc.dst0+n]) if got != tc.want { t.Errorf("dst=b[%d:%d], src=b[%d:%d]: got %q, want %q", tc.dst0, tc.dst1, tc.src0, tc.src1, got, tc.want) diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go index beca34b4d8c..f529c9e7c23 100644 --- a/src/pkg/compress/flate/inflate.go +++ b/src/pkg/compress/flate/inflate.go @@ -511,7 +511,7 @@ func (f *decompressor) copyHist() bool { if x := len(f.hist) - p; n > x { n = x } - forwardCopy(f.hist[f.hp:f.hp+n], f.hist[p:p+n]) + forwardCopy(f.hist[:], f.hp, p, n) p += n f.hp += n f.copyLen -= n