4 releases (2 breaking)
new 0.3.0 | Nov 3, 2024 |
---|---|
0.2.1 | Nov 3, 2024 |
0.2.0 | Nov 2, 2024 |
0.1.0 | Nov 2, 2024 |
#90 in Memory management
283 downloads per month
83KB
2K
SLoC
lightweight-mmap
About
Simple memory mapping helpers for Rust, with minimal amount of code generated.
This crate provides the facilities for opening a file and mapping it to memory with the minimal amount of code generated.
Motivation
This crate is for absolute freaks like me who wish to save 3-8KB of code size in their binaries;
with a thin limited wrapper providing complete zero overhead abstraction. Since std
and 3rd party
mmap crates will compile and run a small amount of code which may not be needed for your use case.
If you have more advanced needs than present in this crate, consider using std
for opening
file handles and a library like memmap2-rs and mmap-rs for mapping.
The API surface here is driven by sewer56-archives-nx and any other projects of mine which need mmap in a tiny package.
Characteristics
- Minimal code size overhead
- Platform-native file handles
- Read-only and read-write memory mappings
- Support for offset and length in mappings
- Supports zero sized mappings.
- Supports mappings to unaligned file offsets.
- Cross-platform compatibility
- Thread-safe (
Send
but notSync
) - All opened handles can be accessed by multiple processes (Linux behaviour)
Crate Features
std
(default): Enables standard library supportmmap
(default): Enables memory map operations, addingmmap
cache info to handles on some platforms. Without this, library can only be used for opening raw file handles.no-format
: Reduces binary size by skippingcore::fmt
formatting machinery as much as possible. Uses itoa and nanokit crates for minimal formatting.trim-file-lengths
: Ensures memory maps cannot exceed file size by trimming mapping length. Adds a small overhead to map open time.
To use without standard library:
[dependencies]
lightweight-mmap = { version = "x.y.z", default-features = false }
To minimize binary size:
[dependencies]
lightweight-mmap = { version = "x.y.z", features = ["no-format"] }
Whether you should use no-format
should depend on whether you already use core::fmt
elsewhere in your
library/binary. Check with cargo bloat. If you don't, it's best to use no-format
to reduce binary size.
Platform Support
The crate is tested and supported on:
Windows
- x86_64-pc-windows-msvc
- i686-pc-windows-msvc
- aarch64-pc-windows-msvc
Linux
- x86_64-unknown-linux-gnu
- i686-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- armv7-unknown-linux-gnueabihf
macOS
- x86_64-apple-darwin
- aarch64-apple-darwin
Android
- x86_64-linux-android
- i686-linux-android
For other platforms, level of support is unknown.
Examples
File Handles
Open a read-only file handle to an existing file:
let handle = ReadOnlyFileHandle::open("assets/test_file.txt").unwrap();
Open a read-write file handle to an existing file:
let handle = ReadWriteFileHandle::open("assets/test_file.txt").unwrap();
Create a new file with pre-allocated size:
let handle = ReadWriteFileHandle::create_preallocated("assets/test_file.txt", 1024).unwrap();
This will create a new file or overwrite an existing file.
Memory Mapping
Create a read-only memory mapping:
use lightweight_mmap::{ReadOnlyFileHandle, ReadOnlyMmap};
// Open the file
let handle = ReadOnlyFileHandle::open("data.bin").unwrap();
// Map 1024 bytes starting at offset 4096
let mapping = ReadOnlyMmap::new(&handle, 4096, 1024).unwrap();
// Access the mapped memory
let data = mapping.as_slice();
Create a read-write memory mapping:
use lightweight_mmap::{ReadWriteFileHandle, ReadWriteMmap};
// Open the file
let handle = ReadWriteFileHandle::open("data.bin").unwrap();
// Map 1024 bytes starting at offset 4096
let mapping = ReadWriteMmap::new(&handle, 4096, 1024).unwrap();
// Access and modify the mapped memory
unsafe {
let data = core::slice::from_raw_parts_mut(mapping.data(), mapping.len());
data[0] = 42;
}
Note: Memory mappings cannot outlive their file handles (compiler should ensure this), and the mapped memory should be accessed carefully to avoid data races.
Memory Advice
Provide hints to the operating system about how memory mapped regions will be accessed:
use lightweight_mmap::{ReadOnlyFileHandle, ReadOnlyMmap, MemoryAdvice};
// Open and map the file
let handle = ReadOnlyFileHandle::open("data.bin").unwrap();
let mapping = ReadOnlyMmap::new(&handle, 0, 1024).unwrap();
// Indicate we'll access this memory soon
mapping.advise(MemoryAdvice::WILL_NEED);
// Indicate sequential access pattern
mapping.advise(MemoryAdvice::SEQUENTIAL);
// Combine multiple hints
mapping.advise(MemoryAdvice::WILL_NEED | MemoryAdvice::SEQUENTIAL);
Available advice flags:
WILL_NEED
: Indicates that the application expects to access the memory soonSEQUENTIAL
: Indicates that memory access will be sequential from lower to higher addressesRANDOM
: Indicates that memory access will be random (non-sequential)
Note: These are hints and may be ignored by the operating system.
Not all hints are supported on all platforms. On Windows, only WILL_NEED
has an effect.
Development
For information on how to work with this codebase, see README-DEV.MD.
License
Licensed under MIT.
Learn more about Reloaded's general choice of licensing for projects..
Dependencies
~0.3–8.5MB
~77K SLoC