Hacker News Digest

Тег: #multithreading

Постов: 20

Automatically Translating C to Rust (cacm.acm.org)

Автоматические инструменты перевода кода с C на Rust полезны, но создают небезопасный и неидиоматичный код. Авторы Jaemin Hong и Sukyoung Ryu исследуют эти проблемы и предлагают решения с использованием статического анализа. Основные трудности включают различия в управлении памятью, типах данных и моделировании ресурсов между двумя языками.

Исследователи подчеркивают, что статический анализ может помочь идентифицировать небезопасные паттерны и предложить более идиоматичные альтернативы на Rust. Они отмечают, что хотя автоматический перевод экономит время, ручная доработка все еще необходима для обеспечения безопасности и производительности. Авторы также выделяют оставшиеся проблемы, такие как обработка указателей, многопоточности и низкоуровневых операций, которые требуют особого внимания при переводе.

by FromTheArchives • 24 октября 2025 г. в 15:12 • 93 points

ОригиналHN

#c#rust#static-analysis#memory-management#pointers#multithreading

Комментарии (62)

  • Обсуждение вращается вокруг проблемы автоматического перевода C в Rust и обратно, включая проблемы с безопасностью, размером массивов и управлением памятью.
  • Участники отмечают, что автоматический перевод может привести к небезопасному коду, особенно если не удается точно определить размеры массивов.
  • Также обсуждается, что если Rust потеряет популярность, то может появиться необходимость в обратном переводе, что вызывает сомнения в целесообразности таких усилий.
  • Некоторые участники подчеркивают, что вместо полного переписывания, возможно, лучше сосредоточиться на создании инструментов, которые могли бы помочь в безопасной работе с памятью в C.
  • В конце концов, обсуждение подводит к мысли, что вместо попыток автоматического перевода, лучше было бы сосредоточиться на создании инструментов, которые могли бы помочь в безопасной работе с памятью в C.

The death of thread per core (buttondown.com)

В асинхронных рантаймах, таких как async Rust, задачи могут приостанавливаться и порождать новую работу, что приводит к двум основным подходам: thread-per-core и work-stealing. При work-stealing потоки могут "воровать" задачи друг у друга, обеспечивая лучшую балансировку нагрузки, хотя это требует возможности перемещения задач между потоками (что вызывает сложности в Rust с требованием Send) и может нарушать локальность данных. В обработке данных долгое время доминировал подход thread-per-core, так как он минимизирует перемещение данных между ядрами и упрощает реализацию, особенно при случайных ключах.

Однако в последние годы наблюдается сдвиг в сторону динамического перераспределения работы на уровне обработки данных. Растущее количество ядер делает неравномерное распределение данных более болезненным, а улучшение производительности ввода-вывода снижает значимость старых ограничений. Подход Morsel-Driven Parallelism предлагает, что системы обработки данных могут быть лучшим местом для динамического перераспределения работы. Это подкрепляется культурными факторами: при масштабировании и мультиарендности проблемы неравномерной нагрузки становятся сложнее для решения на верхних уровнях, требуя встроенной гибкости в самих системах.

by ibobev • 20 октября 2025 г. в 21:19 • 126 points

ОригиналHN

#rust#async-programming#multithreading#parallel-processing#work-stealing#thread-per-core#morsel-driven-parallelism#data-processing#performance-optimization

Комментарии (50)

  • Обсуждение вращается вокруг вопроса, что межъядерная коммуникация может быть настолько дорогой, что даже при наличии 255 ядер лучше всего использовать только одно ядро.
  • Участники обсуждают, что важно не только количество ядер, но и то, как они используются, и что важнее всего - это архитектура приложения и то, насколько оно может быть распараллелено.
  • Также обсуждается, что важно учитывать, что не все задачи одинаково подходят для параллельной обработки, и что важно правильно оценивать, когда стоит распараллеливать задачу, а когда нет.
  • Участники также обсуждают, что важно иметь в виду, что современные языки программирования и среды разработки предоставляют инструменты, которые могут помочь в управлении потоками и задачами, и что важно использовать их правильно.

The future of Python web services looks GIL-free (blog.baro.dev)

Python 3.14 представляет значительный прорыв для многопоточного Python, так как его "free-threaded" вариант достиг фазы II и больше не считается экспериментальным. Производительность улучшилась с 35% штрафом до всего 5-10%, а реализация теперь использует адаптивный интерпретатор без обходных решений из Python 3.13. Автор, разработчик веб-фреймворка и веб-сервера, провел сравнительное тестирование для веб-приложений, так как большинство существующих сервисов являются I/O-bound, а многопоточность критически важна.

