omnizip 0.3.22 → 0.3.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11b7628df01cd834c493cd96ba094783f65997f4c306356b653bd6c7dec27910
4
- data.tar.gz: 40853fd564d6fa1286f995f9b04d62e916aa26b56a7d395e067fe32d706e5730
3
+ metadata.gz: 61cf26f9e324600f286b236ab80e02d720059f32bca2fa3c71640ba3abc4355a
4
+ data.tar.gz: fa189e081e402ecb4d084490e7874402faacf231a296cd009a15f218fcd9453e
5
5
  SHA512:
6
- metadata.gz: cb7ed5d3b46761cccd18a471ad1794aad849981f79c822ad7c8c6670cac260b1af28e7cfd368b894afc41613ca7070fb04a5a4bdef10ffff28f662f2e04add1a
7
- data.tar.gz: f9396815f4ed33c8813812bed12a0f8b54923eaea1a22d62809d15c826b87e0b32aad00c2ea4cc223cffcb36fab6fc97fa1f8401d68a2fd4c31e1937f485e5d4
6
+ metadata.gz: 308660d6095a909d72c528bdfb5e828e76d320172b979a53ef7401aa2c1c12a560a0afd57f49991eb5190f87deca1c15cd798e8abae89bd3341ed3bb43c39b3d
7
+ data.tar.gz: 29ac9066539f2d8cef3973a2eb9cfe15a549a5efead04a1f5c88f28587fb6a2d23ac28c401c1c4187f5c226bfe4b531e3565523400dcd183adc83c842cd2d5dc
data/CHANGELOG.md CHANGED
@@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.23] - 2026-08-26
11
+
12
+ ### Changed
13
+ - Zstd encoder hot paths use allocation-free integer reads instead of
14
+ `String#byteslice` + `unpack1` comparisons (profiling showed GC at
15
+ 52% of encoder time): default-level compression is ~3.4x faster and
16
+ level 22 ~1.9x on the benchmark corpus, with byte-identical output.
17
+
18
+ ## [0.3.22] - 2026-08-25
19
+
20
+ ### Added
21
+ - Zstandard dictionary compression (`Dictionary.from_raw` /
22
+ `serialize` / `deserialize`, `compress_with_dict`,
23
+ `decompress_with_dict`): the dictionary content primes the match
24
+ finder as shared history and the frame header carries the
25
+ Dictionary_ID, which the decoder verifies (Phase-1 scope, as in the
26
+ Rust reference; entropy-table preloading is future work).
27
+
28
+ ## [0.3.21] - 2026-08-25
29
+
30
+ ### Fixed
31
+ - 7-Zip encoder dictionary is now capped at the size announced in the
32
+ coder properties (prevents matches reading outside the decoder
33
+ window for inputs above the announced size).
34
+
35
+ ### Changed
36
+ - Zstd lazy levels (6+) gained the rep0 fast-path and backward
37
+ extension: levels 6-12 improve 0.180 -> 0.154 and levels 19-22
38
+ 0.146 -> 0.126 on the benchmark corpus; the level scale is now
39
+ monotonic.
40
+ - Zstd adaptive block splitting: heterogeneous chunks of 32 KiB or
41
+ more split into 16 KiB sub-blocks so entropy tables fit each
42
+ content regime.
43
+
44
+ ## [0.3.20] - 2026-08-25
45
+
46
+ ### Removed
47
+ - Dead `SevenZipLZMA2`/`XZLZMA2` algorithm wrappers (never
48
+ autoloaded; one referenced a nonexistent decoder constant).
49
+
10
50
  ## [0.3.19] - 2026-08-25
11
51
 
12
52
  ### Fixed
@@ -131,11 +131,29 @@ module Omnizip
131
131
  min_match: MIN_MATCH_ECONOMICAL }
132
132
  end
133
133
 
