Repository navigation
Performance improvements - #357
Merged
Merged
Conversation
…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>
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.
Codecov Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
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.
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. |
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Opening a box reads every frame of the file and verifies the CRC of the whole frame, value included, even for a
LazyBox(BinaryReaderImpl.readFramechecks 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.computeuses slicing-by-8. Eight 256-entryUint32Listtables (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.loadBytescopies the leftover bytes withsetRangeinstead of a byte-by-byte loop.FrameIoHelper.keysFromFilereads 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.
openLazyBoxon 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.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
Crc32.computewith 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.setRangeoffset and disabling the big-box branch all make the new tests fail.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