HLO: IrpaWriter accepts FileBacked mmap handles on JVM/Android (PR E of #523)#529
Merged
michalharakal merged 1 commit intodevelopfrom Apr 19, 2026
Merged
Conversation
… of #523) The gguf and safetensors loaders already produce `BufferHandle.FileBacked` via their `loadTensorStorageMapped` methods, but IrpaWriter previously rejected that variant with a placeholder throw pointing at PR E. This wires the real transfer path: JVM and Android actuals mmap the declared file range via `RandomAccessFile` + `FileChannel.map` and blit it into the sink with no intermediate heap copy. The full ingestion pipeline now runs source file → FileBacked handle → `.irpa` storage segment with zero-copy semantics end-to-end. ### What's wired - `writeFileBackedBytes` — `expect` in commonMain, `actual` per target. - JVM / Android — functional mmap. Android's Dalvik/ART exposes the same FileChannel API as desktop JVM, so the actuals are byte-for- byte identical (kept as separate files until this module adopts a hierarchical jvmAndroidMain source set). - Native (ios*, macos*, linux*), wasmJs, wasmWasi — explicit NotImplementedError with a pointer to #523. Browser wasm has no filesystem; Native mmap via cinterop is follow-up work. Callers on those targets should resolve to Owned/Borrowed first. ### Guardrails - Rejects FileBacked sizes > Int.MAX_VALUE with a clear diagnostic. FileChannel.map cannot return a single region that large; multi- window streaming is a follow-up once a real model hits the limit. - Zero-byte FileBacked is a no-op — does not open the source file. ### Tests - `FileBackedIrpaRoundTripTest.testFileBackedEntryBytesLandInStorageSegment` — writes a known byte pattern to a temp file at a non-aligned offset, constructs a FileBacked ref over a sub-range, runs through IrpaWriter, verifies the .irpa storage segment contains the source bytes verbatim. - `testFileBackedRejectsOversizedMap` — pins the Int.MAX_VALUE guard. - `testFileBackedZeroLengthIsNoOp` — pins that a 0-byte ref does not open the file (references a non-existent path). - `./gradlew allTests` green across all 1047 tasks. Part of #523. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
BufferHandle.FileBackedintoIrpaWriter. JVM and Android useFileChannel.mapfor zero-copy mmap transfer to the.irpastorage segment. Other targets throw with a pointer to follow-up work.FileBackedhandle (already produced by existingloadTensorStorageMappedmethods) →IrpaWriter→.irpabytes.What's here
expect fun writeFileBackedBytesin commonMain.RandomAccessFile+FileChannel.map+ chunked copy into the kotlinx.ioSink. Kept as separate files until this module adopts a hierarchicaljvmAndroidMainsource set.NotImplementedErrorwith a pointer to Design: externalize weights via IREE parameter archive (supersedes #519) #523 follow-up. Callers on those targets should resolve the handle toOwned/Borrowedbefore writing.IrpaWriter.writeBufferHandledispatchesFileBackedto the new seam.Guardrails
FileBacked.sizeInBytes > Int.MAX_VALUE—FileChannel.mapcan't return a single region larger than ~2 GiB. Multi-window streaming is a separate follow-up once a real model hits the limit.FileBackedis a no-op and does not open the source file.What's NOT here
skainet-io-ggufandskainet-io-safetensorsalready exposeloadTensorStorageMapped(filePath)that returnsBufferHandle.FileBacked. The agent exploration showed this path existed; PR E only had to wire the consumer side.Test plan
FileBackedIrpaRoundTripTest.testFileBackedEntryBytesLandInStorageSegment— writes a known byte pattern to a temp file at a non-aligned offset, constructs a FileBacked ref over a sub-range, runs through IrpaWriter, verifies the .irpa storage segment contains source bytes verbatim.testFileBackedRejectsOversizedMap— pins the Int.MAX_VALUE guard.testFileBackedZeroLengthIsNoOp— pins that 0-byte refs don't open the file (uses a non-existent path to prove it)../gradlew allTestsgreen — 1047 tasks across jvm / android / ios / macos / linux / wasmJs / wasmWasi.Part of #523. With this, PRs A–C + E are complete on the SKaiNET side. PR D (skainet-whisper caller wiring to flip policy →
ExternalAlways→IrpaWriter) lives in theskainet-whisperrepo and is the remaining step to actually close #519 end-to-end.🤖 Generated with Claude Code