Для тестирования были созданы ASGI-приложение на FastAPI и WSGI-приложение на Flask, каждый с двумя конечными точками: генератором JSON и имитацией I/O-операции с задержкой 10мс. Использовался сервер Granian, который работает с потоками вместо процессов, и инструмент rewrk для нагрузки. Цель - определить, можно ли наконец отказаться от гигабайтов памяти, тратимых на multiprocessing для параллельной обработки запросов в веб-сервисах.

by gi0baro-dev • 19 октября 2025 г. в 10:38 • 192 points

ОригиналHN

#python#asgi#wsgi#fastapi#flask#multithreading#web-services#performance-optimization

Комментарии (78)

  • Появление free-threading в 3.13-3.14 сделало C-расширения, не обновлённые под free-threading, небезопасными и требует их обновления.
  • Сообщество обсуждает, что отсутствие GIL в 3.14 может привести к тому, что старые библиотеки будут вести себя непредсказуемо, и предлагает, чтобы CPython поставлял инструмент для сканирования и обновления кода.
  • Участники обсуждают, что влияние free-threading на производительность варьируется от «ничего не изменилось» до «значительно лучше» в зависимости от IO vs CPU bound кода, и что влияние на реальные приложения будет варьироваться от «ничего» до «значительно лучше».

Deterministic multithreading is hard (2024) (factorio.com)

Разработчики Factorio поделились деталями исправлений и улучшений для версии 2.0. Одна из самых сложных проблем - баг десинхронизации, связанный с многопоточностью и моддинг API. Оказалось, что ошибка проявлялась только при выполнении четырёх условий одновременно: мод должен изменять тайлы при генерации чанка, запрашивать несколько чанков, принудительно генерировать их немедленно, а игра должна запускаться на компьютерах с разным количеством ядер CPU. Эта проблема существовала с июля 2017 года и была исправлена.

Также улучшена система автопаузы в мультиплеере - сервер теперь будет оставаться на паузе до полной загрузки подключающегося игрока, добавлена опция автопаузы при подключении новых игроков. Оптимизирована работа строительных дронов - проблема с сообщениями "600 заданий не хватает материалов/дронов" возникла из-за того, что игра проверяет только несколько задач за тик, чтобы избежать зависаний при большом количестве робопортов.

by adtac • 19 октября 2025 г. в 09:20 • 95 points

ОригиналHN

#multithreading#factorio#gaming#debugging#game-development

Комментарии (9)

  • Пользователи обсуждают, какие блоги и статьи они считают самыми ценными для разработчиков и почему.
  • Особенно отмечается Factorio Friday Facts и статьи Эмери Бергера, которые, несмотря на свою техническую глубину, остаются бесплатными и доступными.
  • Участники также затрагивают тему того, что сложность использования инструментов вроде Coz или Dthreads может быть препятствием для их широкого внедрения, даже если они и решают важные проблемы.
  • Сообщество отмечает, что такие публикации учат мыслить и показывают примеры хорошего вкуса в инженерии, даже если они не всегда приводят к немедленному применению.

How to stop Linux threads cleanly (mazzo.li)

Остановка потоков Linux требует аккуратного подхода, особенно при работе с низкоуровневыми потоками, созданными через pthread_create или std::thread. В отличие от запуска, корректное завершение потоков позволяет выполнить очистку ресурсов — освобождение памяти, блокировок, сброс логов. Идеального универсального решения не существует, но есть несколько подходов.

Простой метод — организация квази-активного ожидания в каждом потоке с проверкой флага остановки. Когда нужно завершить поток, флаг устанавливается в true, после чего вызывается pthread_join. Цикл не должен быть полностью неблокирующим, но должен завершаться за разумное время. Для потоков, блокирующихся на системных вызовах, используются сигналы для прерывания выполнения. Важно, что даже с этим подходом нужно учитывать обработку сигналов для корректной работы с буферизированным выводом.

by signa11 • 15 октября 2025 г. в 07:28 • 223 points

ОригиналHN

#linux#pthreads#threads#multithreading#posix#signals#io-uring#poll#select#epoll

Комментарии (77)

  • Проблема заключается в том, что POSIX не предоставляет безопасного механизма для остановки потока, и это приводит к тому, что разработчики вынуждены полагаться на pthread_cancel, который небезопасен и может привести к утечкам ресурсов или повреждению состояния.
  • Попытки использовать SIGUSR1 и signalfd для обработки сигналов в пространстве пользователя не решают проблему, потому что большинство библиотек не ожидают, что их вызовы будут прерваны, и это может привести к повреждению состояния.
  • Вместо этого, вместо попыток остановить поток, который может быть в любой точке, лучше структурировать код так, чтобы он мог реагировать на сигнал остановки, или использовать модель, где потоки не блокируются на системных вызовах, а вместо этого используют асинхронные вызовы и ожидают на poll/select/epoll/io_uring.
  • Некоторые комментаторы отмечают, что в Linux существует io_uring, который позволяет прервать системный вызов, и что это может быть использовано для реализации остановки потока, но это не решает проблему, что не все вызовы могут быть прерваны таким образом.
  • В конечном счёте, вместо попыток убить поток, который может быть в любой точке, лучше писать код так, чтобы он был отзывчив к сигналу остановки, и использовать модели, где потоки не блокируются на системных вызовах, а вместо этого используют асинхронные вызовы и ожидают на poll/select/epoll/io_uring.

Multi-Core by Default (rfleury.com)

Ryan Fleury в своём блоге Digital Grove рассуждает о том, что современные процессоры уже давно многоядерны, но большинство программистов всё ещё пишут однопоточный код, упуская до 90% вычислительной мощности. Он приводит пример: сумма элементов массива может быть распараллелена на 4 ядра, но в итоге выигрыш в 3.2 раза превращается в проигрыш в 1.3 раза из-за накладных расходов на синхронизацию и кэш-коэффициенты. Автор приходит к выводу, что надо не "добавлять" многопоточность в специфические случаи, а с самого начала писать весь код как будто он многопоточен, и тогда не будет никаких "особых случаев".

by kruuuder • 10 октября 2025 г. в 07:11 • 97 points

ОригиналHN

#multithreading#parallelism#cpu#compute#performance

Комментарии (54)

  • Обсуждение показало, что современные языки и фреймворки всё ещё не решают фундаментальную проблему — как писать код, который по-настоящему использует многоядерные CPU.
  • Участники подчеркнули, что большинство программистов не имеют ни инструментов, ни культуры для эффективного использования параллелизма.
  • Были упомянуты такие концепции как "неявный параллелизм" и "автоматическое распараллеливание", но никто не смог привести примеры их практического применения.
  • Обсуждение также затронуло вопрос о том, что большинство задач пользователя не требуют параллельного выполнения, и что производительность часто ограничена не столько CPU, сколько IO или GPU.

A comparison of Ada and Rust, using solutions to the Advent of Code (github.com) 🔥 Горячее 💬 Длинная дискуссия

В репозитории представлено детальное сравнение решений Advent of Code 2023, где анализируются подходы к решению задач, эффективность кода и производительность. Основное внимание уделено различиям в алгоритмах и структурах данных, используемых участниками, а также их влиянию на время выполнения и потребление памяти.

Приводятся конкретные примеры кода на разных языках программирования, демонстрирующие оптимизации и trade-offs. Упоминаются ключевые инсайты, такие как важность выбора правильных структур данных для сокращения сложности алгоритмов. Это полезно для разработчиков, стремящихся улучшить свои навыки решения алгоритмических задач.

by andsoitis • 04 октября 2025 г. в 15:10 • 281 points

ОригиналHN

#ada#rust#advent-of-code#algorithms#data-structures#safety-critical#utf-8#multithreading#compiler#memory-safety

Комментарии (196)

  • Участники отмечают сильные стороны Ada, такие как ограниченные числовые типы для предотвращения ошибок, выразительная система типов и удобочитаемость, но сожалеют о его недостаточном распространении вне сообщества safety-critical разработки.
  • Rust ценится за безопасность памяти, фокус на надежности и растущую экосистему, но критикуется за отсутствие формальной спецификации (хотя она сейчас разрабатывается) и сложность с компилятором и асинхронностью.
  • Поднимаются вопросы о различиях в подходах к строкам (Ada использует массивы символов, Rust — UTF-8), многопоточности (встроенные потоки vs. async) и индексации массивов (произвольные типы в Ada vs. словари в Rust).
  • Обсуждаются практические аспекты: скорость компиляции, поддержка Unicode, необходимость спецификаций и влияние экосистемы (инструменты, библиотеки) на выбор языка.
  • Упоминаются нишевые применения Ada (например, в 3D-печати) и потенциальные заимствования его функций (ограниченные типы) в другие языки, такие как Rust, C++ и Nim.

Why is Windows still tinkering with critical sections? – The Old New Thing (devblogs.microsoft.com)

Windows продолжает дорабатывать критические секции, потому что даже небольшие изменения в низкоуровневых механизмах синхронизации могут неожиданно влиять на старое ПО. Например, в Windows 11 24H2 обнаружилась 20-летняя ошибка в GTA San Andreas, связанная с изменением поведения критических секций — игра некорректно использовала их для синхронизации потоков, полагаясь на специфичные детали реализации, которые со временем изменились.

Это подчёркивает, насколько хрупкими могут быть зависимости приложений от внутренней работы ОС, даже если изначально код написан с ошибками. Microsoft приходится балансировать между оптимизацией и обратной совместимостью, поскольку исправление одной проблемы может вызвать регрессию в другом месте, особенно в legacy-приложениях, которые активно используют недокументированное поведение системы.

by OptionOfT • 24 сентября 2025 г. в 17:32 • 95 points

ОригиналHN

#windows#windows-11#gta-san-andreas#wine#reactos#multithreading#legacy-applications

Комментарии (71)

  • Критика Windows за проблемы с производительностью и совместимостью, особенно в контексте запуска старого ПО и игр.
  • Обсуждение недостатков Windows 11, включая медленную работу проводника и высокие требования к ресурсам.
  • Подчеркивание важности обратной совместимости и архивных копий VM для сохранения доступа к старому ПО.
  • Дебаты о качестве инженерной работы Microsoft и ответственности разработчиков игр за ошибки.
  • Упоминание альтернатив, таких как Wine и ReactOS, для обеспечения совместимости со старым Windows-софтом.

Testing is better than data structures and algorithms (nedbatchelder.com)

Новички в программировании часто зацикливаются на изучении структур данных и алгоритмов (DSA), потому что это проверяется на собеседованиях. Однако в реальной работе редко приходится реализовывать сложные алгоритмы вручную — вместо этого стоит понять базовые структуры, их trade-offs и основы Big O, чтобы эффективно организовывать и обрабатывать данные.

Гораздо полезнее сосредоточиться на тестировании: это навык, который постоянно применяется в разработке, улучшает качество кода и выделяет кандидата на фоне других. Тестирование помогает проектировать системы, учит писать проверяемый код и становится отдельной инженерной дисциплиной с богатым инструментарием.

by rsyring • 22 сентября 2025 г. в 16:21 • 151 points

ОригиналHN

#testing#data-structures#algorithms#big-o#property-based-testing#multithreading#performance

Комментарии (143)

  • Участники обсуждают важность знания структур данных и алгоритмов (DSA) для разработчиков, отмечая, что понимание их характеристик (например, сложности операций) часто важнее умения реализовывать их с нуля.
  • Подчеркивается необходимость баланса между теоретическими знаниями (DSA) и практическими навыками тестирования, при этом многие отмечают, что эти навыки не исключают, а дополняют друг друга.
  • В дискуссии звучит критика статьи, указанной в исходном посте, за её провокационный заголовок, который, по мнению участников, упрощает сложную проблему и создает ложную дихотомию между DSA и тестированием.
  • Несколько комментаторов приводят примеры из практики, где незнание базовых принципов DSA (например, сложности алгоритмов) приводило к серьезным проблемам с производительностью в продакшене.
  • Обсуждается роль тестирования: одни видят в нем ключевой навык для обеспечения качества, другие указывают на его ограничения (например, сложность тестирования многопоточных систем) и необходимость сочетать его с другими методами, как property-based тестирование или формальные доказательства.

Statistical Physics with R: Ising Model with Monte Carlo (github.com)

Проект isingLenzMC реализует метод Монте-Карло для классической модели Изинга с использованием высокопроизводительной библиотеки на языке C. Основная цель — эффективное моделирование фазовых переходов в магнитных системах, где спины атомов могут находиться в двух состояниях. Алгоритм учитывает взаимодействие ближайших соседей через гамильтониан Ленз-Джонса, что позволяет точно описывать критические явления.

Код оптимизирован для многопоточных вычислений и поддерживает различные конфигурации решётки, что делает его полезным для исследований в статистической физике и материаловедении. Проект включает примеры использования, документацию и тесты, упрощающие интеграцию в научные расчёты. Практическая ценность заключается в ускорении симуляций без потери точности, что особенно важно для изучения свойств материалов вблизи точки Кюри.

by northlondoner • 19 сентября 2025 г. в 09:19 • 99 points

ОригиналHN

#r#c#monte-carlo#ising-model#statistical-physics#multithreading#scientific-computing#quantum-ergodicity#github

Комментарии (60)

  • Обсуждается внезапный интерес к старому репозиторию с методами статистической физики, возможно, связанный с новой статьей Google по квантовой эргодичности.
  • Участники просят порекомендовать учебные материалы по методам Монте-Карло для начинающих и делятся ссылками на книги и лекции.
  • Затрагивается вопрос о различии терминов "Statistical Physics" и "Statistical Mechanics" (признаны синонимами).
  • Обсуждается роль экосистемы R для воспроизводимых исследований и её потенциальная конкуренция с Python в области научных вычислений.
  • Высказывается мнение, что моделирование одномерной модели Изинга является базовым упражнением, но может быть полезно для понимания эргодичности.

Safepoints and Fil-C (fil-c.org)

Safepoints — это ключевой механизм синхронизации в Fil-C и других виртуальных машинах, обеспечивающий безопасность памяти в многопоточной среде. Они позволяют потокам делать предположения о состоянии VM и сообщать о своём текущем состоянии, что критично для точного сборщика мусора, отладки и профилирования. Без safepoints не было бы возможности безопасно сканировать стеки, обрабатывать сигналы или использовать fork.

Fil-C вставляет pollchecks — проверки на необходимость остановки — на каждом обратном ребре управления в коде. Это короткая инструкция вроде testb, которая при срабатывании переходит к медленному пути обработки. Такой подход гарантирует, что GC может прервать поток только в безопасных точках, избегая проблем с регистрами или векторными инструкциями, и сохраняя корректность без invasive изменений в компиляторе.

by matt_d • 16 сентября 2025 г. в 04:29 • 76 points

ОригиналHN

#fil-c#safepoints#garbage-collection#multithreading#pollchecks#memory-safety#assembly#fork#vfork#jvm

Комментарии (41)

  • Fil-C использует механизм pollchecks для остановки потоков (stop-the-world), что необходимо для корректной работы fork(2), но поддержка vfork(2) пока отсутствует и требует нестандартных решений.
  • Внедрение safepoint-ов в ассемблерный код рискованно и может нарушить предположения Fil-C о безопасности памяти; в долгосрочной перспективе планируется создать способ написания безопасного ассемблерного кода.
  • Подход Fil-C к сборке мусора с опросом точек остановки (polling) создает нагрузку в tight loops, что решается разными оптимизациями (например, разверткой циклов), в отличие от асинхронных сигналов в Go.
  • Мнения о читаемости и понятности реализации Fil-C разделились: одни участники находят ее интересной и хорошо объясненной, другие признаются, что не до конца понимают детали.
  • Утверждение, что Java использует исключительно compacting GC, является упрощением, учитывая множество доступных конфигураций сборщика мусора в разных реализациях JVM.

Writing an operating system kernel from scratch (popovicu.com) 🔥 Горячее

  • Ядро ОС написано на Zig для RISC-V, одноядерное, с вытесняющей многозадачностью и системными вызовами.
  • Unikernel: приложения линкуются с ядром в один бинарник.
  • OpenSBI обслуживает M-режим; ядро работает в S-режиме, потоки — в U.
  • Потоки статические, бесконечные функции; переключение по таймеру каждые 2 мс.
  • Контекст сохраняется на стеке прерываний; ядро и пользователь разделены.
  • GitHub: popovicu/zig-time-sharing-kernel

by Bogdanp • 14 сентября 2025 г. в 15:44 • 309 points

ОригиналHN

#zig#risc-v#operating-systems#kernels#unikernels#opensbi#qemu#multithreading#system-calls

Комментарии (64)

  • Участники делятся опытом создания минимальных ОС на RISC-V и Zig: кто-то перевёл «ОС в 1000 строк» на Zig, кто-то пишет с нуля.
  • Все сходятся: RISC-V проще x86, нет легаси-багажа, документация и эмуляторы доступны.
  • Железо не обязательно: достаточно QEMU; если нужна «реалка» — Milk-V Duo S за $10 или Pico 2.
  • Миникernel — хороший способ выучить архитектуру и Forth; «не изобретай крипту для продакшена» не отменяет экспериментов.
  • В споре о «кто важнее» вспомнили: Линус начинал как хобби, а Столлман уже с 1984 года готовил инфраструктуру GNU.

Writing an operating system kernel from scratch – RISC-V/OpenSBI/Zig (popovicu.com)

Разработка ядра операционной системы с нуля

Недавно я реализовал минимальное ядро ОС с разделением времени для RISC-V. В этой статье расскажу о деталях работы прототипа. Материал предназначен для всех, кто интересуется низкоуровневым ПО, драйверами, системными вызовами, и особенно полезен студентам, изучающим системное ПО и архитектуру компьютеров.

Это переработанная версия учебного проекта по операционным системам, но с фокусом на современные инструменты и архитектуру RISC-V. RISC-V — перспективная технология, которая проще для понимания по сравнению с другими архитектурами, оставаясь популярным выбором для новых систем.

Вместо традиционного C я использовал Zig, что упрощает воспроизведение эксперимента благодаря простой настройке и отсутствию необходимости установки дополнительных инструментов для кросс-компиляции под RISC-V.

Репозиторий и рекомендации

Исходный код доступен на GitHub. Перед изучением рекомендуется ознакомиться с основами программирования на RISC-V без ОС, процессом загрузки через SBI и обработкой прерываний.

Архитектура

Мы разрабатываем унике́рнел (unikernel), где приложение и ядро объединены в один исполняемый файл. Это исключает необходимость отдельной загрузки пользовательского кода во время выполнения.

В основе стека лежит слой SBI (OpenSBI), который управляет выводом на консоль и таймером. RISC-V использует уровни привилегий: M-режим (машинный), S-режим (супервизора) и U-режим (пользовательский). Наше ядро работает в S-режиме.

Цели ядра

  1. Статическое определение потоков (без динамического создания).
  2. Потоки выполняются в пользовательском режиме и могут делать системные вызовы к ядру.
  3. Время распределяется между потоками с помощью таймера, который прерывает выполнение каждые несколько миллисекунд.
  4. Разработка ведётся для одноядерной системы.

Виртуализация и потоки

Перед реализацией важно понять, что такое поток. В среде с разделением времени потоки позволяют эффективно использовать ресурсы системы.

by popovicu • 14 сентября 2025 г. в 00:36 • 87 points

ОригиналHN

#risc-v#opensbi#zig#operating-systems#unikernel#multithreading#kernel-development#system-calls

Комментарии (3)

  • Автор переписал классическое упражнение по созданию минимального ядра ОС с разделением времени для управления пользовательскими потоками.
  • Целью был эксперимент на специфической платформе RISC-V в сочетании с OpenSBI.
  • Для реализации был использован язык программирования Zig вместо традиционного C.
  • Автор отмечает, что подход можно легко повторить на C или Rust.
  • Участник обсуждения предположил, что эта тема уже публиковалась неделей ранее.
  • Другой участник уточнил, что оригинальный пост был два дня назад на Hacker News.
  • Было отмечено, что текущий пост, хотя и от первоначального автора, изначально не получил отклика и был повторно запущен через «пул второго шанса» с измененными временными метками.

RIP pthread_cancel (eissing.org)

curl 8.16.0 внедрил pthread_cancel, чтобы прерывать зависший getaddrinfo, но уже в следующем релизе функцию убирают: отмена потока приводит к утечке памяти.

glibc сначала резолвит имя, выделяя память, затем читает /etc/gai.conf, где встречается fopen — точка отмены. Если поток прервать на этом шаге, выделенные адреса не освобождаются, и утечка повторяется при каждом новом вызове.

Поскольку других «опасных» точек может быть ещё больше, а библиотека не гарантирует чистоту ресурсов, pthread_cancel признан неприемлемым. Возвращаемся к старому выбору: либо ждать pthread_join, либо пускать потоки «в свободное плавание» и накапливать их.

Кто не хочет тормозов — подключает c-ares, но тот не покрывает всех возможностей glibc.

by robin_reala • 13 сентября 2025 г. в 17:20 • 219 points

ОригиналHN

#pthread-cancel#getaddrinfo#glibc#c-ares#dns#posix#c#multithreading

Комментарии (93)

  • Проблема: стандартный POSIX-вызов getaddrinfo блокирующий, не имеет таймаута и плохо сочетается с pthread_cancel, что приводит к утечкам/дедлокам.
  • Исторически DNS-запросы запускали в отдельном потоке/процессе, но 30 лет спустя ситуация не улучшилась.
  • Альтернативы есть: getaddrinfo_a, c-ares, systemd-resolved, io_uring, но они либо glibc-специфичны, либо нетривиальны в кросс-платформенной разработке.
  • Разработчики предлагают:
    – отказаться от pthread_cancel и использовать пул воркер-потоков с флагом «самоубийства»;
    – вынести DNS из libc в системный сервис;
    – дождаться нового POSIX-стандарта асинхронного резолвера.

Default musl allocator considered harmful to performance (nickb.dev)

musl-аллокатор тормозит в 7 раз
Добавь в main.rs:

#[cfg(target_env = "musl")]
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

и в Cargo.toml:

[target.'cfg(target_env = "musl")'.dependencies]
mimalloc = "0.1"

Проблема — конкуренция потоков за malloc. Чем больше потоков, тем хуже.
Замена аллокатора нужна даже для однопоточных программ: забудешь — потом дорого.

Почему musl? Статика + 2 МБ distroless-контейнер = старые RH и быстрый cold-start.

Кейс: сервер обрабатывал данные в 7 раз медленнее хоста.
Виноват 200 000 контекст-переключений/сек vs 1 200 у glibc.
strace показал 6,7 с в futex у musl против 0,5 с у glibc.

by fanf2 • 05 сентября 2025 г. в 20:42 • 77 points

ОригиналHN

#rust#musl#glibc#mimalloc#jemalloc#multithreading#memory-allocation#containers#performance-optimization

Комментарии (53)

  • musl-аллокатор медленен в многопоточных Rust-программах из-за одного глобального замка.
  • Альпийские образы компактны, но «размер» ≠ «скорость»; в проде чаще берут Debian/RHEL.
  • Замена: jemalloc, mimalloc или Wolfi (glibc, apk, busybox) без смены менеджера пакетов.
  • glibc тоже фрагментирует память; MALLOC_ARENA_MAX=jemalloc спасает.
  • Новый mallocng musl не решает конкуренцию потоков: цель musl — минимум кода и харднинг, а не perf.

C++: Strongly Happens Before? (nekrozqliphort.github.io)

Коротко о «strongly happens-before»

В C++20 появилось новое отношение strongly happens-before (SHB), потому что старое happens-before оказалось недостаточно строгим.

Пример кода

std::atomic<int> x{0}, y{0};

// thread-1
x.store(1, seq_cst);
y.store(1, release);

// thread-2
int b = y.fetch_add(1, seq_cst); // b = 1
int c = y.load(relaxed);         // c = 3

// thread-3
y.store(3, seq_cst);
int a = x.load(seq_cst);         // a = 0

Почему нужен SHB

  • Каждый атомарный объект имеет modification order — полный порядок всех записей.
  • Классические правила coherence (write-write, read-read, read-write, write-read) связывают happens-before с этим порядком.
  • Но при смешанных memory_order (например, release + seq_cst) между потоками могут образоваться «дыры», где старое happens-before не гарантирует ожидаемую последовательность.

Отличие SHB от HB

  • SHB добавляет требование: если операция A strongly happens-before B, то все наблюдатели видят записи A раньше записей B, даже при разных memory_order.
  • Для seq_cst SHB совпадает с HB; для release/acquire HB может быть, а SHB — нет.

Итог

Если пользуетесь только seq_cst, можно не заморачиваться. При смешанных порядках SHB — формальный способ не получить «невозможные» значения.

by signa11 • 28 августа 2025 г. в 14:54 • 86 points

ОригиналHN

#c++#multithreading#memory-model#atomic-operations#c++20

Комментарии (14)

  • Участники обсуждают различие между «strong happens-before» в Java и более слабой моделью C++.
  • Код из статьи считается не «простым», а академическим примером; порядок запуска потоков ОС не гарантирует.
  • Наблюдаемые в комментариях значения могут показаться странными, но они допустимы при отсутствии дополнительной синхронизации.
  • Смысл слабых моделей памяти — формально описать множество всех допустимых исполнений, учитывая кэши, оптимизации компилятора и т. д.
  • Добавление ещё одного атомика для «упорядочивания» может, наоборот, запретить именно тот «неинтуитивный» порядок, который автор статьи исследует.

How to slow down a program and why it can be useful (stefan-marr.de)

  • Зачем замедлять программу?
    Искать race-conditions, «виртуально» оценить выгоду оптимизации (как в Coz) и проверять точность профилировщиков. Для этого меняют расписание потоков или вставляют задержки.

  • Как замедляют сейчас?
    Грубо: Thread.sleep, остановка потоков, вставка лишнего байт-кода. Это снижает точность.

  • Наша идея
    Вставлять задержки внутри basic block на уровне x86. Нужны инструкции, которые:
    – надёжно тратят циклы;
    – не искажают семантику;
    – не оптимизируются CPU за счёт out-of-order.

  • Проблема
    Современные процессоры выполняют независимые mov параллельно, поэтому просто добавить «тяжёлые» команды недостаточно — нужно учитывать зависимости и микроархитектуру.

by todsacerdoti • 27 августа 2025 г. в 11:38 • 141 points

ОригиналHN

#multithreading#performance#profiling#optimization#x86#race-conditions#cpu#causal-profiling#coz#toxiproxy

Комментарии (50)

  • Используются разные способы замедления: от NOP-циклов и RDTSC до AVX-нагрузок и «тормозных» устройств вроде C64 Snail или Turbo-кнопки.
  • Замедление помогает выявлять N+1-запросы, неработающие кеши и другие узкие места, которые на быстрых машинах незаметны.
  • Современные CPU оптимизируют NOP/MOV на стадии переименования, поэтому они плохо подходят для точного контроля времени.
  • Causal-profiling (Coz) и специальные прокси (Toxiproxy, dummynet) позволяют «ускорять» выбранный код, оставляя остальное медленным, чтобы заранее оценить выгоду оптимизации.

"Special register groups" invaded computer dictionaries for decades (2019) (righto.com)

Как «специальные группы регистров» 50 лет жили в словарях

Фраза «special register groups» внезапно появилась в определении «CPU» в 1960-е и до сих пор мелькает в учебниках.

В старом глоссарии Минсельхоза США (1960) читаем:

«MAIN FRAME — центральный процессор; включает основную память, арифметическое устройство и special register groups».

Это описание относилось к мэйнфрейму Honeywell 800 (1959), где для многозадачности каждая из 8 программ получала собственный аппаратный набор из 32 регистров — именно их Honeywell назвала «special register groups».

Определение скопировали чиновники, оно попало в Automatic Data Processing Glossary, затем — в сотни книг и статей. Постепенно «main frame» стало синонимом «тип большого компьютера», а «special register groups» превратились в бессмысленную клишированную строчку, которую перепечатывали до 2017 года включительно.

by Bogdanp • 26 августа 2025 г. в 18:57 • 90 points

ОригиналHN

#cpu#registers#multithreading#honeywell#mainframe#history-of-computing#computer-architecture

Комментарии (39)

  • Участники обсудили странное определение «special register groups» в старых словарях: оно неясно и не упоминает обычные регистры.
  • Упомянули, что IBM в 1954 году определяла CPU как совокупность арифметических и управляющих функций, без «специальных регистров».
  • Появились примеры старых машин, например Honeywell 800, где у каждой программы был свой набор регистров — предшественник barrel- и multithread-процессоров.
  • Отмечено, что терминология часто копировалась без проверки, создавая «человеческий слаг» вроде «tongue map» или «brushless DC».
  • Участники сравнили путаницу в терминах с другими примерами, включая RAM, ROM, SMT и «micom» в японских рисоварках.

Without the futex, it's futile (h4x0r.org) 🔥 Горячее

Без futex всё тленно

Книга The Art of Multiprocessor Programming (2-е изд., 2021) считается канонической, но она обходит стороной futex — ключевой примитив современной многопоточности. Это упущение делает пособие бесполезным для практиков.

Futex ≠ mutex
Название происходит от «fast userspace mutex», но futex — это не мьютекс, а основа для всех высокоэффективных примитивов синхронизации. До него всё строилось на громоздких System V IPC, которые не масштабировались: при 1000 потоков futex в 2002-м оказался в 20–120 раз быстрее sysv-блокировок. Windows и macOS добавили аналоги только в 2012 и 2016 гг.

Суть futex
Он разделяет блокировку и ожидание/пробуждение:

  • В user-space проверяем состояние; если свободно — захватываем без системного вызова.
  • При конфликте вызываем futex_wait(addr, expected), засыпаем в ядре на конкретном адресе.
  • Пробуждение — futex_wake(addr, n), где n обычно 1 или «все».

Передаваемое в wait значение защищает от «просыпания» после уже случившегося события: если память изменилась, системный вызов мгновенно возвращает ошибку.

Такой подход убирает лишние системные вызовы и позволяет строить быстрые мьютексы, rw-lock’и, семафоры и пр. без поллинга и экспоненциальных бэкоффов.

Итог
Любая современная библиотека (pthreads, C++ std::mutex, Rust std::sync) опирается на futex. Учебник, игнорирующий этот примитив, не готовит к реальной разработке.

by eatonphil • 19 августа 2025 г. в 13:53 • 284 points

ОригиналHN

#futex#multithreading#system-v#linux#pthreads#rust#c++#io-uring#numa#synchronization

Комментарии (138)

  • Futex — это быстрый примитив синхронизации, который экономит системные вызовы при отсутствии конфликтов и не требует выделения ядром объектов.
  • В отличие от Benaphore и старых SysV-механизмов, futex не требует предварительной инициализации в ядре и исчезает, когда нет ожидающих.
  • Обсуждение подчёркивает, что современные учебники по многопроцессорному программированию обязаны упоминать futex, но «The Art of Multiprocessor Programming» этому не уделяет внимания.
  • Улучшения futex2 (Linux ≥5.16) добавили NUMA-поддержку и аналог Windows WaitForMultipleObjects, а io_uring теперь умеет работать с futex.
  • Для надёжности при падении потока существуют robust-locks и списки futex, которые ядро автоматически разблокирует.

Partially Matching Zig Enums (matklad.github.io)

by ingve • 09 августа 2025 г. в 08:50 • 129 points

ОригиналHN

#zig#comptime#metaprogramming#memory-safety#data-race-safety#multithreading

Комментарии (89)

  • Zig вызывает интерес благодаря мощному comptime и «inline else», позволяющим абстрагироваться без рантайм-оверхеда.
  • Участники сравнивают его метапрограммирование с C, D и Rust, отмечая, что похожие идеи уже были, но Zig может сделать их популярнее.
  • Главный упрек Zig — отсутствие гарантий memory- и data-race safety, из-за чего многие считают его неподходящим для многопоточного кода.
  • «comptime unreachable» воспринимается как способ доказать компилятору недостижимость кода, а не как runtime-assert.
  • Некоторые считают, что язык ещё нестабилен и экосистема незрела, поэтому широкое внедрение отложено.