Commit 5b1d47d1 authored by Nigel Tao's avatar Nigel Tao

compress/lzw: fix the stupidity of allocating and zeroing a new buffer

on each loop iteration, yielding a 20x performance improvement.

R=rsc, r2
CC=golang-dev
https://golang.org/cl/4240044
parent 54f00407
...@@ -99,6 +99,9 @@ func decode(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os. ...@@ -99,6 +99,9 @@ func decode(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os.
// The c == hi case is a special case. // The c == hi case is a special case.
suffix [1 << maxWidth]uint8 suffix [1 << maxWidth]uint8
prefix [1 << maxWidth]uint16 prefix [1 << maxWidth]uint16
// buf is a scratch buffer for reconstituting the bytes that a code expands to.
// Code suffixes are written right-to-left from the end of the buffer.
buf [1 << maxWidth]byte
) )
// Loop over the code stream, converting codes into decompressed bytes. // Loop over the code stream, converting codes into decompressed bytes.
...@@ -131,9 +134,6 @@ func decode(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os. ...@@ -131,9 +134,6 @@ func decode(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os.
case code == eof: case code == eof:
return w.Flush() return w.Flush()
case code <= hi: case code <= hi:
// buf is a scratch buffer for reconstituting the bytes that a code expands to.
// Code suffixes are written right-to-left from the end of the buffer.
var buf [1 << maxWidth]byte
c, i := code, len(buf)-1 c, i := code, len(buf)-1
if code == hi { if code == hi {
// code == hi is a special case which expands to the last expansion // code == hi is a special case which expands to the last expansion
......
...@@ -7,6 +7,7 @@ package lzw ...@@ -7,6 +7,7 @@ package lzw
import ( import (
"bytes" "bytes"
"io" "io"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
...@@ -109,3 +110,23 @@ func TestReader(t *testing.T) { ...@@ -109,3 +110,23 @@ func TestReader(t *testing.T) {
} }
} }
} }
type devNull struct{}
func (devNull) Write(p []byte) (int, os.Error) {
return len(p), nil
}
func BenchmarkDecoder(b *testing.B) {
b.StopTimer()
buf0, _ := ioutil.ReadFile("../testdata/e.txt")
compressed := bytes.NewBuffer(nil)
w := NewWriter(compressed, LSB, 8)
io.Copy(w, bytes.NewBuffer(buf0))
w.Close()
buf1 := compressed.Bytes()
b.StartTimer()
for i := 0; i < b.N; i++ {
io.Copy(devNull{}, NewReader(bytes.NewBuffer(buf1), LSB, 8))
}
}
...@@ -98,3 +98,14 @@ func TestWriter(t *testing.T) { ...@@ -98,3 +98,14 @@ func TestWriter(t *testing.T) {
} }
} }
} }
func BenchmarkEncoder(b *testing.B) {
b.StopTimer()
buf, _ := ioutil.ReadFile("../testdata/e.txt")
b.StartTimer()
for i := 0; i < b.N; i++ {
w := NewWriter(devNull{}, LSB, 8)
w.Write(buf)
w.Close()
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment