РелизРазбор · На радарSimon Willison→ оригинал

Саймон Уиллисон с Claude ускорил разбор чисел в SQLite с 67 до 19 нс

Сумма «-$1,234.56» из CSV требует очистки, прежде чем её можно складывать в SQLite. Саймон Уиллисон попросил Claude сравнить расширения на C и Rust для такой задачи: первые версии на Rust оказались быстрее, хотя занимали заметно больше места. После замены стандартного парсера в C время обработки строки на смешанных данных снизилось с 67 до 19 нс — против 41–46 нс у Rust.

AI-обработка оригинала Simon Willison; редакция Hamidun News
Саймон Уиллисон с Claude ускорил разбор чисел в SQLite с 67 до 19 нс
Источник: Simon Willison. Коллаж: Hamidun News.
Слушать статью
Паспорт материала и цифры
ПараметрДанные
ПервоисточникSimon Willison ↗
Главный редактор
Ключевой факт #1Расширение на C занимало 14 КБ, варианты на Rust — 298 и 321 КБ.
Ключевой факт #2Замеры охватывали 2 млн строк; результат зависит от состава данных.
Ключевой факт #3Перед выбором языка проверьте, какая функция съедает время.

Выгрузили платежи в CSV, загрузили в SQLite, а в колонке с суммами лежит «-$1,234.56». Для человека это число, для базы — строка, которую нужно разобрать перед сложением и сортировкой. Саймон Уиллисон решил проверить, насколько сложно добавить для этого функцию parse_number(), и поручил Claude сравнить реализации на C и Rust.

Получился небольшой, но полезный инженерный эксперимент. Сначала Rust выиграл по скорости, а C — по размеру расширения. Затем Уиллисон попросил заменить функцию разбора числа в C, и расклад поменялся: на смешанных данных время обработки строки снизилось с 67 до 19 наносекунд. Практический смысл здесь — в том, как один конкретный участок кода меняет результат сравнения языков.

Одна SQL-функция вместо очистки в каждом запросе

Задача у parse_number() простая: убрать из строки запятые, знаки валют и процента, учесть начальный минус и вернуть числовое значение. Если разобрать строку нельзя, функция должна вернуть NULL. Такое поведение позволяет вынести повторяющуюся очистку в расширение SQLite и затем использовать результат в вычислениях.

Например, «-$1,234.56» после удаления доллара и разделителя тысяч превращается в -1234.56. Дальше это значение можно складывать с другими платежами или сортировать как число. Разработчику не приходится заново собирать цепочку строковых замен в каждом запросе.

С процентами правила стоит определить отдельно. В исходном запросе Уиллисон предложил удалять знак процента. Но для конкретного продукта нужно решить, означает ли «12.5%» число 12.5 или долю 0.125. От этого зависит правильность последующих вычислений. Сам по себе быстрый разбор строки такого решения за команду не принимает.

Почему Rust сначала оказался быстрее

Claude подготовил варианты расширения на C и с двумя библиотеками Rust: rusqlite и sqlite-loadable-rs. По данным Уиллисона, собранное расширение на C занимало 14 КБ. Варианты на Rust — 321 и 298 КБ соответственно. Для небольшой встраиваемой утилиты такая разница может иметь значение.

Однако первая версия на C проигрывала по скорости. На смешанных данных её дополнительная стоимость обработки составляла 67 нс на строку, тогда как варианты на Rust показывали 46 и 41 нс. Уиллисон связал разницу с разбором чисел: использованный в Rust механизм работал быстрее стандартной функции C strtod.

Следующий запрос к Claude был уже точечным: написать собственную функцию разбора десятичного числа на C, способную догнать или обойти Rust. После этой замены вариант на C показал 19 нс на смешанных данных, 16 нс на целых числах и 18 нс на десятичных дробях.

Для сравнения: на десятичных дробях исходная версия C требовала 106 нс, а варианты Rust — 55 и 47 нс. Все приведённые замеры относятся к эксперименту на двух миллионах строк. Речь идёт о дополнительной стоимости обработки строки, поэтому переносить эти цифры на время выполнения целого SQL-запроса напрямую нельзя.

Что проверить перед использованием

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

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

Уиллисон также попросил Claude оформить исследование и выложил результат в репозитории simonw/research. Для разработчика это отправная точка: повторить замеры на своей выгрузке, проверить корректность и только после этого выбирать реализацию. Claude в этой истории помог быстро пройти путь от идеи до нескольких измеренных вариантов; оценивать их пригодность всё равно приходится по требованиям конкретной системы.

Сюжет

Вопросы и ответы по материалу

Что известно по теме: одна SQL-функция вместо очистки в каждом запросе?

Задача у parse_number() простая: убрать из строки запятые, знаки валют и процента, учесть начальный минус и вернуть числовое значение. Если разобрать строку нельзя, функция должна вернуть NULL. Такое поведение позволяет вынести повторяющуюся очистку в расширение SQLite и затем использовать результат в вычислениях. Например, «-$1,234.56» после удаления доллара и разделителя тысяч превращается в -1234.56. Дальше это значение можно складывать с другими платежами или сортировать как число.

Что известно по теме: почему Rust сначала оказался быстрее?

Claude подготовил варианты расширения на C и с двумя библиотеками Rust: rusqlite и sqlite-loadable-rs. По данным Уиллисона, собранное расширение на C занимало 14 КБ. Варианты на Rust — 321 и 298 КБ соответственно. Для небольшой встраиваемой утилиты такая разница может иметь значение. Однако первая версия на C проигрывала по скорости. На смешанных данных её дополнительная стоимость обработки составляла 67 нс на строку, тогда как варианты на Rust показывали 46 и 41 нс.

Что известно по теме: что проверить перед использованием?

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

ЖХ
Жемал Хамидун — CPO Alpina Digital, продакт-менеджер AlpinaGPT. Делает AI-продукты с 2019 года. Hamidun News — pet project, который вырос в production-агрегатор с 6000+ читателей.
✦ Единое AI-пространство · Nomad

Протестируйте новые LLM и мультимодальные модели в одном окне

Платформа Nomad AI (nomadnet.ai) даёт прямой доступ к Claude Opus 5.5, GPT-6, Gemini 3.1, DeepSeek и автономным агентам без VPN, зарубежных карт и зоопарка подписок.

Открыть Nomad AI →Автономный Nomad Agent
Что вы думаете?
Загружаем комментарии…