-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c53519
commit a8145f4
Showing
1 changed file
with
36 additions
and
30 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,47 @@ | ||
# mini-alloc | ||
|
||
`mini-alloc` is a very small bump allocator for wasm32 intended to be used as | ||
the global Rust allocator. It never deallocates memory -- that is, `dealloc` | ||
does nothing. It's suitable for cases where binary size is at a premium and | ||
it's acceptable to leak all allocations. | ||
`mini-alloc` is a small and performant allocator optimized for `wasm32` targets like [Arbitrum Stylus][Stylus]. You can use it in your program as follows. | ||
```rust | ||
#[global_allocator] | ||
static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT; | ||
``` | ||
|
||
One other major limitation: this crate is not thread safe! `MiniAlloc` | ||
implements `Sync` because that is a required of a global allocator, but this is | ||
not a valid implementation of `Sync`, and it must only be used from a single | ||
thread. | ||
## Benchmarks | ||
|
||
Also, `core::arch::wasm32::memory_grow` must never be called by any code outside | ||
this crate. | ||
`mini-alloc` implements a minimal bump allocator strategy. It never deallocates memory -- that is, `dealloc` does nothing. It's suitable for cases where binary size is at a premium and it's acceptable to leak all allocations. The simplicity of this model makes it very efficient, as seen in the following benchmarks. | ||
|
||
On targets other than wasm32, `MiniAlloc` simply forwards to the allocator from | ||
another crate, `wee_alloc::WeeAlloc`. | ||
| | `MiniAlloc` | [`WeeAlloc`][WeeAlloc] | Std Library | | ||
|--------------|-------------|------------------------|----------------| | ||
| alloc | 333 gas | 721 gas | 516 gas | | ||
| alloc_zeroed | 329 gas | 95 million gas | 48 million gas | | ||
|
||
`mini-alloc` uses less ink on | ||
[Stylus](https://github.com/OffchainLabs/stylus-sdk-rs) compared to other | ||
allocators. When running the `edge_cases` test in this crate on Stylus, here are | ||
ink costs (minus the cost of memory expansion) when using `MiniAlloc` vs | ||
`WeeAlloc` and Rust's default allocator. | ||
The benchmarks compare the performance of this crate's `edge_cases` test in the [Stylus VM][StylusVM]. Normal allocations are over **2x** cheaper than when using [`WeeAlloc`][WeeAlloc], a common WASM alternative that this crate defaults to when built for non-WASM targets. | ||
|
||
Replacing each instance of `alloc` in the test with `alloc_zeroed` reveals an over **99%** improvement for zero-filled allocations. Unlike [`WeeAlloc`][WeeAlloc] and the standard library, `MiniAlloc` takes advantage of the fact that WASM pages are zero-filled at initialization, and uses fewer of them due to the layout of Rust's memory. | ||
|
||
| | MiniAlloc | WeeAlloc | Default | | ||
| ------------- | ------------ | ------------ | ------------ | | ||
| alloc | 3324474 | 7207816 | 5163328 | | ||
| alloc_zeroed | 3288777 | 954023099920 | 484822031511 | | ||
In the above tests we disable memory expansion costs, which unfairly penelize `WeeAlloc` and the standard library due to their increased resource consumption. | ||
|
||
`alloc` means `edge_cases` was run as it appears in this crate. `alloc_zeroed` | ||
means the calls to `alloc` were replaced with calls to `alloc_zeroed`. We can | ||
achieve substantial savings in this case because newly expanded memory in WASM | ||
is already zeroed. | ||
## Notice | ||
|
||
Use `MiniAlloc` like this: | ||
`MiniAlloc` should not be used in `wasm32` environments that enable the multithreading proposal. Although `MiniAlloc` implements `Sync` since Rust requires it for the global allocator, this crate should not be used in this way. This should not be a concern in [`Stylus`][Stylus]. | ||
|
||
```rust | ||
#[global_allocator] | ||
static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT; | ||
``` | ||
Also, `core::arch::wasm32::memory_grow` must never be called by any code outside this crate. | ||
|
||
On targets other than wasm32, `MiniAlloc` simply forwards to the allocator from another crate, `wee_alloc::WeeAlloc`. | ||
|
||
## License | ||
|
||
© 2023 Offchain Labs, Inc. | ||
|
||
This project is licensed under either of | ||
|
||
- [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([licenses/Apache-2.0](../licenses/Apache-2.0)) | ||
- [MIT license](https://opensource.org/licenses/MIT) ([licenses/MIT](../licenses/MIT)) | ||
|
||
at your option. | ||
|
||
The [SPDX](https://spdx.dev) license identifier for this project is `MIT OR Apache-2.0`. | ||
|
||
[Stylus]: https://github.com/OffchainLabs/stylus-sdk-rs | ||
[StylusVM]: https://github.com/OffchainLabs/stylus | ||
[WeeAlloc]: https://github.com/rustwasm/wee_alloc |