diff options
| -rw-r--r-- | server/flate.go | 6 | ||||
| -rw-r--r-- | server/flate_test.go | 78 |
2 files changed, 81 insertions, 3 deletions
diff --git a/server/flate.go b/server/flate.go index e2d87f4..01becb6 100644 --- a/server/flate.go +++ b/server/flate.go @@ -8,9 +8,9 @@ import ( // the protocol requires us to send the level as a gzipped flat array. but our // level representation is close to run length encoding that can be achieved -// with DEFLATE. it is thus in theory significantly more CPU efficient to, -// instead of expanding out the RLE and compressing it with the generic -// compressor, translate it directly into DEFLATE +// with DEFLATE. it is thus significantly more CPU efficient to, instead of +// expanding out the RLE and compressing it with the generic compressor, +// translate it directly into DEFLATE func deflateRuns( wr io.Writer, runs []blockData, changes []blockData, levelSize uint32) (length uint32, err error) { diff --git a/server/flate_test.go b/server/flate_test.go new file mode 100644 index 0000000..2a85004 --- /dev/null +++ b/server/flate_test.go @@ -0,0 +1,78 @@ +package server + +import ( + "io" + "bufio" + "testing" + "compress/gzip" + "encoding/binary" +) + +type benchCompressor func(*blockVolume) io.ReadCloser + +func theirCompress(v *blockVolume) io.ReadCloser { + rd, wr := io.Pipe() + go func() { + defer wr.Close() + z := gzip.NewWriter(wr) + defer z.Close() + bw := bufio.NewWriter(z) + defer bw.Flush() + + v.RLock() + defer v.RUnlock() + binary.Write(bw, binary.BigEndian, uint32(v.size.X*v.size.Y*v.size.Z)) + for block := range v.unsyncGetAll() { + err := bw.WriteByte(byte(block)) + if err != nil { + return + } + } + }() + return rd +} + +func ourCompress(v *blockVolume) io.ReadCloser { + return v.syncCompressForNetwork() +} + +func doCompressorBenchmark( + b *testing.B, c benchCompressor, v *blockVolume, testName string) { + b.StartTimer() + rd := c(v) + data, err := io.ReadAll(rd) + if err != nil { + panic(err) + } + b.Logf("compressed %s to %d bytes", testName, len(data)) + b.StopTimer() +} + +func doCompressorBenchmarks(b *testing.B, c benchCompressor) { + b.StopTimer() + var ( + v blockVolume + size = blockPos {1024, 1024, 1024} + ) + v.init(size) + doCompressorBenchmark(b, c, &v, "empty") + v.init(size) + generateDebug(&v) + doCompressorBenchmark(b, c, &v, "debug") + v.init(size) + generateFlat(&v) + doCompressorBenchmark(b, c, &v, "flat") + v.init(size) + generateSphere(&v) + doCompressorBenchmark(b, c, &v, "sphere") +} + +func BenchmarkNaiveGzip(b *testing.B) { + doCompressorBenchmarks(b, theirCompress) + b.Logf("naive gzip compressor completed in %v", b.Elapsed()) +} + +func BenchmarkDeflate(b *testing.B) { + doCompressorBenchmarks(b, ourCompress) + b.Logf("custom deflate compressor completed in %v", b.Elapsed()) +} |
