Crossfire: High-performance lockless spsc/mpsc/mpmc channels for Rust
Библиотека crossfire-rs предоставляет безблокировочные (lock-free) реализации очередей MPMC (множественные производители/потребители) и MPSC (множественные производители/один потребитель) для асинхронного программирования на Rust. Проект основан на популярной библиотеке crossbeam, которая специализируется на низкоуровневых примитивах параллелизма.
Основное преимущество crossfire-rs - это высокая производительность благодаря использованию безблокировочных алгоритмов, что позволяет избежать накладных расходов на блокировки. Библиотека особенно полезна для высоконагруженных систем, где производительность и параллелизм являются критически важными факторами. Реализации поддерживают асинхронный контекст, что делает их идеальными для использования в современных асинхронных приложениях на Rust.
Комментарии (15)
- Обсуждение вращается вокруг тонких различий между различными моделями каналов (SPSC, MPMC и т.д.) и их влиянии на безопасность отмены и производительность.
- Участники обмениваются ссылками на документацию и обсуждают, какие именно гарантии предоставляет каждая реализация.
- Появляется вопрос о том, как именно Kanal и другие библиотеки реализуют оптимизации, которые могут влиять на безопасность отмены.
- Участники обсуждают, какие именно факторы производительности (например, latency vs throughput) имеют наибольшее значение для их конкретного варианта использования.
- В конце обсуждение сводится к тому, что выбор канала зависит от специфики рабочей нагрузки и что сравнительные бенчмарки могут не отражать реальную эффективность в продакшене.
Multi-Core by Default
Ryan Fleury в своём блоге Digital Grove рассуждает о том, что современные процессоры уже давно многоядерны, но большинство программистов всё ещё пишут однопоточный код, упуская до 90% вычислительной мощности. Он приводит пример: сумма элементов массива может быть распараллелена на 4 ядра, но в итоге выигрыш в 3.2 раза превращается в проигрыш в 1.3 раза из-за накладных расходов на синхронизацию и кэш-коэффициенты. Автор приходит к выводу, что надо не "добавлять" многопоточность в специфические случаи, а с самого начала писать весь код как будто он многопоточен, и тогда не будет никаких "особых случаев".
Комментарии (54)
- Обсуждение показало, что современные языки и фреймворки всё ещё не решают фундаментальную проблему — как писать код, который по-настоящему использует многоядерные CPU.
- Участники подчеркнули, что большинство программистов не имеют ни инструментов, ни культуры для эффективного использования параллелизма.
- Были упомянуты такие концепции как "неявный параллелизм" и "автоматическое распараллеливание", но никто не смог привести примеры их практического применения.
- Обсуждение также затронуло вопрос о том, что большинство задач пользователя не требуют параллельного выполнения, и что производительность часто ограничена не столько CPU, сколько IO или GPU.
Комментарии (45)
- Дискуссия разворачивается вокруг старых обвинений в адрес языка C и архитектуры x86, но участники быстро указывают, что стековые инструкции и концепция вызова функций существовали задолго до C и даже были запатентованы в 1957 году.
- Спор уходит в сторону от предмета: автор статьи не предлагает никакой альтернативы, кроме как упоминания о "сообщениях" без каких-либо деталей.
- Участники также отмечают, что статья игнорирует такие факторы как тепловой бюджет, параллелизм и стоимость транзисторов.
- В итоге обсуждение сводится к тому, что критика не предлагает никакой конструктивной альтернативы и что современные CPU не оптимизированы под конкретные задачи, но и под общий набор инструкций, что делает их универсальными.
Is life a form of computation?
Жизнь можно рассматривать как форму вычислений, и эта идея восходит к работам Алана Тьюринга и Джона фон Неймана. Они показали, что самовоспроизведение, как и вычисления, может выполняться машинами, следуя закодированным инструкциям — подобно тому, как ДНК управляет биологическими процессами. Это не метафора: ДНК буквально является программой, где определённые последовательности кодируют действия, например, добавление аминокислоты к белку.
Однако биологические вычисления отличаются от традиционных цифровых: они массово параллельны, децентрализованы и стохастичны. Клетки содержат триста квинтиллионов рибосом, каждая из которых действует как крошечный компьютер, работающий в условиях теплового шума и случайности. В отличие от надёжных логических вентилей в компьютерах, биологические процессы обратимы и неточны, но используют случайность как преимущество для адаптации. Современные технологии, такие как ИИ, тоже всё чаще полагаются на параллелизм и случайность, что сближает их с биологическими системами.
Комментарии (131)
- Критика отсутствия чёткого определения понятия «вычисление» и спекулятивного характера аналогий между биологией и информатикой.
- Обсуждение возможности моделирования жизни как вычисления, но не отождествления этих процессов, с оговоркой о необходимости строгих определений.
- Упоминание альтернативных концепций, таких как прогностическая обработка, иерархия Хомского и принцип вычислительной эквивалентности Вольфрама.
- Скептицизм по поводу детерминизма жизни и редукционистского подхода, игнорирующего её сложность, стохастичность и emergent-свойства.
- Замечание о том, что подобные аналогии являются продуктом человеческого абстрактного мышления и не существуют в природе в явном виде.
Wild performance tricks
В Wild-линковщике для Rust применяют несколько продвинутых техник оптимизации параллельной работы. Например, используют split_off_mut для безопасного разделения мутабельных срезов Vec<SymbolId> между потоками, что позволяет обрабатывать символы каждого объекта параллельно без блокировок, сохраняя кэш-локальность.
Для инициализации вектора без задержек на основном потоке задействуют крейт sharded-vec-writer: предварительно аллоцируют память, разбивают её на сегменты по числу символов в объектах и заполняют их параллельно через VecWriter, что ускоряет стартовую фазу.
В случаях, когда требуются случайные записи в общий вектор (например, для обработки дубликатов символов в C++), переходят на атомарные операции. Вместо стабильного, но ограниченного AtomicU32::from_mut_slice (только nightly) или постоянного использования атомиков (что снижает производительность), временно преобразуют &[SymbolId] в &[AtomicSymbolId] через unsafe-конверсию, экономя на издержках синхронизации в основном коде.
Комментарии (67)
- Обсуждаются оптимизации Rust, такие как преобразование
VecвIntoIterи обратно для эффективного повторного использования аллокации, что реализовано в стандартной библиотеке как специальный случай. - Высказываются предостережения против некоторых "трюков производительности", например, перемещения аллокации в другой поток для освобождения, из-за особенностей работы аллокаторов и сомнительной выгоды.
- Поднимается вопрос о надёжности оптимизаций компилятора (LLVM) в релизных сборках, которые могут меняться между версиями и сложны для верификации, что контрастирует с медленными debug-сборками.
- Отмечается, что многие трюки направлены на обход ограничений borrow checker для получения разрешения на выполнение операций, а не на решение аппаратных задач производительности.
- Обсуждается преимущество Rust в безопасном параллелизме (например, с Rayon) по сравнению с C/C++, где обеспечение потоковой безопасности значительно сложнее.
Effect Systems vs. Print Debugging: A Pragmatic Solution
Системы эффектов в языках программирования, такие как в Flix, строго контролируют побочные действия вроде вывода в консоль, что мешает привычной отладке с помощью println. Ложь системе эффектов через unchecked_cast приводит к проблемам: компилятор удаляет «бесполезный» код без видимых эффектов или ломает семантику при оптимизациях.
Flix ищет прагматичный баланс между строгостью и удобством, предлагая временные решения для отладки без нарушения гарантий. Например, вводят функцию dprintln, которая обманывает систему эффектов, но рискует быть удалённой оптимизатором. Ключевой вывод: языки должны позволять гибкость там, где она нужна, без компромисса с безопасностью.
Комментарии (35)
- Обсуждается подход Flix к типизации эффектов, включая системные (например, Debug) и возможность создания пользовательских эффектов.
- Рассматриваются целевые use-case языка: платформенная независимость, совместимость с JVM/Java, применение в бэкенде и академические цели.
- Поднимаются вопросы о практичности системы эффектов: необходимость для оптимизаций, потенциальная избыточность и сложность.
- Обсуждается проблема автоматической параллелизации и оптимизации, включая риски переупорядочивания или удаления операций ввода-вывода.
- Упоминаются аналогичные реализации в других языках (Haskell, Koka, Roc, Effekt) и их эволюция в моделировании эффектов.
Show HN: WeUseElixir - Elixir project directory
Каталог WeUseElixir собирает реальные примеры использования языка Elixir в продакшене, демонстрируя разнообразие его применения — от библиотек до крупных компаний. Здесь можно найти такие известные инструменты, как Oban для обработки фоновых заданий, Absinthe для работы с GraphQL и Flop для пагинации в Ecto.
Среди компаний, применяющих Elixir, — PepsiCo, платформа для стриминга концертов VEEPS и сервис удалённой работы Remote. Каталог помогает разработчикам находить вдохновение, инструменты и потенциальных работодателей, подчёркивая практическую ценность экосистемы Elixir.
Комментарии (50)
- Участники высоко оценивают язык Elixir, его подход к функциональному программированию, параллелизму и сообщество, отмечая его эффективность для проектов любого масштаба.
- Были предложения по улучшению каталога WeUseElixir: добавить фильтрацию по типам проектов, разрешить добавлять компании без регистрации и исправлять данные о стеках технологий.
- Обсуждались технические аспекты: преимущества BEAM (виртуальной машины Erlang) для отказоустойчивости, продуктивность фреймворка Phoenix LiveView и варианты интеграции с клиентским состоянием.
- Участники поделились известными компаниями и проектами, использующими Elixir (например, Plausible Analytics, Supabase, ElectricSQL), и другими подобными каталогами.
- Задан вопрос о выборе между языками экосистемы BEAM: Erlang (для опытных команд), Elixir (общего назначения) и Gleam (строгая типизация).
My Foray into Vlang
V как Go с шоколадкой
Go — это ваниль: просто, быстро, без фанатизма. V же — «ваниль++»: тот же вкус, но сверху посыпка из фич.
Карты
langs := {"elixir": {"score": 100}}
score := langs["elixir"]["score"] or { -1 }
Фиксированные типы, or {} вместо if err != nil, spread-оператор ... для слияния.
Структуры
struct Language {
pub mut:
score int = -1
name string @[required]
}
Методы можно вешать прямо на массивы, поля можно помечать @[required], дефолты и флаги CLI задаются в одном месте.
WithOption
fn new_server(opts ServerOptions) ! { ... }
Встроенный «функциональный» паттерн: new_server(port: 8080, debug: true).
Enum и лямбды
Enum’ы есть, лямбды короткие: nums.filter(it % 2 == 0).
Подводные камни
net.httpпока не дотягивает до Go.veb(веб-фреймворк) сырой.- Сборка сложнее: нужен
vи C-компилятор. - Параллелизм есть, но экосистема молода.
Итог
V — это Go с синтаксическим сахаром и парой острых углов. Для экспериментов — огонь, для продакшена — пока нет.
Комментарии (30)
- Участники спорят, действительно ли V лучше Go: одни отмечают быструю компиляцию и «красивые» фичи, другие — нестабильность компилятора и отсутствие надёжности.
- Поддерживающие Go указывают на его зрелость, стабильность GC, удобство кросс-компиляции и отказ от «лишнего».
- Сторонники V хвалят синтаксис (const по умолчанию, sum types, простой С-интерфейс), но признают, что язык пока «сырой».
- Некоторые считают V «предупреждением» о том, почему Go часто говорит «нет» новым возможностям.
- Есть мнение, что ни Go, ни V не решают задачу «лёгкого C для приложений»; предлагают смотреть на Zig или Free Pascal.