Почему
📈 Векторный рост: Избегаем реаллокаций
Мы часто пишем:
Что происходит под капотом?
1. Вектор создается пустым (0 байт).
2. Первый
3. Пятый
• Создается новый буфер (размером x2).
• Все старые элементы копируются туда.
• Старый буфер освобождается.
• Новый элемент записывается.
Это называется Reallocation. Это дорого. Если у вас 10 миллионов элементов, вы сделаете десятки реаллокаций и скопируете гигабайты данных просто так.
Решение: Если вы хотя бы примерно знаете размер - подскажите компилятору.
Правило:
#rust #performance #vectors
👉 @rust_lib
Vec::new() это ловушка для производительности.📈 Векторный рост: Избегаем реаллокаций
Мы часто пишем:
let mut vec = Vec::new();
for item in heavy_iter {
vec.push(item);
}
Что происходит под капотом?
1. Вектор создается пустым (0 байт).
2. Первый
push: аллокация на 4 элемента (условно).3. Пятый
push: места нет.• Создается новый буфер (размером x2).
• Все старые элементы копируются туда.
• Старый буфер освобождается.
• Новый элемент записывается.
Это называется Reallocation. Это дорого. Если у вас 10 миллионов элементов, вы сделаете десятки реаллокаций и скопируете гигабайты данных просто так.
Решение: Если вы хотя бы примерно знаете размер - подскажите компилятору.
// Идеально, если знаем точно
let mut vec = Vec::with_capacity(exact_count);
// Или используем итераторы, они часто сами знают свой размер
let vec: Vec<_> = heavy_iter.collect();
collect() умный. Он смотрит на size_hint итератора и сразу аллоцирует нужный буфер (если итератор "честный").Правило:
Vec::new() - только если вы правда не знаете, будет ли там хоть один элемент. В остальных случаях - with_capacity.#rust #performance #vectors
👉 @rust_lib
👍31❤6🥰2😢2🤗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
🗝 Турбируем HashMap
Стандартный
Почему? Он криптографически стоек к HashDoS атакам (когда злоумышленник подбирает ключи так, чтобы все они попадали в один бакет, превращая мапу в связный список и убивая CPU).
Но SipHash медленный. Если вы решаете алгоритмические задачи, пишете геймдев или у вас внутренний сервис без внешнего доступа - вам не нужна защита от DoS. Вам нужна скорость.
Используйте сторонние хэшеры. Самые популярные:
1.
2.
Пример с крейтом
Прирост производительности на операциях вставки/поиска может достигать 2x-3x на простых ключах.
Итог:
• Backend наружу? Оставляем дефолтный
• GameDev / Algo / Internal Data Processing? Ставим
#rust #performance #hashmap #external_crates
👉 @rust_lib
Стандартный
std::collections::HashMap в Rust использует алгоритм хэширования SipHash.Почему? Он криптографически стоек к HashDoS атакам (когда злоумышленник подбирает ключи так, чтобы все они попадали в один бакет, превращая мапу в связный список и убивая CPU).
Но SipHash медленный. Если вы решаете алгоритмические задачи, пишете геймдев или у вас внутренний сервис без внешнего доступа - вам не нужна защита от DoS. Вам нужна скорость.
Используйте сторонние хэшеры. Самые популярные:
1.
FxHash (rustc-hash) - используется внутри самого компилятора Rust и Firefox. Молниеносно быстрый для коротких ключей (integers).2.
AHash - современный, быстрый, использует аппаратные инструкции AES.Пример с крейтом
rustc-hash:
use rustc_hash::FxHashMap;
// Это та же HashMap, но с быстрым хэшером
let mut map: FxHashMap<u32, &str> = FxHashMap::default();
Прирост производительности на операциях вставки/поиска может достигать 2x-3x на простых ключах.
Итог:
• Backend наружу? Оставляем дефолтный
SipHash.• GameDev / Algo / Internal Data Processing? Ставим
FxHash или AHash.#rust #performance #hashmap #external_crates
👉 @rust_lib
👍17❤6🥰2✍1🏆1
🔮 Ты не пройдешь: Магия предсказателя ветвлений
Вы когда-нибудь задумывались, почему обработка отсортированного массива чисел происходит в разы быстрее, чем случайного, даже если логика одна и та же?
Всё дело в конвейере (pipeline). Процессор выполняет инструкции не по одной, а потоком: пока одна декодируется, другая уже выполняется. Но тут появляется
Процессор не знает, пойдет код в
• Угадал? Выполнение продолжается без задержек.
• Не угадал? Происходит Pipeline Flush. Процессор выбрасывает все инструкции, которые успел "набрать" по неверному пути, и начинает заново с правильного адреса. Это огромная потеря тактов (10-20 циклов CPU).
Пример на Rust:
На случайных данных BPU ошибается в 50% случаев. На сортированных почти никогда.
Вывод: Чем предсказуемее ваши данные, тем быстрее работает ваш код. Иногда
#rust #cpu #lowlevel #performance #branch_prediction
👉 @rust_lib
Вы когда-нибудь задумывались, почему обработка отсортированного массива чисел происходит в разы быстрее, чем случайного, даже если логика одна и та же?
Всё дело в конвейере (pipeline). Процессор выполняет инструкции не по одной, а потоком: пока одна декодируется, другая уже выполняется. Но тут появляется
if (ветвление).Процессор не знает, пойдет код в
then или в else, пока не вычислит условие. Но ждать он не может - конвейер встанет. Поэтому он угадывает.• Угадал? Выполнение продолжается без задержек.
• Не угадал? Происходит Pipeline Flush. Процессор выбрасывает все инструкции, которые успел "набрать" по неверному пути, и начинает заново с правильного адреса. Это огромная потеря тактов (10-20 циклов CPU).
Пример на Rust:
// Если data отсортирован: T T T T T F F F F F (паттерн ясен)
// Если data случайный: T F T T F F T F (паттерн непредсказуем)
for &x in &data {
if x > 128 {
sum += x;
}
}
На случайных данных BPU ошибается в 50% случаев. На сортированных почти никогда.
Вывод: Чем предсказуемее ваши данные, тем быстрее работает ваш код. Иногда
data.sort() перед обработкой окупается с лихвой.#rust #cpu #lowlevel #performance #branch_prediction
👉 @rust_lib
👍21👎3✍2❤1🥰1
🥶 Холодный расчет:
Компилятор Rust (LLVM) очень умный, но иногда мы знаем о поведении программы больше, чем он. Мы можем подсказать ему, какая ветка кода будет выполняться чаще.
1. Атрибут
Идеально для обработки ошибок. Вы говорите компилятору: "Сюда мы будем заходить крайне редко".
Компилятор сдвинет этот код в "дальний угол" бинарника, чтобы "горячий" путь шел линейно в памяти (это улучшает работу кэша инструкций и BPU).
2.
В стабильном Rust пока нет
Используйте
#rust #optimization #llvm #hints
👉 @rust_lib
#[cold] и likelyКомпилятор Rust (LLVM) очень умный, но иногда мы знаем о поведении программы больше, чем он. Мы можем подсказать ему, какая ветка кода будет выполняться чаще.
1. Атрибут
#[cold]Идеально для обработки ошибок. Вы говорите компилятору: "Сюда мы будем заходить крайне редко".
Компилятор сдвинет этот код в "дальний угол" бинарника, чтобы "горячий" путь шел линейно в памяти (это улучшает работу кэша инструкций и BPU).
#[cold] // <-- Подсказка
fn handle_fatal_error() {
// Логирование, паника, сложная логика...
}
fn process(data: &str) {
if let Err(_) = parse(data) {
handle_fatal_error(); // Компилятор знает, что это маловероятно
return;
}
// Happy path идет дальше линейно
}
2.
likely / unlikely (Nightly / Crates)В стабильном Rust пока нет
std::intrinsics::likely, но есть крейт likely или хаки. Это прямая инструкция процессору через LLVM.
// С крейтом `likely`
if likely(x > 0) {
// Оптимизатор будет строить код так,
// будто это условие почти всегда true
}
Используйте
#[cold] для ошибок и граничных случаев. Это стабильно, бесплатно и делает код чище.#rust #optimization #llvm #hints
👉 @rust_lib
👍16✍2🥰2❤1🔥1🤗1
🚫 Убиваем
Самый быстрый
Иногда можно заменить ветвление на арифметику. Это гарантирует отсутствие Pipeline Flush, так как поток инструкций линейный.
Задача: Вернуть
С ветвлением:
Branchless (без ветвления):
В Rust
Но подождите!
Современные компиляторы часто делают это сами. Они превращают простой
Как проверить?
Смотрите в ассемблер (через
Совет: Пишите читаемый код. И только если профайлер показывает, что BPU захлебывается в горячем цикле - переписывайте на арифметику.
#rust #assembly #branchless #performance
👉 @rust_lib
if: Branchless ProgrammingСамый быстрый
if - это отсутствие if.Иногда можно заменить ветвление на арифметику. Это гарантирует отсутствие Pipeline Flush, так как поток инструкций линейный.
Задача: Вернуть
a, если condition true, и b, если false.С ветвлением:
let result = if condition { a } else { b };
// Генерирует инструкцию перехода (JMP/JNE) -> Риск misprediction
Branchless (без ветвления):
В Rust
bool можно скастить в u8 (true = 1, false = 0).
// (a * 1) + (b * 0) = a
// (a * 0) + (b * 1) = b
let result = a * (condition as i32) + b * (!condition as i32);
Но подождите!
Современные компиляторы часто делают это сами. Они превращают простой
if в инструкцию CMOV (Conditional Move). Это инструкция процессора: "Скопируй данные, если флаг выставлен". Это не ветвление, это просто копирование по условию.Как проверить?
Смотрите в ассемблер (через
godbolt или cargo-show-asm). Если видите cmov - поздравляю, у вас branchless код, и он будет работать быстро, даже если данные случайны. Если видите jle / jne - это прыжок.Совет: Пишите читаемый код. И только если профайлер показывает, что BPU захлебывается в горячем цикле - переписывайте на арифметику.
#rust #assembly #branchless #performance
👉 @rust_lib
👍14❤3🔥2✍1🥰1🤗1
🏎️ SIMD для ленивых: Автовекторизация в Rust
SIMD - это когда процессор одной инструкцией складывает не два числа, а сразу 4, 8 или 16.
Многие думают, что SIMD это сложно и требует
Допустим, у вас есть цикл:
Если вы скомпилируете это в релизе для x86_64, компилятор сгенерирует инструкции SSE2 (обрабатывая по 4 числа
Как сделать еще быстрее?
Если вы знаете, что ваш код будет работать на современном железе, разрешите компилятору использовать AVX2 (по 8 чисел
Но есть нюанс: Компилятор очень осторожен. Он не применит SIMD, если:
1. Есть риск паники. Если срезы разной длины, компилятор вставит проверки границ (
• Лечение: Используйте итераторы (
2. Есть риск алиасинга. Если
• Лечение: Rust тут молодец, его правила заимствования гарантируют отсутствие мутабельного алиасинга.
Всегда смотрите в ассемблер (
#rust #simd #performance #llvm #autovectorization
👉 @rust_lib
SIMD - это когда процессор одной инструкцией складывает не два числа, а сразу 4, 8 или 16.
Многие думают, что SIMD это сложно и требует
unsafe. Но лучший SIMD тот, который LLVM написал за вас.Допустим, у вас есть цикл:
pub fn add_arrays(a: &[f32], b: &[f32], out: &mut [f32]) {
// Простые смертные пишут так:
for i in 0..a.len() {
out[i] = a[i] + b[i];
}
}
Если вы скомпилируете это в релизе для x86_64, компилятор сгенерирует инструкции SSE2 (обрабатывая по 4 числа
f32 за раз). Почему? Потому что SSE2 гарантированно есть на всех 64-битных процессорах Intel/AMD.Как сделать еще быстрее?
Если вы знаете, что ваш код будет работать на современном железе, разрешите компилятору использовать AVX2 (по 8 чисел
f32).
RUSTFLAGS="-C target-cpu=native" cargo build --release
Но есть нюанс: Компилятор очень осторожен. Он не применит SIMD, если:
1. Есть риск паники. Если срезы разной длины, компилятор вставит проверки границ (
bounds check) внутри цикла. Это убивает векторизацию.• Лечение: Используйте итераторы (
zip) или явно проверяйте длины до цикла и используйте assert!, чтобы дать хинт оптимизатору.2. Есть риск алиасинга. Если
out пересекается в памяти с a или b.• Лечение: Rust тут молодец, его правила заимствования гарантируют отсутствие мутабельного алиасинга.
Всегда смотрите в ассемблер (
cargo-show-asm), чтобы убедиться, что цикл развернулся в SIMD-инструкции (ищите что-то вроде vaddps вместо addss).#rust #simd #performance #llvm #autovectorization
👉 @rust_lib
👍13❤8🥰1🤗1
💀 Хардкорный режим: std::arch и интринсики
Автовекторизация не сработала? Алгоритм слишком сложен для LLVM? Придется марать руки.
Встречайте
Это очень unsafe.
Это не портабельно (код для x86 не заработает на ARM M1).
Как выглядит сложение массивов на AVX2 (x86_64):
Главная опасность: Если вы вызовете эту функцию на старом процессоре (без AVX2), программа упадет с ошибкой "Illegal Instruction".
Решение: Runtime detection. Вы должны проверять фичи процессора в рантайме.
Это сложно, больно, но дает максимальный контроль над железом.
#rust #simd #unsafe #lowlevel #intrinsics
👉 @rust_lib
Автовекторизация не сработала? Алгоритм слишком сложен для LLVM? Придется марать руки.
Встречайте
std::arch. Это модуль, дающий доступ к конкретным инструкциям процессора (интринсикам).Это очень unsafe.
Это не портабельно (код для x86 не заработает на ARM M1).
Как выглядит сложение массивов на AVX2 (x86_64):
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
// Атрибут важен! Он говорит компилятору, что внутри этой функции
// можно использовать 256-битные регистры.
#[target_feature(enable = "avx2")]
unsafe fn add_avx2(a: &[f32], b: &[f32], out: &mut [f32]) {
// Мы обязаны обрабатывать данные чанками по 8 штук.
// (Опустим проверки длин и обработку "хвостов" для краткости)
for i in (0..a.len()).step_by(8) {
// Загружаем 8 float'ов в 256-битный регистр
let vec_a = _mm256_loadu_ps(a.as_ptr().add(i));
let vec_b = _mm256_loadu_ps(b.as_ptr().add(i));
// ОДНА инструкция сложения для 8 пар чисел
let vec_res = _mm256_add_ps(vec_a, vec_b);
// Выгружаем обратно в память
_mm256_storeu_ps(out.as_mut_ptr().add(i), vec_res);
}
}
Главная опасность: Если вы вызовете эту функцию на старом процессоре (без AVX2), программа упадет с ошибкой "Illegal Instruction".
Решение: Runtime detection. Вы должны проверять фичи процессора в рантайме.
fn add_smart(a: &[f32], b: &[f32], out: &mut [f32]) {
if is_x86_feature_detected!("avx2") {
// Безопасно, мы проверили
unsafe { add_avx2(a, b, out) };
} else {
// Медленный фоллбэк для старого железа
add_scalar(a, b, out);
}
}
Это сложно, больно, но дает максимальный контроль над железом.
#rust #simd #unsafe #lowlevel #intrinsics
👉 @rust_lib
👍9🔥3🙈2❤1🥰1🤗1
🚀 Portable SIMD: Пишем один раз, работает везде
В прошлом посте вы видели ужас ручных интринсиков. Представьте, что вам нужно поддерживать SSE2, AVX2, AVX-512, да еще и ARM NEON для макбуков. Это ад из
Rust сообщество решает эту проблему. Встречайте Portable SIMD (сейчас это крейт
Идея: мы используем абстрактные типы "широких" чисел, а компилятор сам мапит их на лучшие инструкции целевой платформы.
Выглядит это потрясающе чисто:
Никакого
Если вы компилируете это под AVX2 - будет AVX2. Под ARM NEON - будет NEON.
Это будущее высокопроизводительного Rust. Ждем стабилизации.
#rust #simd #nightly #future
👉 @rust_lib
В прошлом посте вы видели ужас ручных интринсиков. Представьте, что вам нужно поддерживать SSE2, AVX2, AVX-512, да еще и ARM NEON для макбуков. Это ад из
cfg_if и дублирования кода.Rust сообщество решает эту проблему. Встречайте Portable SIMD (сейчас это крейт
portable-simd или фича #![feature(portable_simd)] в nightly).Идея: мы используем абстрактные типы "широких" чисел, а компилятор сам мапит их на лучшие инструкции целевой платформы.
Выглядит это потрясающе чисто:
#![feature(portable_simd)] // Нужен nightly Rust
use std::simd::{f32x8, Simd};
fn add_portable(a: &[f32], b: &[f32], out: &mut [f32]) {
// Берем чанки по 8 элементов
let chunks_a = a.chunks_exact(8);
let chunks_b = b.chunks_exact(8);
let chunks_out = out.chunks_exact_mut(8);
for ((slice_a, slice_b), slice_out) in chunks_a.zip(chunks_b).zip(chunks_out) {
// Превращаем слайсы в SIMD-вектора (почти бесплатно)
let vec_a = f32x8::from_slice(slice_a);
let vec_b = f32x8::from_slice(slice_b);
// Обычный оператор "+" работает как SIMD сложение!
let vec_res = vec_a + vec_b;
// Записываем обратно
vec_res.copy_to_slice(slice_out);
}
// + нужно обработать "хвост", если длина не кратна 8
}
Никакого
unsafe! Никаких _mm256_ugly_names!Если вы компилируете это под AVX2 - будет AVX2. Под ARM NEON - будет NEON.
Это будущее высокопроизводительного Rust. Ждем стабилизации.
#rust #simd #nightly #future
👉 @rust_lib
🔥22❤2👍1🥰1🤗1
🪄 Разрушаем магию: Твоя Future - это просто
Многие приходят в Rust из Go или Erlang и думают, что
Когда вы пишете
Смотрим код:
Под капотом LLVM генерирует невидимый
Когда рантайм вызывает метод
1. Выполняется кусок кода до первого
2. Состояние переключается (в
3. Управление возвращается обратно в рантайм! (Никакого блокирования потока).
Почему это круто? Такой
#rust #async #under_the_hood #future
👉 @rust_lib
enumМногие приходят в Rust из Go или Erlang и думают, что
async запускает легковесный поток (горутину). Забудьте. Асинхронный Rust работает совершенно иначе - он не аллоцирует стек под каждую задачу.Когда вы пишете
async fn, компилятор превращает вашу функцию в конечный автомат (State Machine).Смотрим код:
async fn fetch_data() {
let req = build_request();
let resp = send(req).await; // <-- Точка остановки 1
process(resp).await; // <-- Точка остановки 2
}
Под капотом LLVM генерирует невидимый
enum, который хранит локальные переменные между вызовами .await:
// Примерно так это видит компилятор:
enum FetchDataStateMachine {
Start,
WaitSend { req: Request }, // Храним локальные переменные
WaitProcess { resp: Response },
Done,
}
Когда рантайм вызывает метод
poll() у этой Future:1. Выполняется кусок кода до первого
.await.2. Состояние переключается (в
WaitSend).3. Управление возвращается обратно в рантайм! (Никакого блокирования потока).
Почему это круто? Такой
enum весит считанные байты. Вы можете создать миллион таких Future на обычном ноутбуке, и они займут всего пару десятков мегабайт оперативки. Никакая ОС не позволит вам создать миллион настоящих потоков.#rust #async #under_the_hood #future
👉 @rust_lib
👍17✍7❤3🥰1🤗1
⏰ Хватит дергать:
Окей, Future вернула управление (сказала
Здесь на сцену выходят Executor, Reactor и Waker.
• Executor - это менеджер задач. Он берет Future и вызывает у нее
• Reactor - это слушатель ОС (обертка над
• Waker - это тот самый пейджер, который выдают в бургерной.
Как это работает:
1. Future делает сетевой запрос и понимает, что данных еще нет.
2. Она регистрирует этот запрос в Reactor и отдает ему свой Waker (колбэк, в котором зашит ID этой Future).
3. Future возвращает
4. ...проходит время... Сетевая карта получает пакеты. ОС дергает
5. Reactor видит: "Ага, пришли данные для сокета X". Он берет Waker, привязанный к этому сокету, и вызывает
6. Waker сигнализирует Executor'у: "Задача #42 готова, помести её обратно в очередь на выполнение".
7. Executor снова вызывает
Никакого холостого хода CPU. Только чистая событийная архитектура.
#rust #async #waker #tokio #epoll
👉 @rust_lib
Waker и паттерн пейджераОкей, Future вернула управление (сказала
Poll::Pending). Но как рантайм узнает, что данные по сети пришли и пора снова вызвать poll()? Если он будет постоянно опрашивать все Future в цикле (while loop), ваш CPU улетит в космос на 100% загрузке.Здесь на сцену выходят Executor, Reactor и Waker.
• Executor - это менеджер задач. Он берет Future и вызывает у нее
poll().• Reactor - это слушатель ОС (обертка над
epoll в Linux, kqueue в macOS или IOCP в Windows). Он ждет событий от сетевой карты или диска.• Waker - это тот самый пейджер, который выдают в бургерной.
Как это работает:
1. Future делает сетевой запрос и понимает, что данных еще нет.
2. Она регистрирует этот запрос в Reactor и отдает ему свой Waker (колбэк, в котором зашит ID этой Future).
3. Future возвращает
Pending. Executor забывает про неё и идет выполнять другие задачи.4. ...проходит время... Сетевая карта получает пакеты. ОС дергает
epoll.5. Reactor видит: "Ага, пришли данные для сокета X". Он берет Waker, привязанный к этому сокету, и вызывает
waker.wake().6. Waker сигнализирует Executor'у: "Задача #42 готова, помести её обратно в очередь на выполнение".
7. Executor снова вызывает
poll(), и стейт-машина делает следующий шаг.Никакого холостого хода CPU. Только чистая событийная архитектура.
#rust #async #waker #tokio #epoll
👉 @rust_lib
👍9🔥4❤2🥰2👨💻1🤗1
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Работа с Linux: Ubuntu, CentOS, Debian. Сетевое …
💩25👎11🤡5👍2🤣2🤬1🙈1
🥷 Кража во спасение: Work Stealing в Tokio
Если вы используете
Как честно распределить 100,000 задач между 8 потоками, чтобы никто не простаивал и не было узкого горлышка (bottleneck)?
Если сделать одну Глобальную очередь (Global Queue), куда смотрят все потоки, они передерутся за Мьютекс (Mutex contention). Производительность рухнет.
Поэтому Tokio использует Локальные очереди (Local Queues):
1. У каждого потока-воркера есть своя личная очередь задач (до 256 штук).
2. Воркер берет задачи только из своей очереди. Никаких блокировок! Это невероятно быстро.
3. Новые задачи, порожденные текущей (
А что если один поток закончил все задачи, а у другого их еще 200?
Включается Work Stealing (Кража работы):
1. Скучающий воркер смотрит в локальные очереди других потоков.
2. Он находит самую загруженную очередь и втихаря "крадет" ровно половину её задач.
3. Забирает их себе в локальную очередь и начинает молотить.
Это гениальный компромисс: 99% времени потоки работают без блокировок, и лишь изредка (при перекосе баланса) происходит синхронизация для кражи. Именно поэтому Tokio выдерживает миллионы RPS на мощных серверах.
#rust #tokio #architecture #multithreading #work_stealing
👉 @rust_lib
Если вы используете
tokio::main, вы запускаете многопоточный рантайм (Multi-Threaded Scheduler). Под капотом создается пул потоков (воркеров), обычно по числу ядер процессора.Как честно распределить 100,000 задач между 8 потоками, чтобы никто не простаивал и не было узкого горлышка (bottleneck)?
Если сделать одну Глобальную очередь (Global Queue), куда смотрят все потоки, они передерутся за Мьютекс (Mutex contention). Производительность рухнет.
Поэтому Tokio использует Локальные очереди (Local Queues):
1. У каждого потока-воркера есть своя личная очередь задач (до 256 штук).
2. Воркер берет задачи только из своей очереди. Никаких блокировок! Это невероятно быстро.
3. Новые задачи, порожденные текущей (
tokio::spawn), падают в локальную очередь этого же потока.А что если один поток закончил все задачи, а у другого их еще 200?
Включается Work Stealing (Кража работы):
1. Скучающий воркер смотрит в локальные очереди других потоков.
2. Он находит самую загруженную очередь и втихаря "крадет" ровно половину её задач.
3. Забирает их себе в локальную очередь и начинает молотить.
Это гениальный компромисс: 99% времени потоки работают без блокировок, и лишь изредка (при перекосе баланса) происходит синхронизация для кражи. Именно поэтому Tokio выдерживает миллионы RPS на мощных серверах.
#rust #tokio #architecture #multithreading #work_stealing
👉 @rust_lib
🔥17❤1👍1🥰1🤗1
Wgpu - это безопасная и переносимая графическая библиотека для Rust, основанная на API WebGPU. Она подходит для универсальной графики и вычислений на GPU.
Приложения, использующие wgpu, могут работать нативно на Vulkan, Metal, DirectX 12 и OpenGL ES, а также в браузерах через WebAssembly на WebGPU и WebGL2.
https://wgpu.rs/
https://github.com/gfx-rs/wgpu
👉 @rust_lib
Приложения, использующие wgpu, могут работать нативно на Vulkan, Metal, DirectX 12 и OpenGL ES, а также в браузерах через WebAssembly на WebGPU и WebGL2.
https://wgpu.rs/
https://github.com/gfx-rs/wgpu
👉 @rust_lib
🔥9❤2🥰1🤗1
💻Angular — один из самых строгих и системных инструментов разработки пользовательских интерфейсов. Его выбирают крупные компании, где важны масштабируемость, предсказуемость кода и возможность развивать продукт долгие годы. Мы расскажем вам как работать с этим инструментом. Записывайтесь на открытые уроки в преддверии старта курса «Angular-разработчик»:
📆26 марта в 20:00 МСК на открытом уроке разберём, как LLM ускоряют фронтенд-разработку. Покажем их развитие, подготовим Angular-проект к работе с ИИ, создадим приложение и обсудим, где ИИ реально помогает разработчику.
📆9 апреля в 20:00 МСК на открытом уроке разберём сигналы в Angular: создадим реактивную форму с валидацией, обсудим управление состоянием и сравним с подходом на RxJS.
📆21 апреля в 20:00 МСК разберём архитектуру Angular-приложения: слои, feature-подход, разделение UI, логики и API, а также паттерны и структуру реального проекта.
Подробности об уроках и регистрация: https://vk.cc/cVBvJD
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
📆26 марта в 20:00 МСК на открытом уроке разберём, как LLM ускоряют фронтенд-разработку. Покажем их развитие, подготовим Angular-проект к работе с ИИ, создадим приложение и обсудим, где ИИ реально помогает разработчику.
📆9 апреля в 20:00 МСК на открытом уроке разберём сигналы в Angular: создадим реактивную форму с валидацией, обсудим управление состоянием и сравним с подходом на RxJS.
📆21 апреля в 20:00 МСК разберём архитектуру Angular-приложения: слои, feature-подход, разделение UI, логики и API, а также паттерны и структуру реального проекта.
Подробности об уроках и регистрация: https://vk.cc/cVBvJD
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
🤮9❤2🤔1🎉1🐳1🌭1
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Работа с Linux: Ubuntu, CentOS, Debian. Сетевое …
💩21🤮10🤡4🍌2😁1🌚1