Skip to content

Decode DEFLATE with zlib in the inflating reader - #2506

Draft
nikosavola wants to merge 4 commits into
KLayout:masterfrom
nikosavola:pr-inflate-zlib
Draft

nikosavola wants to merge 4 commits into
KLayout:masterfrom
nikosavola:pr-inflate-zlib

Conversation

@nikosavola

Copy link
Copy Markdown
Contributor

Draft, stacked on #2505: the first two commits are #2505's and drop out once it is merged and I rebase. New here are the last two commits.

  • InflateFilter now decodes with zlib raw inflate, the same way DeflateFilter already encodes with zlib, instead of its own Huffman decoder. BitStream and HuffmannDecoder are removed, about 400 lines less
  • zlib keeps its own window, so the output buffer is linear and the ring buffer with its rotation is gone
  • zlib takes the compressed input in chunks. The bytes behind the DEFLATE stream are pushed back through a new bypass_inflate flag on InputStream::unget, so the raw stream continues right after the block, and pos () does not count the bytes zlib has not decoded yet
  • this is the decoder for OASIS CBLOCKs and for .gz files
  • new tests for raw data behind a DEFLATE stream, pos () while inflating and truncated input. They pass with the old decoder too
  • second piece of the Inflate OASIS CBLOCKs in one go with zlib #2468 split
case before after speedup
OASIS read with CBLOCKs, 200k polygons (75 MB) 6.34 s 2.14 s 2.96x
OASIS read with CBLOCKs (vexriscv) 148.7 ms 87.6 ms 1.70x
OASIS read, 200k polygons (102 MB) 1.69 s 1.67 s 1.01x
OASIS read (vexriscv) 77.9 ms 78.7 ms 0.99x
GDS2 read (vexriscv) 144.2 ms 146.4 ms 0.99x

Xeon Gold 6248, gcc 13 -O2, before (#2505) and after alternated on one pinned core for 6 to 10 rounds, every round agrees. The uncompressed reads do not run the changed code, so their 1% either way is code layout.

- get was out-of-line, so byte-wise readers such as the OASIS varint decoder and the GDS2 record reader paid a call per get, two inside a CBLOCK
- the inline get serves bytes from the raw buffer and single bytes from the inflate ring buffer, refills and the end of the inflated data stay in get_slow
- the last ring slot is left to get_slow too: get rotates the ring there so the read pointer does not wrap, otherwise a following unget(1) asserts
- tlStream.h now needs the InflateFilter definition, so tlDeflate.h no longer includes tlStream.h and BitStream::get_byte moved to tlDeflate.cc

| case | before ms | after ms | speedup |
|---|---:|---:|---:|
| oasis_read_vexriscv_compressed | 145.0 | 132.4 | 1.09x |
| gds2_read_vexriscv | 135.9 | 127.8 | 1.06x |
| oasis_read_vexriscv | 71.5 | 69.9 | 1.02x |

Xeon Gold 6248, g++ 13 -O2, before and after alternated for 6 rounds on one pinned core, every round agrees.
- InflateFilter uses zlib raw inflate like DeflateFilter already uses zlib deflate, instead of its own Huffman decoder
- the output buffer is linear, zlib keeps its own window, so the ring buffer and its rotation are gone
- zlib reads the compressed input in chunks, the part behind the DEFLATE stream is pushed back with the new bypass_inflate flag of InputStream::unget so raw reading continues right after the block
- InputStream::pos does not count the chunk part zlib has not decoded yet, so error positions inside a CBLOCK stay close to where they were
- BitStream and HuffmannDecoder were only used by the old decoder and are removed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant