Стартапы и венчурный капитал

Как обработать 1 миллиард строк в Bun/TypeScript менее чем за 10 секунд

Стартапы и венчурный капитал
Parsing 1 Billion Rows in Bun/TypeScript Under 10s

Подробное руководство по оптимизации обработки огромных файлов в Bun с использованием TypeScript. Узнайте, как преодолеть ограничения памяти, эффективно разбивать файлы на части и ускорять вычисления с помощью многопоточности и ручной обработки байтов.

Обработка огромных объёмов данных в современных приложениях является одной из самых сложных и интересных задач. Особенно если речь идёт о файлах, содержащих миллиарды строк, которые архивируют значимый массив информации. В данной статье расскажем, как на платформе Bun и с помощью TypeScript можно эффективно обработать файл с миллиардами строк размером 13.8 ГБ менее чем за 10 секунд, рассмотрим возникающие при этом проблемы и пути их решения. Изначально основные сложности связаны с ограничениями памяти, многопоточностью в однопоточной среде и характером ввода-вывода.

Работа с большими файлами требует грамотного подхода к чтению данных, чтобы избежать перегрузки оперативной памяти и не столкнуться с ошибками во время загрузки. Первая попытка загрузить весь файл целиком в память часто оказывается неудачной. На практике оказывается, что хотя операционная система и физически располагает достаточным объёмом RAM, платформа Bun накладывает жёсткие ограничения на размер объектов Buffer, которые в большинстве случаев не могут превышать 4 ГБ из-за технических особенностей реализации с использованием 32-битных чисел. В итоге попытка вызова readFileSync с огромным файлом приводит к ошибке ENOMEM – недостаток памяти. Чтобы решить эту проблему, необходимо отказаться от загрузки всего файла целиком и перейти к пакетной обработке данных.

Разбиение файла на небольшие чанки позволяет выделять память под manageable куски и последовательно обрабатывать их. В Bun для работы с файлами доступно несколько API: readFileSync, Bun.file с .text(), методы открывания и чтения с использованием fd (file descriptor), а также поточное чтение с readline. Для работы с большими объемами лучше всего подходят именно чтение чанками через открытый файловый дескриптор и потоковые методы.

 

Выбор размера чанка – это также важный момент. Эксперименты показали, что слишком большие буферы (например, 4 ГБ) не дают прироста в скорости и даже замедляют процесс из-за затрат на выделение и инициализацию памяти. С другой стороны, слишком маленькие размеры увеличивают количество системных вызовов и оверхед при обработке. Оптимальным размером оказался буфер в диапазоне 128 КБ, что совпадает с размерами страниц памяти и параметрами readahead в современных ОС. Это даёт почти мгновенное чтение файла без падений и стабильную работу процесса.

 

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

 

Таким образом гарантируется, что каждый поток получит на обработку полный набор строк без пересечений и потерь. Для максимальной скорости обработки важно не только эффективно читать данные, но и задействовать весь доступный ресурс процессора. Bun — однопоточная платформа, что ограничивает использование нескольких ядер напрямую. Чтобы обойти это, возникает идея использования воркеров — отдельных процессов или потоков, которые параллельно обрабатывают выделенные части файла. Каждый воркер читает свой чанок, парсит строки и аккумулирует статистику локально.

В конце результаты всех воркеров собираются и агрегируются в глобальный статистический отчёт. Создание ровного числа чанков, равного количеству CPU ядер, и распределение работы между воркерами позволяет добиться масштабируемости и снизить время обработки в несколько раз. Такой подход является аналогом технологий многопоточной обработки в других языках и фреймворках, но реализован с учётом особенностей Bun и JavaScript. Следующий узкий горлышко — парсинг строк из их текстового представления. В некоторых инструментах для построчного чтения используется встроенное преобразование в UTF-8 строку, что стоит больших затрат процессорного времени при обработке миллиардов записей.

Исходя из этого, решение было найдено в отказе от дорогих преобразований с использованием строк в пользу прямого парсинга байтов. Анализ каждого байта из прочитанного буфера позволяет существенно ускорить распознавание данных. В файле ожидаются ограниченный набор символов — латинские буквы, цифры, точка с запятой, знак минуса, цифры с плавающей точкой и символ перевода строки. Зная это, можно последовательно пройтись по байтам, определить позицию разделителя (';'), отделить имя станции и температуру, а затем численно собрать число из ASCII-кодов символов без промежуточных конвертаций в строки. Такой байтовый парсинг, реализованный через проверку кодов символов и построение численных значений вручную, позволяет избежать лишнего времени на преобразование и аллокацию строк, что при работе с миллиардами строк даёт выигрыш в десятки процентов по времени.

Кроме того, для каждого узла информации аккумулируется статистика: минимум, максимум, сумма и количество измерений, что в конце позволяет вычислить среднее значение температуры для каждой станции. Хранение этой информации в Map или хеш-таблице с быстрым доступом позволяет вести подсчёт за один проход файла. В итоге, комплексно применяя все перечисленные техники — правильный выбор размера буфера, аккуратное разбиение файла с сохранением целостности строк, использование многопоточности через воркеры и оптимизированный байтовый парсинг — удалось ускорить процесс обработки файла с миллиардами строк до 9.22 секунд. Этот результат впечатляет для языка на базе JavaScript, обычно не ассоциируемого с высокопроизводительной обработкой больших данных.

Он показывает перспективы и возможности платформы Bun и TypeScript в нетипичных задачах, выходящих за пределы стандартного веб-разработчика. Важным выводом из проделанной работы является осознание ограничений платформы и необходимость глубокого понимания внутренней работы инструментов и операционной системы. В частности, о лимите буфера на 4 ГБ, поведении планировщика и файловой системы, обработке памяти и необходимости работы с низкоуровневыми байтовыми массивами. Также работа с воркерами в Bun показала, что хотя подход возможен, он требует дополнительной обвязки и разделения кода, что немного усложняет разработку по сравнению с языками, изначально заточенными под параллелизм, такими как Go или Rust. Тем не менее его использование значительно расширяет возможности в однопоточном окружении JavaScript.

Автоматическая торговля на криптовалютных биржах

Далее
What Every Data Scientist Needs to Know About GPUs [video]
Суббота, 18 Октябрь 2025 Все, что должен знать каждый дата-сайентист о графических процессорах (GPU)

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

Arm estimates a 14-fold increase in data center customers since 2021
Суббота, 18 Октябрь 2025 Arm: стремительный рост числа клиентов дата-центров с 2021 года

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

Japan Wires the Ocean with an Earthquake-Sensing 'Nervous System'
Суббота, 18 Октябрь 2025 Япония создает океаническую «нервную систему» для раннего обнаружения землетрясений и цунами

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

Robot performs realistic gallbladder surgery 'with 100% accuracy'
Суббота, 18 Октябрь 2025 Революция в хирургии: робот выполняет удаление желчного пузыря с точностью 100%

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

Show HN: InvestAI – An AI assistant to help people invest more independently
Суббота, 18 Октябрь 2025 InvestAI – Искусственный интеллект, который поможет инвестировать самостоятельно и эффективно

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

Bastille 1.0 – Bastille Day 2025
Суббота, 18 Октябрь 2025 Bastille 1.0 – Новый этап развития контейнерных технологий на Bastille Day 2025

Подробный обзор релиза Bastille 1. 0, его инновационных функций и улучшений, которые открывают новые возможности для управления VNET Jail в FreeBSD на Bastille Day 2025.

The Lazy Marketer's Guide to Not Writing Terrible AI Prompts
Суббота, 18 Октябрь 2025 Как маркетологу создавать эффективные AI-промпты без лишних усилий

Подробное руководство для маркетологов по созданию качественных AI-запросов, которое поможет повысить результативность работы с искусственным интеллектом и оптимизировать рабочие процессы.