134
- def hash4(src, pos, h_bits)
135
- v = src.getbyte(pos) |
134
+ # Allocation-free little-endian reads; the hot loops call
135
+ # these millions of times, and String#byteslice + unpack1
136
+ # showed up as half the encoder's time via GC pressure.
137
+ def read4(src, pos)
138
+ src.getbyte(pos) |
136
139
  (src.getbyte(pos + 1) << 8) |
137
140
  (src.getbyte(pos + 2) << 16) |
138
141
  (src.getbyte(pos + 3) << 24)
142
+ end
143
+
144
+ def read8(src, pos)
145
+ src.getbyte(pos) |
146
+ (src.getbyte(pos + 1) << 8) |
147
+ (src.getbyte(pos + 2) << 16) |
148
+ (src.getbyte(pos + 3) << 24) |
149
+ (src.getbyte(pos + 4) << 32) |
150
+ (src.getbyte(pos + 5) << 40) |
151
+ (src.getbyte(pos + 6) << 48) |
152
+ (src.getbyte(pos + 7) << 56)
153
+ end
154
+
155
+ def hash4(src, pos, h_bits)
156
+ v = read4(src, pos)
139
157
  # 32-bit wrapping multiply (C/uint32_t), then the high bits.
140
158
  ((v * PRIME4_BYTES) & 0xFFFFFFFF) >> (32 - h_bits)
141
159
  end
@@ -148,8 +166,8 @@ module Omnizip
148
166
  b_size = b.bytesize
149
167
  while len + 8 <= limit && a_pos + len + 8 <= a_size &&
150
168
  b_pos + len + 8 <= b_size
151
- wa = a.byteslice(a_pos + len, 8).unpack1("Q<")
152
- wb = b.byteslice(b_pos + len, 8).unpack1("Q<")
169
+ wa = read8(a, a_pos + len)
170
+ wb = read8(b, b_pos + len)
153
171
  if wa == wb
154
172
  len += 8
155
173
  else
@@ -289,8 +307,7 @@ module Omnizip
289
307
  # rubocop:disable-next Metrics/AbcSize
290
308
  def rep0_match(src, ip, rep0, min_match, limit, anchor)
291
309
  return nil if rep0 <= 0 || ip <= rep0
292
- return nil if src.byteslice(ip, MIN_MATCH) !=
293
- src.byteslice(ip - rep0, MIN_MATCH)
310
+ return nil if read4(src, ip) != read4(src, ip - rep0)
294
311
 
295
312
  m_len = MIN_MATCH + count_match(
296
313
  src, ip + MIN_MATCH, src, ip + MIN_MATCH - rep0,
@@ -346,7 +363,7 @@ module Omnizip
346
363
  break if dist >= max_distance
347
364
  break if candidate + MIN_MATCH > size
348
365
 
349
- if src.byteslice(ip, MIN_MATCH) == src.byteslice(candidate, MIN_MATCH)
366
+ if read4(src, ip) == read4(src, candidate)
350
367
  m_len = MIN_MATCH + count_match(src, ip + MIN_MATCH,
351
368
  src, candidate + MIN_MATCH,
352
369
  [max_extend - MIN_MATCH, 0].max)
@@ -397,7 +414,7 @@ module Omnizip
397
414
  if candidate.positive? && candidate < ip
398
415
  dist = ip - candidate
399
416
  if dist < max_distance && candidate + MIN_MATCH <= size &&
400
- src.byteslice(ip, MIN_MATCH) == src.byteslice(candidate, MIN_MATCH)
417
+ read4(src, ip) == read4(src, candidate)
401
418
  best_len = MIN_MATCH + count_match(
402
419
  src, ip + MIN_MATCH, src, candidate + MIN_MATCH,
403
420
  [limit + MIN_MATCH_ECONOMICAL - ip - MIN_MATCH, 0].max
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Omnizip
4
- VERSION = "0.3.22"
4
+ VERSION = "0.3.23"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omnizip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.22
4
+ version: 0.3.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.