LocalWalSyncImpl._flush - Out of Memory crash#4539
Conversation
- Change _wals initialization from const [] to mutable [] to prevent "Cannot add to unmodifiable list" crash - Write WAL frames to disk incrementally using IOSink instead of building entire data list in memory to prevent OOM - Free in-memory data after flushing to disk - Continue instead of throwing when file path is unavailable Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request effectively addresses a critical Out of Memory (OOM) crash during WAL flushing by switching to an incremental write approach using IOSink. The changes also fix a crash related to modifying an unmodifiable list and gracefully handle cases where a WAL file path is unavailable. Additionally, a subtle but critical bug involving loop variable shadowing has been resolved. The memory footprint is further reduced by clearing WAL data after it's been flushed to disk. The overall solution is robust and well-implemented. I've added one suggestion to further optimize the file writing logic for better performance and readability.
| final byteFrame = ByteData(frame.length); | ||
| for (int k = 0; k < frame.length; k++) { | ||
| byteFrame.setUint8(k, frame[k]); | ||
| } | ||
| sink.add(Uint32List.fromList([frame.length]).buffer.asUint8List()); | ||
| sink.add(byteFrame.buffer.asUint8List()); |
There was a problem hiding this comment.
This block manually copies bytes from frame into a new ByteData buffer. Since wal.data likely contains Uint8List instances from the byte stream, frame (which is a sublist of an element from wal.data) is also a Uint8List. You can add it to the sink directly, which is more efficient and readable, avoiding the unnecessary allocation and byte-by-byte copy.
sink.add(Uint32List.fromList([frame.length]).buffer.asUint8List());
sink.add(frame);
Summary
_walsas mutable[]instead ofconst []Crash Stats (combined iOS + Android)
Test plan
🤖 Generated with Claude Code