Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faust: Update the memory allocation issue doc #1011

Merged
merged 1 commit into from
Apr 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions architecture/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,19 @@ As usual with faust2xx tools, other Faust compiler specific options can be given

## Memory allocation issues

At the moment, there is no formal way to allocate an arbitrary struct on the heap in rust. The current approach taken by Faust is to allocate the dsp with `Box::new(Dsp::new())` which would be expected to first allocate on stack then move on heap, but this move is optimized away in release and it's allocated directly on the heap. However, when running in debug mode, the intermediary allocation is here making any echo or reverb very likely to stack overflow.
A DSP can be large in memory and allocating it on the heap by using [Box](https://doc.rust-lang.org/std/boxed/struct.Box.html) is often necessary to avoid stack overflows. Unfortunately, Rust does not have a native way to directly allocate on the heap, and `let dsp = Box::new(Dsp::new())` will only solve the problem in release build where the intermediary stack allocation will be optimized away.

The standard way is to allocate the DSP on the heap with the help of the third-party `crate default-boxed`.
Faust fixes this problem with the help of the crate [default-boxed](https://docs.rs/default-boxed/latest/default_boxed/) that generates a method that allocates a struct on the heap. When using the generated architecture files, the project is already configured to use this crate and directly allocate on the heap. If you are not using the generated architecture files, ensure that the `Cargo.toml` file building the generated code contains the dependency to `default-boxed` and the feature `default-boxed`:

The change in the generated code of Faust is very conservative: it's under conditional compilation with a feature, disabled by default. When the feature is enabled, it adds a `new default_boxed()` method. This change should not break any user, including in specific environment such as embedded/no-std. The following code can be used to setup the allocation:
```toml
[dependencies]
default-boxed = { version = "0.2.0", optional = true }

```Rust
let mut dsp;
#[cfg(feature = "default-boxed")]
{
use default_boxed::DefaultBoxed;
dsp = mydsp::default_boxed();
}

#[cfg(not(feature = "default-boxed"))]
{
dsp = Box::new(mydsp::new());
}
[features]
default = ["default-boxed"]
default-boxed = ["dep:default-boxed"]
```

Then, allocate the DSP with `let dsp = Dsp::default_boxed()` instead of `let dsp = Box::new(Dsp::new())`.

This feature can be opted out by building without the `default-boxed` feature, for example with `--no-default-features`. This removes both the `default-boxed` dependency and the `::default_boxed()` method.
Loading