Skip to content

Commit b8d4502

Browse files
committed
Micro-optimizations: cache w_end, parallel sort arrays, make_uninit, inline codes
Chain walk: Cache comparison byte w_end to avoid repeated array lookup per chain iteration. Update w_end only when best_len improves. Huffman: Split tuple sort array into parallel freq/sym arrays for better cache locality during insertion sort. Eliminates tuple allocation and separate leaf_freq/leaf_sym copy step. Allocations: Use make_uninit_int for leaf_freq, leaf_sym, node_freq, and RLE all arrays (immediately overwritten, no zeroing needed). Use make_uninit for BitWriter buffer growth in ensure_capacity. Block encoding: Cache codes arrays as locals and use unsafe_get to eliminate method call overhead in the token encoding loop. 321/321 tests, 170/170 parity.
1 parent 3fbdae6 commit b8d4502

3 files changed

Lines changed: 31 additions & 24 deletions

File tree

flate/bit_writer.mbt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn BitWriter::ensure_capacity(self : BitWriter, needed : Int) -> Unit {
2222
} else {
2323
self.pos + needed
2424
}
25-
let new_buf = FixedArray::make(new_cap, b'\x00')
25+
let new_buf = @blit.make_uninit(new_cap)
2626
@blit.blit_fixed_array(new_buf, 0, self.buf, 0, self.pos)
2727
self.buf = new_buf
2828
}
@@ -202,6 +202,9 @@ fn BitWriter::write_dynamic_block(
202202
self.write_dynamic_header_precomputed(
203203
lit_bl, dist_bl, cl_codes, cl_bl, hlit, hdist, hclen, is_final,
204204
)
205+
// Cache codes arrays in locals to avoid method call overhead
206+
let lit_c = dyn_lit_codes.codes
207+
let dist_c = dyn_dist_codes.codes
205208
for t in tokens {
206209
if t.is_match() {
207210
let length = t.get_length()
@@ -210,7 +213,7 @@ fn BitWriter::write_dynamic_block(
210213
let length_code = length_encode_table[lidx]
211214
let length_extra_bits = length_encode_table[lidx + 1]
212215
let length_extra_val = length_encode_table[lidx + 2]
213-
let lentry = dyn_lit_codes.get(length_code)
216+
let lentry = lit_c.unsafe_get(length_code)
214217
self.write_bits_lsb(lentry >> 5, (lentry & 0x1FU).reinterpret_as_int())
215218
if length_extra_bits > 0 {
216219
self.write_bits_lsb(
@@ -222,7 +225,7 @@ fn BitWriter::write_dynamic_block(
222225
let dist_code = dist_encode_table[didx]
223226
let dist_extra_bits = dist_encode_table[didx + 1]
224227
let dist_extra_val = dist - dist_base[dist_code]
225-
let dentry = dyn_dist_codes.get(dist_code)
228+
let dentry = dist_c.unsafe_get(dist_code)
226229
self.write_bits_lsb(dentry >> 5, (dentry & 0x1FU).reinterpret_as_int())
227230
if dist_extra_bits > 0 {
228231
self.write_bits_lsb(
@@ -231,11 +234,11 @@ fn BitWriter::write_dynamic_block(
231234
)
232235
}
233236
} else {
234-
let entry = dyn_lit_codes.get(t.get_literal().to_int())
237+
let entry = lit_c.unsafe_get(t.get_literal().to_int())
235238
self.write_bits_lsb(entry >> 5, (entry & 0x1FU).reinterpret_as_int())
236239
}
237240
}
238-
let eob = dyn_lit_codes.get(END_BLOCK_MARKER)
241+
let eob = lit_c.unsafe_get(END_BLOCK_MARKER)
239242
self.write_bits_lsb(eob >> 5, (eob & 0x1FU).reinterpret_as_int())
240243
}
241244
}
@@ -262,7 +265,7 @@ fn BitWriter::write_dynamic_header_precomputed(
262265
self.write_bits_lsb(cl_bl[code_order[i]].reinterpret_as_uint(), 3)
263266
}
264267
let total = hlit + hdist
265-
let all = FixedArray::make(total, 0)
268+
let all = @blit.make_uninit_int(total)
266269
for i in 0..<hlit {
267270
all[i] = lit_bl[i]
268271
}

flate/deflater.mbt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,11 @@ fn Deflater::step_lazy(self : Deflater) -> Unit {
511511
} else {
512512
max_chain
513513
}
514+
// Cache the comparison byte to avoid repeated array lookup
515+
let mut w_end = window.unsafe_get(i + best_len)
514516
while pos >= 0 && i - pos <= MAX_MATCH_OFFSET && chain_count < chain_limit {
515-
if best_len > 0 &&
516-
window.unsafe_get(pos + best_len) != window.unsafe_get(i + best_len) {
517+
// Skip check: compare byte at best_len position first
518+
if window.unsafe_get(pos + best_len) != w_end {
517519
let next = prev.unsafe_get(pos & WINDOW_MASK)
518520
if next >= pos {
519521
break
@@ -529,6 +531,7 @@ fn Deflater::step_lazy(self : Deflater) -> Unit {
529531
if best_len >= nice || best_len == max_len {
530532
break
531533
}
534+
w_end = window.unsafe_get(i + best_len)
532535
}
533536
let next = prev.unsafe_get(pos & WINDOW_MASK)
534537
if next >= pos {

flate/huffman_encoder.mbt

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,34 +74,35 @@ fn compute_bit_lengths(
7474
}
7575
return bit_lengths
7676
}
77-
let sorted = FixedArray::make(active, (0, 0))
77+
// Use parallel arrays instead of tuple array for better cache locality
78+
let leaf_freq = @blit.make_uninit_int(active)
79+
let leaf_sym = @blit.make_uninit_int(active)
7880
for i = 0, idx = 0; i < n; {
7981
if freqs[i] > 0 {
80-
sorted[idx] = (freqs[i], i)
82+
leaf_freq[idx] = freqs[i]
83+
leaf_sym[idx] = i
8184
continue i + 1, idx + 1
8285
}
8386
continue i + 1, idx
8487
}
88+
// Insertion sort by frequency (parallel arrays)
8589
for i in 1..<active {
86-
let key = sorted[i]
90+
let kf = leaf_freq[i]
91+
let ks = leaf_sym[i]
8792
let mut j = i - 1
88-
while j >= 0 && sorted[j].0 > key.0 {
89-
sorted[j + 1] = sorted[j]
93+
while j >= 0 && leaf_freq[j] > kf {
94+
leaf_freq[j + 1] = leaf_freq[j]
95+
leaf_sym[j + 1] = leaf_sym[j]
9096
j -= 1
9197
}
92-
sorted[j + 1] = key
93-
}
94-
let leaf_freq = FixedArray::make(active, 0)
95-
let leaf_sym = FixedArray::make(active, 0)
96-
for i, entry in sorted {
97-
leaf_freq[i] = entry.0
98-
leaf_sym[i] = entry.1
98+
leaf_freq[j + 1] = kf
99+
leaf_sym[j + 1] = ks
99100
}
100101
let total_nodes = 2 * active - 1
101102
let parent = FixedArray::make(total_nodes, -1)
102-
let node_freq = FixedArray::make(total_nodes, 0)
103-
for i, f in leaf_freq {
104-
node_freq[i] = f
103+
let node_freq = @blit.make_uninit_int(total_nodes)
104+
for i in 0..<active {
105+
node_freq[i] = leaf_freq[i]
105106
}
106107
let mut leaf_ptr = 0
107108
let mut int_ptr = active
@@ -308,7 +309,7 @@ fn rle_count_freqs(
308309
cl_freqs : FixedArray[Int],
309310
) -> Unit {
310311
let total = hlit + hdist
311-
let all = FixedArray::make(total, 0)
312+
let all = @blit.make_uninit_int(total)
312313
for i in 0..<hlit {
313314
all[i] = lit_bl[i]
314315
}

0 commit comments

Comments
 (0)