mirror of
https://github.com/ratatui/ratatui.git
synced 2025-09-29 22:11:34 +00:00
feat(no_std)!: option to disable layout cache for no_std
compatibility (#1795)
Resolves #1780 BREAKING CHANGE: Disabling `default-features` will now disable layout cache, which can have a negative impact on performance. `Layout::init_cache` and `Layout::DEFAULT_CACHE_SIZE` are now only available if `layout-cache` feature is enabled.
This commit is contained in:
parent
09173d1829
commit
ab48c06171
@ -20,6 +20,8 @@ This is a quick summary of the sections below:
|
|||||||
- `Backend` now uses `Self::Error` for error handling instead of `std::io::Error`
|
- `Backend` now uses `Self::Error` for error handling instead of `std::io::Error`
|
||||||
- `Terminal<B>` now uses `B::Error` for error handling instead of `std::io::Error`
|
- `Terminal<B>` now uses `B::Error` for error handling instead of `std::io::Error`
|
||||||
- `TestBackend` now uses `core::convert::Infallible` for error handling instead of `std::io::Error`
|
- `TestBackend` now uses `core::convert::Infallible` for error handling instead of `std::io::Error`
|
||||||
|
- Disabling `default-features` will now disable layout cache, which can have a negative impact on performance
|
||||||
|
- `Layout::init_cache` and `Layout::DEFAULT_CACHE_SIZE` are now only available if `layout-cache` feature is enabled
|
||||||
- [v0.29.0](#v0290)
|
- [v0.29.0](#v0290)
|
||||||
- `Sparkline::data` takes `IntoIterator<Item = SparklineBar>` instead of `&[u64]` and is no longer const
|
- `Sparkline::data` takes `IntoIterator<Item = SparklineBar>` instead of `&[u64]` and is no longer const
|
||||||
- Removed public fields from `Rect` iterators
|
- Removed public fields from `Rect` iterators
|
||||||
@ -84,6 +86,26 @@ This is a quick summary of the sections below:
|
|||||||
|
|
||||||
## Unreleased (0.30.0)
|
## Unreleased (0.30.0)
|
||||||
|
|
||||||
|
### `Layout::init_cache` and `Layout::DEFAULT_CACHE_SIZE` are now only available if `layout-cache` feature is enabled ([#1795])
|
||||||
|
|
||||||
|
[#1795]: https://github.com/ratatui/ratatui/pull/1795
|
||||||
|
|
||||||
|
Previously, `Layout::init_cache` and `Layout::DEFAULT_CACHE_SIZE` were available independently of
|
||||||
|
enabled feature flags.
|
||||||
|
|
||||||
|
### Disabling `default-features` will now disable layout cache, which can have a negative impact on performance ([#1795])
|
||||||
|
|
||||||
|
[#1795]: https://github.com/ratatui/ratatui/pull/1795
|
||||||
|
|
||||||
|
Layout cache is now opt-in in `ratatui-core` and enabled by default in `ratatui`. If app doesn't
|
||||||
|
make use of `no_std`-compatibility, and disables `default-feature`, it is recommended to explicitly
|
||||||
|
re-enable layout cache. Not doing so may impact performance.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- ratatui = { version = "0.29.0", default-features = false }
|
||||||
|
+ ratatui = { version = "0.30.0", default-features = false, features = ["layout-cache"] }
|
||||||
|
```
|
||||||
|
|
||||||
### `TestBackend` now uses `core::convert::Infallible` for error handling instead of `std::io::Error` ([#1823])
|
### `TestBackend` now uses `core::convert::Infallible` for error handling instead of `std::io::Error` ([#1823])
|
||||||
|
|
||||||
[#1823]: https://github.com/ratatui/ratatui/pull/1823
|
[#1823]: https://github.com/ratatui/ratatui/pull/1823
|
||||||
|
@ -24,6 +24,12 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
|
## enables std
|
||||||
|
std = []
|
||||||
|
|
||||||
|
## enables layout cache
|
||||||
|
layout-cache = ["std"]
|
||||||
|
|
||||||
## enables conversions to / from colors, modifiers, and styles in the ['anstyle'] crate
|
## enables conversions to / from colors, modifiers, and styles in the ['anstyle'] crate
|
||||||
anstyle = ["dep:anstyle"]
|
anstyle = ["dep:anstyle"]
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use alloc::format;
|
use alloc::format;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cell::RefCell;
|
|
||||||
use core::iter;
|
use core::iter;
|
||||||
use core::num::NonZeroUsize;
|
use core::num::NonZeroUsize;
|
||||||
use std::{dbg, thread_local};
|
use std::dbg;
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -39,8 +38,9 @@ type Cache = LruCache<(Rect, Layout), (Segments, Spacers)>;
|
|||||||
// calculations.
|
// calculations.
|
||||||
const FLOAT_PRECISION_MULTIPLIER: f64 = 100.0;
|
const FLOAT_PRECISION_MULTIPLIER: f64 = 100.0;
|
||||||
|
|
||||||
thread_local! {
|
#[cfg(feature = "layout-cache")]
|
||||||
static LAYOUT_CACHE: RefCell<Cache> = RefCell::new(Cache::new(
|
std::thread_local! {
|
||||||
|
static LAYOUT_CACHE: core::cell::RefCell<Cache> = core::cell::RefCell::new(Cache::new(
|
||||||
NonZeroUsize::new(Layout::DEFAULT_CACHE_SIZE).unwrap(),
|
NonZeroUsize::new(Layout::DEFAULT_CACHE_SIZE).unwrap(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -188,6 +188,8 @@ impl Layout {
|
|||||||
/// bit more to make it a round number. This gives enough entries to store a layout for every
|
/// bit more to make it a round number. This gives enough entries to store a layout for every
|
||||||
/// row and every column, twice over, which should be enough for most apps. For those that need
|
/// row and every column, twice over, which should be enough for most apps. For those that need
|
||||||
/// more, the cache size can be set with [`Layout::init_cache()`].
|
/// more, the cache size can be set with [`Layout::init_cache()`].
|
||||||
|
/// This const is unused if layout cache is disabled.
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub const DEFAULT_CACHE_SIZE: usize = 500;
|
pub const DEFAULT_CACHE_SIZE: usize = 500;
|
||||||
|
|
||||||
/// Creates a new layout with default values.
|
/// Creates a new layout with default values.
|
||||||
@ -280,8 +282,9 @@ impl Layout {
|
|||||||
/// grows until `cache_size` is reached.
|
/// grows until `cache_size` is reached.
|
||||||
///
|
///
|
||||||
/// By default, the cache size is [`Self::DEFAULT_CACHE_SIZE`].
|
/// By default, the cache size is [`Self::DEFAULT_CACHE_SIZE`].
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub fn init_cache(cache_size: NonZeroUsize) {
|
pub fn init_cache(cache_size: NonZeroUsize) {
|
||||||
LAYOUT_CACHE.with_borrow_mut(|c| c.resize(cache_size));
|
LAYOUT_CACHE.with_borrow_mut(|cache| cache.resize(cache_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the direction of the layout.
|
/// Set the direction of the layout.
|
||||||
@ -653,11 +656,18 @@ impl Layout {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub fn split_with_spacers(&self, area: Rect) -> (Segments, Spacers) {
|
pub fn split_with_spacers(&self, area: Rect) -> (Segments, Spacers) {
|
||||||
LAYOUT_CACHE.with_borrow_mut(|c| {
|
let split = || self.try_split(area).expect("failed to split");
|
||||||
let key = (area, self.clone());
|
|
||||||
c.get_or_insert(key, || self.try_split(area).expect("failed to split"))
|
#[cfg(feature = "layout-cache")]
|
||||||
.clone()
|
{
|
||||||
})
|
LAYOUT_CACHE.with_borrow_mut(|cache| {
|
||||||
|
let key = (area, self.clone());
|
||||||
|
cache.get_or_insert(key, split).clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "layout-cache"))]
|
||||||
|
split()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_split(&self, area: Rect) -> Result<(Segments, Spacers), AddConstraintError> {
|
fn try_split(&self, area: Rect) -> Result<(Segments, Spacers), AddConstraintError> {
|
||||||
@ -1200,14 +1210,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
fn cache_size() {
|
fn cache_size() {
|
||||||
LAYOUT_CACHE.with_borrow(|c| {
|
LAYOUT_CACHE.with_borrow(|cache| {
|
||||||
assert_eq!(c.cap().get(), Layout::DEFAULT_CACHE_SIZE);
|
assert_eq!(cache.cap().get(), Layout::DEFAULT_CACHE_SIZE);
|
||||||
});
|
});
|
||||||
|
|
||||||
Layout::init_cache(NonZeroUsize::new(10).unwrap());
|
Layout::init_cache(NonZeroUsize::new(10).unwrap());
|
||||||
LAYOUT_CACHE.with_borrow(|c| {
|
LAYOUT_CACHE.with_borrow(|cache| {
|
||||||
assert_eq!(c.cap().get(), 10);
|
assert_eq!(cache.cap().get(), 10);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,10 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
#!
|
#!
|
||||||
## By default, we enable the crossterm backend as this is a reasonable choice for most applications
|
## By default, we enable the crossterm backend as this is a reasonable choice for most applications
|
||||||
## as it is supported on Linux/Mac/Windows systems. We also enable the `underline-color` feature
|
## as it is supported on Linux/Mac/Windows systems. We also enable the `underline-color` feature
|
||||||
## which allows you to set the underline color of text and the `macros` feature which provides
|
## which allows you to set the underline color of text, the `macros` feature which provides
|
||||||
## some useful macros.
|
## some useful macros and `layout-cache` which speeds up layout cache calculations
|
||||||
default = ["crossterm", "underline-color", "all-widgets", "macros"]
|
## in `std`-enabled environments.
|
||||||
|
default = ["crossterm", "underline-color", "all-widgets", "macros", "layout-cache"]
|
||||||
#! Generally an application will only use one backend, so you should only enable one of the following features:
|
#! Generally an application will only use one backend, so you should only enable one of the following features:
|
||||||
## enables the [`CrosstermBackend`](backend::CrosstermBackend) backend and adds a dependency on [`crossterm`].
|
## enables the [`CrosstermBackend`](backend::CrosstermBackend) backend and adds a dependency on [`crossterm`].
|
||||||
crossterm = ["dep:ratatui-crossterm"]
|
crossterm = ["dep:ratatui-crossterm"]
|
||||||
@ -48,6 +49,9 @@ serde = [
|
|||||||
"ratatui-termwiz?/serde",
|
"ratatui-termwiz?/serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
## enables layout cache
|
||||||
|
layout-cache = ["ratatui-core/layout-cache"]
|
||||||
|
|
||||||
## enables conversions from colors in the [`palette`] crate to [`Color`](crate::style::Color).
|
## enables conversions from colors in the [`palette`] crate to [`Color`](crate::style::Color).
|
||||||
palette = ["ratatui-core/palette", "dep:palette"]
|
palette = ["ratatui-core/palette", "dep:palette"]
|
||||||
|
|
||||||
|
@ -54,6 +54,15 @@ impl Run for TestBackend {
|
|||||||
Backend::Termion => "termion",
|
Backend::Termion => "termion",
|
||||||
Backend::Termwiz => "termwiz",
|
Backend::Termwiz => "termwiz",
|
||||||
};
|
};
|
||||||
|
// This is a temporary hack to run tests both with and without layout cache.
|
||||||
|
// https://github.com/ratatui/ratatui/issues/1820
|
||||||
|
run_cargo(vec![
|
||||||
|
"test",
|
||||||
|
"--all-targets",
|
||||||
|
"--no-default-features",
|
||||||
|
"--features",
|
||||||
|
format!("{backend},layout-cache").as_str(),
|
||||||
|
])?;
|
||||||
run_cargo(vec![
|
run_cargo(vec![
|
||||||
"test",
|
"test",
|
||||||
"--all-targets",
|
"--all-targets",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user