🐮 Cow: Ленивое клонирование
Все знают: лишний
Допустим, мы чистим инпут от спецсимволов.
1. Если спецсимволов нет - зачем аллоцировать новую строку? Можно вернуть ссылку на исходную.
2. Если есть - придется создать новую
Здесь на сцену выходит
Это мощнейший инструмент для хот-пасов (hot paths), где 90% данных не требуют изменений. Не ленитесь использовать
#rust #performance #std
👉 @rust_lib
Все знают: лишний
clone() - это грех. Но иногда нам нужно вернуть строку, которая может быть изменена, а может и нет.Допустим, мы чистим инпут от спецсимволов.
1. Если спецсимволов нет - зачем аллоцировать новую строку? Можно вернуть ссылку на исходную.
2. Если есть - придется создать новую
String.Здесь на сцену выходит
std::borrow::Cow (Clone on Write).
use std::borrow::Cow;
fn sanitize(input: &str) -> Cow<str> {
if input.contains('!') {
// Аллокация происходит только тут
Cow::Owned(input.replace('!', "?"))
} else {
// Тут мы просто возвращаем ссылку. Zero allocation.
Cow::Borrowed(input)
}
}
Это мощнейший инструмент для хот-пасов (hot paths), где 90% данных не требуют изменений. Не ленитесь использовать
Cow там, где можно избежать лишних аллокаций.#rust #performance #std
👉 @rust_lib
👍31❤5🥰1😁1🤗1
🤠 Трюк Индианы Джонса:
Типичная ситуация: у вас есть
Компилятор бьет по рукам: нельзя просто так переместить (move) значение из-за мутабельной ссылки. Новички часто делают
Решение:
Оно забирает значение из ссылки, оставляя на его месте
Это работает для всего, что реализует
Это zero-cost, семантически верно и намного быстрее клонирования.
#rust #std #optimization #tips
👉 @rust_lib
std::mem::takeТипичная ситуация: у вас есть
&mut self, и вы хотите забрать поле (например, String или Vec), что-то с ним сделать, и, возможно, вернуть обратно или сохранить измененную версию.Компилятор бьет по рукам: нельзя просто так переместить (move) значение из-за мутабельной ссылки. Новички часто делают
.clone(), чтобы успокоить borrow checker. Но это лишняя аллокация!Решение:
std::mem::take.Оно забирает значение из ссылки, оставляя на его месте
Default::default().
struct Buffer {
data: Vec<u8>,
}
impl Buffer {
fn process(&mut self) {
// Мы "выкрадываем" вектор.
// В self.data теперь пустой Vec (без аллокаций).
let raw_data = std::mem::take(&mut self.data);
// Тяжелая обработка в другом потоке/функции,
// требующая владения (ownership)
let processed = heavy_transform(raw_data);
// Возвращаем результат
self.data = processed;
}
}
Это работает для всего, что реализует
Default (Option, String, Vec). Для типов без Default есть std::mem::replace.Это zero-cost, семантически верно и намного быстрее клонирования.
#rust #std #optimization #tips
👉 @rust_lib
🔥25👍8❤6🥰1😁1🤗1
⚡️ Забудь про RefCell для примитивов
Вам нужно изменить поле внутри неизменяемой структуры (
Рука тянется к
1. Хранит счетчик заимствований (borrow count).
2. В рантайме проверяет правила (может паниковать!).
Если ваш тип реализует
В чем магия
У него нет никакого рантайм-оверхеда. Вообще. Он не проверяет заимствования.
Он работает так: "Я даю тебе копию значения" (
Это атомарно? Нет. Это работает только в одном потоке. Но для однопоточного кода (или внутри
#rust #std #optimization #interior_mutability
👉 @rust_lib
Вам нужно изменить поле внутри неизменяемой структуры (
&self).Рука тянется к
RefCell? Стоп.RefCell имеет оверхед:1. Хранит счетчик заимствований (borrow count).
2. В рантайме проверяет правила (может паниковать!).
Если ваш тип реализует
Copy (числа, bool, маленькие структуры) - используйте Cell.В чем магия
Cell?У него нет никакого рантайм-оверхеда. Вообще. Он не проверяет заимствования.
Он работает так: "Я даю тебе копию значения" (
get) или "Я заменяю значение целиком" (set). Вы не можете получить ссылку (&) на содержимое Cell, поэтому правила Rust не нарушаются.
use std::cell::Cell;
struct Metric {
count: Cell<u64>, // Zero overhead
}
impl Metric {
fn inc(&self) {
// Мы меняем значение по неизменяемой ссылке &self
let current = self.count.get();
self.count.set(current + 1);
}
}
Это атомарно? Нет. Это работает только в одном потоке. Но для однопоточного кода (или внутри
thread_local) это самая быстрая мутабельность, которая только возможна.#rust #std #optimization #interior_mutability
👉 @rust_lib
👍13✍6❤1🥰1🤗1