Skip to content

Add RandomAccessFile.readMapped(Sync) to dart:io library  #49810

Open
@biggs0125

Description

@biggs0125

Proposal (draft change)

Add 2 methods, readMapped and readMappedSync, to the RandomAccessFile interface in the dart:io SDK package. These methods would expose the functionality of memory mapping files into the virtual address space (mmap). They would function similarly to the read/readSync methods but would avoid the allocation of a new Uint8List.

For simplicity we would mark the address space as “read protected”. This would be enforced within the Dart world by returning unmodifiable views of the Uint8Lists from the new methods. Here is the proposed file.dart API:

/// Loads the file into a memory mapped [Uint8List].
///
/// The resulting [Uint8List] is externally allocated and memory mapped into
/// the heap virtual address space. The allocated virtual memory space will
/// be marked as 'readonly' and so the Uint8List will be unmodifiable.
Future<Uint8List> readMapped();



/// Synchronously loads the file into a memory mapped [Uint8List].
///
/// The resulting [Uint8List] is externally allocated and memory mapped into
/// the heap virtual address space. The allocated virtual memory space will
/// be marked as 'readonly' and so the Uint8List will be unmodifiable.
///
/// Throws a [FileSystemException] if the operation fails.
Uint8List readMappedSync();

Goal

Reduce memory usage in Dart2JS running in sequential mode. In sequential mode Dart2JS serializes the results of its first 4 phases (kernel, closed world, global inference, codegen) after computing each of them. Then at the start of each phase, the results for all the previous phases are deserialized and loaded into memory. By the final phase we the serialized bytes for every phase of the compiler stored in memory. For large applications, this is a significant amount of memory stored in these byte arrays.

Justification

In some large applications we see hundreds of MBs saved in every phase of the Dart2JS compiler using this strategy. This peaks at around 700MB of memory saved in the final phase for these large applications. This also unblocks some further optimizations that can be made to preserve memory.

Breaking change overview

This change to the RandomAccessFile interface would be a breaking change as implementations of the interface would need to implement these new methods.

It is unlikely there are many implementers of this interface beyond the dart:io package itself. One known implementer is package:file which has 2 places that would need to be updated with these methods. MemoryRandomAccessFile and ForwardingRandomAccessFile would each have simple implementations of these methods: draft change

Note: The implementations in package:file are all marked as @override with a lint ignore. dart:io won't have the interface change yet. By landing that change first and setting the min SDK version of package:file to >= 2.19.0-dev we can avoid ever actually breaking package:file. These implementations will be valid overrides once dart:io is updated but before then they are just methods on those subclasses. The lint ignores will keep the analyzer from flagging these methods.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.library-iotriagedIssue has been triaged by sub teamtype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions