Не всё же работать, иногда можно и поиграть.
Разобрали пять способов пополнения баланса Steam. Один зачисляет деньги на кошелёк по логину за одну-две минуты с комиссией около 6%. Другой показывает итоговую сумму ещё до оплаты и подходит для регулярных небольших пополнений. Третий — маркетплейс, где условия зависят от выбранного продавца, но сделки защищены гарантиями площадки. Четвёртый предлагает пополнение и по логину, и через продажу игровых предметов почти без комиссии. Пятый не берёт свою комиссию, но добавляет разницу за счёт курса конвертации.
По каждому — реальная комиссия, лимиты и на что смотреть, чтобы не наткнуться на мошенников. Складывайте в сохранёнки, вдруг пригодится.
Разобрали пять способов пополнения баланса Steam. Один зачисляет деньги на кошелёк по логину за одну-две минуты с комиссией около 6%. Другой показывает итоговую сумму ещё до оплаты и подходит для регулярных небольших пополнений. Третий — маркетплейс, где условия зависят от выбранного продавца, но сделки защищены гарантиями площадки. Четвёртый предлагает пополнение и по логину, и через продажу игровых предметов почти без комиссии. Пятый не берёт свою комиссию, но добавляет разницу за счёт курса конвертации.
По каждому — реальная комиссия, лимиты и на что смотреть, чтобы не наткнуться на мошенников. Складывайте в сохранёнки, вдруг пригодится.
Интерпретатор WebAssembly ускорили в 2,2 раза, и автор объяснил каждую оптимизацию
Wasmi нужен там, где JIT запрещён или не помещается: плагины, микроконтроллеры, песочницы, смарт-контракты. Версия 2.0 по замерам проекта исполняет код в 2,2 раза быстрее 1.0 по геометрическому среднему, а пост Робина Фрайлера читается как учебник по устройству быстрых интерпретаторов.
Три источника ускорения: четыре режима dispatch вместо одного switch-loop (
Отдельная история про компилятор: Rust 1.92 включил
@prog_stuff
Wasmi нужен там, где JIT запрещён или не помещается: плагины, микроконтроллеры, песочницы, смарт-контракты. Версия 2.0 по замерам проекта исполняет код в 2,2 раза быстрее 1.0 по геометрическому среднему, а пост Робина Фрайлера читается как учебник по устройству быстрых интерпретаторов.
Три источника ускорения: четыре режима dispatch вместо одного switch-loop (
auto-dispatch сам выбирает threaded-код, где компилятор позволяет), новое IR с аккумуляторными регистрами вместо стековых смещений и append-only CodeMap, где вызов функции на горячем пути не делает ни одного lookup. Ячейки стека стали 64-битными, поэтому SIMD больше не стоит 8% обычному коду.Отдельная история про компилятор: Rust 1.92 включил
DestinationPropagation, и CoreMark у интерпретатора Stitch упал с 3000 до 2200. Похожую проблему нашли и в Wasmi, после исправления результат вырос с 2800 до 4200. Вывод: после обновления toolchain бенчмарки интерпретатора надо перепрогонять. Сравнение с Wasm3, WAMR и Wasmtime Pulley разобрали на сайте.@prog_stuff
❤🔥2
Утечку горутин теперь ищет сборщик мусора: как устроен новый профиль в Go 1.27
Обычный goroutine-профиль показывает, сколько горутин заблокировано, но не говорит, проснутся ли они. Команда Go объяснила, как профиль
На схеме из блога видно, куда это встроено в маркировку GC. Худший случай, цепочка горутин, каждая из которых держит примитив следующей, даёт O(n²) за цикл, поэтому профиль советуют снимать раз в несколько часов, а не постоянно. Не ловит ожидание сети, файлов и самодельных спинлоков. Пример с 116 зависшими воркерами и что включить у себя, на сайте.
@prog_stuff
Обычный goroutine-профиль показывает, сколько горутин заблокировано, но не говорит, проснутся ли они. Команда Go объяснила, как профиль
goroutineleak решает это через достижимость: горутина живая, если она не заблокирована или если канал либо мьютекс, на котором она ждёт, достижим из другой живой горутины. Всё, что осталось недостижимым после обхода, разбудить некому.На схеме из блога видно, куда это встроено в маркировку GC. Худший случай, цепочка горутин, каждая из которых держит примитив следующей, даёт O(n²) за цикл, поэтому профиль советуют снимать раз в несколько часов, а не постоянно. Не ловит ожидание сети, файлов и самодельных спинлоков. Пример с 116 зависшими воркерами и что включить у себя, на сайте.
@prog_stuff
Форк SQLite с ветками и merge дошёл до беты, и авторы честно назвали цену записи
DoltLite заменяет в SQLite B-tree на content-addressed Prolly Tree, а всё остальное, от парсера SQL до тестового harness, оставляет родным. Из-за этого база получает Git-подобные операции: branch, merge, diff, rebase, cherry-pick, reset, push и pull на свой remote или DoltHub. 31 августа проект объявил бету и версию 0.50.0.
Цифры совместимости серьёзные: 100%
Цена: в памяти чтение медленнее на 10%, запись на 60%; для файловых баз чтение на уровне SQLite, а вот мелкие autocommit-записи в 3,1 раза дольше, 400 мкс против 125. Каждое изменение порождает новые chunk с хешами, и на одиночной вставке это не амортизируется. Где такая база уместна, а где SQLite останется быстрее, разобрали на сайте.
@prog_stuff
DoltLite заменяет в SQLite B-tree на content-addressed Prolly Tree, а всё остальное, от парсера SQL до тестового harness, оставляет родным. Из-за этого база получает Git-подобные операции: branch, merge, diff, rebase, cherry-pick, reset, push и pull на свой remote или DoltHub. 31 августа проект объявил бету и версию 0.50.0.
Цифры совместимости серьёзные: 100%
sqllogictest из 5,8 млн запросов и 99,46% из 892 277 TCL-тестов самого SQLite. Оставшиеся 4809 расхождений упираются в архитектуру: нет rowid, chunk вместо page, нет WAL рядом с файлом.Цена: в памяти чтение медленнее на 10%, запись на 60%; для файловых баз чтение на уровне SQLite, а вот мелкие autocommit-записи в 3,1 раза дольше, 400 мкс против 125. Каждое изменение порождает новые chunk с хешами, и на одиночной вставке это не амортизируется. Где такая база уместна, а где SQLite останется быстрее, разобрали на сайте.
@prog_stuff
Прототип Cloudflare ужал текст в кэше в 2,8 раза, потратив на это несколько процентов CPU
Казалось бы, текст в интернете и так сжат. Но по замерам Cloudflare около 71% текстовых ответов приходят от origin-серверов без
Прототип Cache Transcoding внутри Pingora сжимает подходящие ответы zstd уровня 3 при записи в кэш, между дата-центрами гоняет их сжатыми и распаковывает перед клиентом. Кодирование стоит 4,31 нс на байт, декодирование 1,56 нс, коэффициент 2,834x на двух тестовых объектах, а не на всём кэше. Порог 4 КиБ отсёк мелочь и потерял всего 1% выигрыша.
Главная фраза статьи: стоимость кодирования платится один раз, когда объект попадает в кэш. Приём переносится на nginx с proxy_cache и Varnish без изменений в идее; порядок действий и где считать CPU разобрали на сайте.
@prog_stuff
Казалось бы, текст в интернете и так сжат. Но по замерам Cloudflare около 71% текстовых ответов приходят от origin-серверов без
Content-Encoding: сжимает уже edge, а на диск кэша объект ложится сырым. При этом HTML, JSON, CSS и JS дают 67,3% запросов и 22,3% байтов, а картинки и видео 21,4% запросов и 63,3% байтов, их пересжимать бессмысленно.Прототип Cache Transcoding внутри Pingora сжимает подходящие ответы zstd уровня 3 при записи в кэш, между дата-центрами гоняет их сжатыми и распаковывает перед клиентом. Кодирование стоит 4,31 нс на байт, декодирование 1,56 нс, коэффициент 2,834x на двух тестовых объектах, а не на всём кэше. Порог 4 КиБ отсёк мелочь и потерял всего 1% выигрыша.
Главная фраза статьи: стоимость кодирования платится один раз, когда объект попадает в кэш. Приём переносится на nginx с proxy_cache и Varnish без изменений в идее; порядок действий и где считать CPU разобрали на сайте.
@prog_stuff
Один младший бит: как реализация FMA вскрыла одинаковую ошибку в Rust std, std::simd и musl
Shnatsel переносил формально верифицированный алгоритм fused multiply-add в библиотеку
Ошибка живёт в программной эмуляции FMA, на железе с аппаратной инструкцией её нет: затронуты старые Intel без AVX2, Hygon и 32-битный ARM. Автор не берётся оценить практический ущерб, но называет сценарий, где это больно: детерминированные симуляции, которые обязаны давать одинаковые биты на разных машинах. Проверка из трёх hex-чисел и состояние патчей на сайте.
@prog_stuff
Shnatsel переносил формально верифицированный алгоритм fused multiply-add в библиотеку
fearless_simd, добавил тесты на миллион субнормальных значений и получил расхождение. Дальше оказалось, что f32::mul_add в стандартной библиотеке Rust ошибается ровно так же, как и fmaf() в musl, а контрпример к первой версии патча нашла языковая модель.Ошибка живёт в программной эмуляции FMA, на железе с аппаратной инструкцией её нет: затронуты старые Intel без AVX2, Hygon и 32-битный ARM. Автор не берётся оценить практический ущерб, но называет сценарий, где это больно: детерминированные симуляции, которые обязаны давать одинаковые биты на разных машинах. Проверка из трёх hex-чисел и состояние патчей на сайте.
@prog_stuff
👍2
Разработчик сделал бэкенд компилятора, чтобы написать игру для Game Boy на чистом Rust
Game Boy не является целью Rust даже на уровне Tier 3: процессор SM83 не поддерживается LLVM. Автор под ником zlfn начинал с SDCC и библиотеки GBDK, а закончил собственным форком LLVM с бэкендом Z80/SM83 и форком rustc с целью
Внутри есть Rust-библиотеки для графики, звука, ввода и консоли, упаковка кода в банки по 16 КиБ и собственный линкер. Готовый ROM
Автор предупреждает, что проект не тестировался вне его машины и это ранняя стадия. Но это редкий пример, когда «Rust везде» доказано не докладом, а бэкендом компилятора под восьмибитную приставку. Репозиторий на GitHub.
@prog_stuff
Game Boy не является целью Rust даже на уровне Tier 3: процессор SM83 не поддерживается LLVM. Автор под ником zlfn начинал с SDCC и библиотеки GBDK, а закончил собственным форком LLVM с бэкендом Z80/SM83 и форком rustc с целью
sm83. Теперь cargo-gb build собирает crate в ROM, а cargo-gb run сразу запускает эмулятор.Внутри есть Rust-библиотеки для графики, звука, ввода и консоли, упаковка кода в банки по 16 КиБ и собственный линкер. Готовый ROM
sprite.gb можно скачать и запустить в любом эмуляторе; исходник примера лежит в examples/sprite.Автор предупреждает, что проект не тестировался вне его машины и это ранняя стадия. Но это редкий пример, когда «Rust везде» доказано не докладом, а бэкендом компилятора под восьмибитную приставку. Репозиторий на GitHub.
@prog_stuff
❤🔥3
Стековый байткод против регистрового: замер на одном языке, одном железе и честной методике
Максим Шевалье-Буавер, в прошлом автор YJIT для Ruby, переписала VM своего языка Plush с стековой модели на регистровую и разложила, откуда взялось ускорение. Инструкция стала 64-битным словом с тремя операндами;
Методика: 11 чередующихся запусков на тест, медиана, повтор всего набора. Медиана ускорения 2,07 раза, максимум 3,37, тесты GC не сдвинулись. Против Lua 5.5.1 на
@prog_stuff
Максим Шевалье-Буавер, в прошлом автор YJIT для Ruby, переписала VM своего языка Plush с стековой модели на регистровую и разложила, откуда взялось ускорение. Инструкция стала 64-битным словом с тремя операндами;
a + b из трёх диспетчеризаций превратилось в одну. Сама смена модели дала 1,55 раза по геометрическому среднему, слитые сравнения-переходы, непосредственные операнды и свёртка констант добавили ещё 25%.Методика: 11 чередующихся запусков на тест, медиана, повтор всего набора. Медиана ускорения 2,07 раза, максимум 3,37, тесты GC не сдвинулись. Против Lua 5.5.1 на
fib быстрее на 24%. Главный урок автора: в интерпретаторе считайте инструкции, а не такты. Полный разбор на сайте.@prog_stuff
Модуль std ускорил сборку Seastar на 22% без единой правки в исходниках
Чуаньцы Сюй из команды Clang показал два способа подключить
Замер на Seastar, Clang и libc++ из ветки 24,
Из ограничений: нужен Clang 24 (в 23 автор ловил зависание), в module map нельзя включать заголовки с макросами вроде
@prog_stuff
Чуаньцы Сюй из команды Clang показал два способа подключить
import std; к проекту, который об этом не знает. Preload заставляет компилятор загружать BMI модуля std перед каждой единицей трансляции через -fmodule-file. Module Map идёт дальше: файл std.modulemap подменяет #include <vector> и остальные STL-заголовки на import std; автоматически.Замер на Seastar, Clang и libc++ из ветки 24,
-j8, медиана из трёх прогонов. Wall-time: 92,21 с с заголовками, 81,09 с с Preload, 71,55 с с Module Map, то есть минус 12% и минус 22%. Пользовательское CPU-время упало с 655,7 до 497,5 с. Память при Preload выросла на 2,7%, при Module Map снизилась на 3,3%.Из ограничений: нужен Clang 24 (в 23 автор ловил зависание), в module map нельзя включать заголовки с макросами вроде
cassert, а заголовки пришлось пробросить симлинками. Полный патч к CMake лежит в ветке автора, разбор в блоге.@prog_stuff
Двухчасовое расследование о том, откуда взялась фраза про преждевременную оптимизацию
Её полвека цитируют то как Кнута, то как Хоара, чаще всего чтобы осадить желание написать код побыстрее. Кейси Муратори собрал больше 200 исторических документов, от переписки Дейкстры времён «GOTO considered harmful» до отчётов конференций NATO 1968 года, и показал, при каких обстоятельствах фраза родилась и к чему её на самом деле применяли.
Попутно у Хоара в 1965 году нашлась конструкция, похожая на SSA-форму, а у Страуструпа в 1979-м приём, который сегодня называют dependency injection. В нашем канале Tproger разобрали подробнее.
@prog_stuff
Её полвека цитируют то как Кнута, то как Хоара, чаще всего чтобы осадить желание написать код побыстрее. Кейси Муратори собрал больше 200 исторических документов, от переписки Дейкстры времён «GOTO considered harmful» до отчётов конференций NATO 1968 года, и показал, при каких обстоятельствах фраза родилась и к чему её на самом деле применяли.
Попутно у Хоара в 1965 году нашлась конструкция, похожая на SSA-форму, а у Страуструпа в 1979-м приём, который сегодня называют dependency injection. В нашем канале Tproger разобрали подробнее.
@prog_stuff
Выделите всю память при старте и никогда больше: как TigerBeetle защищается от перегрузки
Алексей Кладов (matklad) отвечает на письмо читателя, который получил use-after-free в матчере ордеров с пулом объектов, и выводит из этого два приёма из TigerStyle. Первый: никакой динамической аллокации после инициализации. Программа запускается с
На возражение «а вдруг память ещё есть» ответ: а вдруг нет? Попытка выделить ещё один объект под нагрузкой заканчивается OOM-киллером, который снимает весь процесс с миллионом ордеров внутри, а то и супервизор. Со статическим лимитом система может не стартовать без памяти, но если стартовала, деградирует предсказуемо. По дороге разбирается, почему пул объектов одного типа превращает опасный use-after-free в скучный детерминированный баг.
@prog_stuff
Алексей Кладов (matklad) отвечает на письмо читателя, который получил use-after-free в матчере ордеров с пулом объектов, и выводит из этого два приёма из TigerStyle. Первый: никакой динамической аллокации после инициализации. Программа запускается с
--orders-max=1_000_000, выделяет массив под миллион ордеров одной строкой и всё, что сверх лимита, отклоняет.На возражение «а вдруг память ещё есть» ответ: а вдруг нет? Попытка выделить ещё один объект под нагрузкой заканчивается OOM-киллером, который снимает весь процесс с миллионом ордеров внутри, а то и супервизор. Со статическим лимитом система может не стартовать без памяти, но если стартовала, деградирует предсказуемо. По дороге разбирается, почему пул объектов одного типа превращает опасный use-after-free в скучный детерминированный баг.
@prog_stuff
Сколько знаков в 52 факториала и как прикинуть это без калькулятора
Началось с бытового вопроса: насколько велико число перестановок колоды карт. Дальше Эли Бендерски задумался, как оценивать такие величины, не имея под рукой ни калькулятора, ни компьютера.
Оказалось, что за оценкой количества знаков в факториале стоит вполне занятная математика, и разбор разворачивает её шаг за шагом, без предварительных знаний сверх школьных.
Жанр здесь не прикладной, а тот, ради которого такие блоги и читают: короткое погружение в тему, которая на работе не понадобится, но перестраивает интуицию про рост чисел.
Началось с бытового вопроса: насколько велико число перестановок колоды карт. Дальше Эли Бендерски задумался, как оценивать такие величины, не имея под рукой ни калькулятора, ни компьютера.
Оказалось, что за оценкой количества знаков в факториале стоит вполне занятная математика, и разбор разворачивает её шаг за шагом, без предварительных знаний сверх школьных.
Жанр здесь не прикладной, а тот, ради которого такие блоги и читают: короткое погружение в тему, которая на работе не понадобится, но перестраивает интуицию про рост чисел.
«Zero-cost» compile-time информация о типах стоит экспоненциально, а runtime-таблица линейно
Джинджер Билл, автор языка Odin, объясняет, почему Odin форматирует вывод через RTTI, а не через генерацию кода на этапе компиляции. Таблица типов растёт линейно: N типов, N записей, одна процедура печати на все, ноль дополнительной работы у семантического анализатора. Её размер можно прочитать в бинарнике в байтах.
CTTI специализирует код под каждый тип и каждую комбинацию: сериализатор N типов в K форматов даёт N на K инстанциаций, и это повторяется в проверке типов, кодогенерации и размере бинарника. Цену этого никто не может назвать в цифрах, потому что она размазана по компилятору, зато её называют «бесплатной». Автор аккуратно разводит «известно на этапе компиляции» и «бесплатно перечислить на этапе компиляции»: это разные вещи.
@prog_stuff
Джинджер Билл, автор языка Odin, объясняет, почему Odin форматирует вывод через RTTI, а не через генерацию кода на этапе компиляции. Таблица типов растёт линейно: N типов, N записей, одна процедура печати на все, ноль дополнительной работы у семантического анализатора. Её размер можно прочитать в бинарнике в байтах.
CTTI специализирует код под каждый тип и каждую комбинацию: сериализатор N типов в K форматов даёт N на K инстанциаций, и это повторяется в проверке типов, кодогенерации и размере бинарника. Цену этого никто не может назвать в цифрах, потому что она размазана по компилятору, зато её называют «бесплатной». Автор аккуратно разводит «известно на этапе компиляции» и «бесплатно перечислить на этапе компиляции»: это разные вещи.
@prog_stuff
Задержка, пропускная способность или цена токена: карта компромиссов инференса LLM
Филип Кили из Baseten раскладывает все приёмы ускорения инференса на две группы. Одни двигают развёртывание вдоль кривой компромисса: размер батча (маленький даёт низкую задержку и дорогой токен, большой наоборот), tensor parallelism с дорогой all-to-all коммуникацией ради задержки, expert parallelism, который на широких MoE может занимать целую стойку. Другие сдвигают саму кривую: квантизация в MXFP4 и NVFP4, оптимизация ядер, speculative decoding (EAGLE-3, DSpark, DFlash), разнесение prefill и decode по разным воркерам.
Полезная арифметика: удвоение производительности железа и удвоение софтверного слоя вместе дают четырёхкратный выигрыш. И честная оговорка: на практике фронтир зубчатый, и попадание в целевые числа чаще вопрос перебора конфигураций, чем новой идеи.
@prog_stuff
Филип Кили из Baseten раскладывает все приёмы ускорения инференса на две группы. Одни двигают развёртывание вдоль кривой компромисса: размер батча (маленький даёт низкую задержку и дорогой токен, большой наоборот), tensor parallelism с дорогой all-to-all коммуникацией ради задержки, expert parallelism, который на широких MoE может занимать целую стойку. Другие сдвигают саму кривую: квантизация в MXFP4 и NVFP4, оптимизация ядер, speculative decoding (EAGLE-3, DSpark, DFlash), разнесение prefill и decode по разным воркерам.
Полезная арифметика: удвоение производительности железа и удвоение софтверного слоя вместе дают четырёхкратный выигрыш. И честная оговорка: на практике фронтир зубчатый, и попадание в целевые числа чаще вопрос перебора конфигураций, чем новой идеи.
@prog_stuff
WhatsApp* классифицирует мошеннические сообщения на устройстве, не нарушая сквозное шифрование
Задача с виду противоречивая: распознать мошенническое сообщение и не прочитать переписку. Meta* публикует технический обзор Scam Alert до массового выката, вместе с ограниченной бетой, и приглашает исследователей безопасности его ломать.
Решение целиком на устройстве: содержимое сообщений не покидает телефон ради классификации и не отправляется автоматически ни в WhatsApp*, ни в Meta*, ни кому-либо ещё. Функция опциональна и включается пользователем.
Принципы названы прямо: модель достаточно мала, чтобы работать на мобильном железе, достаточно проста, чтобы её опубликовать для независимой проверки, и достаточно эффективна без серверной части. Недавние успехи в моделях на устройстве как раз и сделали такой размен возможным.
*Компания Meta и её продукты признаны экстремистскими, их деятельность запрещена на территории РФ.
Задача с виду противоречивая: распознать мошенническое сообщение и не прочитать переписку. Meta* публикует технический обзор Scam Alert до массового выката, вместе с ограниченной бетой, и приглашает исследователей безопасности его ломать.
Решение целиком на устройстве: содержимое сообщений не покидает телефон ради классификации и не отправляется автоматически ни в WhatsApp*, ни в Meta*, ни кому-либо ещё. Функция опциональна и включается пользователем.
Принципы названы прямо: модель достаточно мала, чтобы работать на мобильном железе, достаточно проста, чтобы её опубликовать для независимой проверки, и достаточно эффективна без серверной части. Недавние успехи в моделях на устройстве как раз и сделали такой размен возможным.
*Компания Meta и её продукты признаны экстремистскими, их деятельность запрещена на территории РФ.
Engineering at Meta
How We’re Building Scam Alert on WhatsApp With End-to-End Encryption and Verifiability Guarantees
WhatsApp is committed to helping people stay safe while protecting the privacy of their messages. As scam tactics evolve — from impersonation to social engineering to AI-generated lures — we’…
🤯1