Skip to content

Performance improvements - #357

Merged
Rexios80 merged 9 commits into
IO-Design-Team:mainfrom
jonasbernardo:faster-box-open
Nov 6, 2026
Merged

Rexios80 merged 9 commits into
IO-Design-Team:mainfrom
jonasbernardo:faster-box-open

Conversation

@jonasbernardo

Copy link
Copy Markdown
Contributor

Opening a box reads every frame of the file and verifies the CRC of the whole frame, value included, even for a LazyBox (BinaryReaderImpl.readFrame checks it before deciding to keep only the key). In our app, opening a 59 MB lazy box with 1,518 keys was the biggest wait between the splash screen and the first content. Three changes make it about twice as fast, without touching the file format:

  • Crc32.compute uses slicing-by-8. Eight 256-entry Uint32List tables (8 KB, built once) let the loop consume eight bytes per iteration instead of one. The result is bit-identical to the old byte-at-a-time table.
  • BufferedFileReader.loadBytes copies the leftover bytes with setRange instead of a byte-by-byte loop.
  • FrameIoHelper.keysFromFile reads boxes bigger than 1 MiB in 1 MiB chunks instead of 64 KB ones. Boxes up to 1 MiB keep the default chunk.

Measurements

Android, Infinix X6837 (8 GB RAM), profile (AOT) build. openLazyBox on a cold process, in a background isolate, crashRecovery: false. One APK containing all four variants, the variant picked per launch; alternating order (ABCD/DCBA); 2 rounds × 10 launches per variant. Every paired launch was faster than the original.

Box Original CRC only Copy + chunk only All three
59 MB, 1,518 keys 1,455 ms 1,154 ms (−21%) 965 ms (−34%) 716–733 ms (−50%)
6 MB, 360 keys 182 ms 143–158 ms 111 ms 71–81 ms (−56 to −61%)

On an M4 Pro Mac (AOT executable), the same 59 MB box opened in ~218 ms before and ~51 ms after (−77%); there the CRC alone accounted for most of it.

Correctness

  • New unit tests compare Crc32.compute with a bitwise reference (no tables) for every offset 0–15 × length 0–300 × six initial CRCs, unaligned views, a 1 MiB buffer and chained calls. They run on the VM, dart2js and dart2wasm.
  • A new integration test reopens normal and lazy boxes whose frames (up to ~150 KB) straddle the read chunks.
  • Each change was checked by breaking it: swapping two tables, a wrong shift, a wrong setRange offset and disabling the big-box branch all make the new tests fail.
  • Outside the repo, on the real 59 MB box: on the device, the new CRC matches the old one and the stored CRC of all 1,649 frames, the whole-file CRC matches zlib.crc32, and 20,000 random slices with random initial CRCs and unaligned views match. On the Mac, recovery of 7 damaged copies (truncated mid-frame, flipped bytes) ends at the same size with the same keys, and files written by either version are byte-identical and readable by the other.

🤖 Generated with Claude Code

…unks for big boxes

Opening a box reads every frame and checks the CRC of the whole frame,
even for a LazyBox. Crc32.compute now consumes eight bytes per iteration
(slicing-by-8, bit-identical results), BufferedFileReader copies leftover
bytes with setRange, and keysFromFile reads boxes bigger than 1 MiB in
1 MiB chunks. Opening a 59 MB lazy box on an Android device goes from
1,455 ms to ~720 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rexios80

Rexios80 commented Nov 6, 2026

Copy link
Copy Markdown
Member

This PR touches internals I am not very familiar with. It will take a while to validate.

Custom ciphers can return a key CRC outside of 32 bits, and masking it
changed the checksums of boxes they already wrote. Such a CRC is now
processed one byte at a time first, so results match the previous
implementation for every input. Also closes the file if reading its
length fails, trims the CRC tests, drops the redundant chunk integration
test, and bumps the version to 2.22.1.
Raise the skip list height cap from 12 to 32 so lookups and inserts stay logarithmic past ~4k keys, and generate AES IVs with four 32-bit secure random calls instead of sixteen 8-bit ones.
Store compact copies of written values instead of views over the 4 KB
writer buffer, cancel watch subscriptions when a listener cancels, and
require isolate_channel 0.6.2.
@Rexios80 Rexios80 changed the title Faster box opening: slicing-by-8 CRC32, bulk buffer copy, bigger chunks for big boxes Performance improvements Nov 6, 2026
@codecov

codecov Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.89%. Comparing base (6dfa776) to head (7f7d9e6).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #357      +/-   ##
==========================================
+ Coverage   93.78%   93.89%   +0.11%     
==========================================
  Files          66       66              
  Lines        2685     2734      +49     
==========================================
+ Hits         2518     2567      +49     
  Misses        167      167              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Boxes opened in the Hive isolate now write frames and read lazy values
with synchronous file IO, which avoids the async IO round trip on every
operation.
@Rexios80
Rexios80 merged commit 4eee4f8 into IO-Design-Team:main Nov 6, 2026
1 check passed
@Rexios80

Rexios80 commented Nov 6, 2026

Copy link
Copy Markdown
Member

Thank you for the contribution! This made me curious what other optimizations could be made, and now IsolatedHive is also waaay faster. Even faster than normal Hive in some cases. This is released as v2.23.0.

@jonasbernardo

Copy link
Copy Markdown
Contributor Author

I'm happy to be able to contribute; I've always had this problem with slow opening times. Compared to other solutions, AI helped solve

@jonasbernardo
jonasbernardo deleted the faster-box-open branch November 7, 2026 00:14
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.

2 participants