Skip to content

Commit

Permalink
simplify dynamic decode loop
Browse files Browse the repository at this point in the history
Current timing:

$ zig build bench -Doptimize=ReleaseSafe && hyperfine --warmup 1 -r 10 'zig-out/bin/inflate_bench'
Benchmark 1: zig-out/bin/inflate_bench
  Time (mean ± σ):     355.0 ms ±   0.8 ms    [User: 353.4 ms, System: 1.6 ms]
  Range (min … max):   354.0 ms … 356.3 ms    10 runs
  • Loading branch information
ianic committed Feb 2, 2024
1 parent 0a80cda commit f58c7de
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/Token.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const match_lengths_index = [_]u8{
const MatchLength = struct {
code: u16,
base_scaled: u8, // base - 3, scaled to fit into u8 (0-255), same as lit_len field in Token.
base: u16, // 3-358
base: u16, // 3-258
extra_length: u8 = 0,
extra_bits: u4,
};
Expand Down
25 changes: 15 additions & 10 deletions src/inflate.zig
Original file line number Diff line number Diff line change
Expand Up @@ -180,32 +180,37 @@ pub fn Inflate(comptime wrap: Wrapper, comptime ReaderType: type) type {

fn dynamicBlock(self: *Self) !bool {
while (!self.windowFull()) {
try self.bits.fill(15);
const sym = self.lit_h.find(try self.bits.peekF(u15, F.buffered | F.reverse));
self.bits.shift(sym.code_bits);
try self.bits.fill(15); // optimization so other bit reads can be buffered (avoiding one in hot path)
const sym = try self.decodeSymbol(&self.lit_h);

if (sym.kind == .literal) {
self.win.write(sym.symbol);
continue;
}
if (sym.kind == .end_of_block) {
// end of block
return true;
}

// decode backward pointer <length, distance>
try self.bits.fill(5 + 15 + 13);
// Decode match backreference <length, distance>
try self.bits.fill(5 + 15 + 13); // so we can use buffered reads
const length = try self.decodeLength(sym.symbol);

const dsm = self.dst_h.find(try self.bits.peekF(u15, F.buffered | F.reverse)); // distance symbol
self.bits.shift(dsm.code_bits);

const dsm = try self.decodeSymbol(&self.dst_h);
const distance = try self.decodeDistance(dsm.symbol);
self.win.writeCopy(length, distance);
}
return false;
}

// Peek 15 bits from bits reader (maximum code len is 15 bits). Use
// decoder to find symbol for that code. We then know how many bits is
// used. Shift bit reader for that much bits, those bits are used. And
// return symbol.
inline fn decodeSymbol(self: *Self, decoder: anytype) !hfd.Symbol {
const sym = decoder.find(try self.bits.peekF(u15, F.buffered | F.reverse));
self.bits.shift(sym.code_bits);
return sym;
}

fn step(self: *Self) Error!void {
switch (self.state) {
.protocol_header => {
Expand Down

0 comments on commit f58c7de

Please sign in to comment.