↓Перейти к основному содержанию

Как я ускорил «1С:Предприятие» в 5000 раз, переписав всё на Common Lisp

··7 мин.

Как-то раз я записывал очередное видео для студентов об истории Unix. Должен отметить, студенты у меня непростые: прожженные 1С-ники с серьезным «синдромом утенка», заработанным при работе с Windows.

А ведь когда-то давно, в 2006 году, я и сам был таким. Но случайно установленный дистрибутив Linux открыл для меня совершенно иной мир - мир с богатой историей, пронизывающей компьютерные науки.

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

И вот, рассказывая о Unix way, подумал: «Стоп! Ведь это можно применить для связи 1С:Предприятия с любым кодом очень простым способом». Жаль, конечно, что способ неуниверсален: платформа на каждой ОС работает в этом моменте по-разному. Но собирать и устанавливать библиотеку для разных операционных систем куда затратнее, а уж тем более - тестировать.

На это 1-е апреля, я решил потратить немного времени записать этот ролик.

Выбор языков прогрммирования #

Выбор пал на три языка на которых мы будем писать и которые будем «дружить» с 1С:

  1. С
  2. JavaScript
  3. Common Lisp

Почему Си #

Си - фундамент всего, на нем можно написать самый быстрый алгоритм. К тому же, он прост, но просто он со звездочкой.

Почему JavaScript #

В V8 Google влил огромное количество средств, что и сделало этот скриптовый язык самым быстрым на текущий момент. А TypeScript сегодня, на мой взгляд, язык для бизнес-приложений номер один. Тут мог бы быть и Python, но я выбрал JS.

Почему Common Lisp #

Потому что мне так захотелось. Если серьезно, язык сегодня маргинальный дедушка, но многое новое, как известно, хорошо забытое старое. Посмотрите, что мы будем делать, на чем это еще можно показать? Обычно говоря про Lisp, говорят про s-выражения, гомоиконичность, вытекающие из всего этого макросы. Макросы мы сегодня трогать не будем, это очень сложная тема. Поскольку этот механизм языка часто ругают, я останавлюсь на этом моменте, он интересен. Трогать в видео не будем, нужно пару месяцев чтобы научиться использовть этот иструмент.

Макросы #

Люблю макросы. Напишите побольше макросов и вас никогда не уволят.

Я могу лишь рассказать как и почему полюбил этот иструмент.

Макросы это просто, макрос - это код, который генерирует код. Жаль языков которые это нормально поддерживают немного. Интересно что им для этого необязательно обладать гомоиконичностью. Есть язык, в котором я использую их постоянно, вернее, во многом из-за них его и выбрал. Еще я применяю его, поскольку он один из немногих компилируется не в LLVM, а в Си. То есть, если автор его забросит, я смогу очень долго использовать компилятор он не перестанет работать.

Почему же мне так нравятся макросы. Все потому, что мне очень не нравится писать тривиальный, повторяющийся код. У меня есть внутреннее приложение, такая смесь CRM + Билинг. Переводя на язык 1С штук 8 справочников, 3 документа. Когда-то давно он был написан на React, использовался Refine+Supabase. Такой класический сетап для стартапа, быстро, просто, понятно. Все было прикольно, кроме размера бандала в 3+ мегабайта.

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

Если знакомлюсь с какой-то новой, модной веб-технологией, фреймворком или библиотекой, то беру и пишу этот биллинг снова, чтобы пощупать технологию на практике. Так я переписывал его много раз. Потом фронтенд остался на Vue + Quasar, а на бэкенде постоянно менял различные TS/JS-библиотеки. Там был Nuxt.js, потом Hono + Drizzle ORM. Устав от вечной беты Drizzle, я заменил его на Kysely. И было хорошо. И писать было прикольно и приятно.

Кочевать по JS-библиотекам надоело. На Python у меня когда-то был коммерческий сервис по раскрутке Instagram-аккаунтов. Это было приложение для ПК на Python + Qt, бэк на Starlette, плюс много криптографии (бэкенд, по сути, выполнял роль сервера лицензий). В 2022 году всё заблокировали, международные переводы ходить перестали, и проект канул в лету.

В целом, переписывать на Python было неинтересно. Я подумал про Go: стильно, модно, молодежно, много вакансий, «PHP XXI века». Однако кода получилось очень и очень много, намного больше, чем в TS-версии. «Печалька», - подумал я и закопал эту реализацию.

Как же быть? Хочется язык с компилятором, скоростью Си и объемом кода как на TS. Вероятно, остается только выть на Луну?

Прошло много времени, и как-то раз я просматривал один далеко не мейнстримный язык, не корпоративный проект, а во многом игрушку автора. Сначала мне это показалось ерундой: несерьезно, инструменты сырые, отладчика нет. И тут я увидел макросы. На этапе компиляции можно манипулировать AST-деревом как угодно. Я как раз в тот момент недавно написал обфускатор кода для 1С. И там использовал парсер для создания AST, манипулирования им и генерации итогового, запутанного кода. И я подумал: «Чудно, звезды сложились!» Ведь что такое бэкенд веб-приложения? Входные данные -> Валидация -> Middleware -> Бизнес-логика -> Выходные данные. А интересует меня лишь бизнес-логика. Пусть остальное генерят макросы.

Сказано - сделано. Написал DSL, похожий на TS-Hono. Немного кривенький, но я первый раз делал свой фреймворк, сам того не понимая. И вот мои три тысячи строк на DSL разворачиваются при компиляции в 30–35 тысяч строк на Nim. Да, забыл сказать: язык, который мне зашел, - это Nim. В нем много недостатков, но есть и интересные моменты, макросы - один из таких.

К чему я веду: путь к чему-то стоящему бывает извилистым. Иногда человек не владеет темой либо устремления у него другие, и он говорит: «Макросы - это плохо». Представьте команду из 50 человек в отделе корпорации. Чего они там понапишут? Это же ужас!

Я не хочу работать в условных Яндексе, OZON или Google. Я хочу создавать свои маленькие, прикольные продукты небольшими силами. Мне нравятся инструменты, позволяющие делать это быстро. Мне нравятся технологии, не требующие развесистых IDE на Java, предпочитаю Vim или, в крайнем случае, VS Code (хотя и он разжирел в последнее время). Часто рабочий процесс выглядит как-то так:

Страшно? Не пугайтесь, для клиентов я пишу на чем-то мейнстримном, в основном на TS, Python, Go. Ах да, бывает еще Pascal + Lazarus, когда ваяю GUI для ПК.

Но если вы решите освоить макросы и потратите 2–3 месяца на их изучение, в вашем арсенале появится супероружие. Написать макрос на порядок сложнее, чем обычный код (если это, конечно, не Hello World). Если он потом часто используется, то сэкономит вам массу времени. Не каждую задачу стоит решать с помощью макроса, но как только звезды сойдутся (подходящая задача + нужный инструмент), вот тогда и приходит понимание.

LLM - скажите вы #

Сложная тема, инструмент можно использовать по-разному. Я в своей работе использую LLM, но для примеров, экспериментов и обучения. Решения определенных «затупов». Но мне нравится писать код. А кто-то использует так:

Инструмент новый, идет наработка методов применения :-)

Один инструмент другому не мешает. Активно экспериментирую с нейросетями llama.cpp, stable-diffusion.cpp и koboldcpp. Удивительные технологии, есть интересные задумки, но так мы отклонимся от темы.

Алгоритмы и скорость #

Пример который мы разберем в видео, пример из реальной практики. Алгоритм реально используется в обмене данными между УНФ и БП, так что перед нами не абстрактная академическая задача, а сугубо практический кейс.

Условия задачи: Есть последовательность чисел X1, X2, X3, Xn и некая сумма Y. Как вычислить, какие числа из последовательности образуют сумму Y?

Эта задача известна как «Задача о сумме подмножества». Это NP-полная задача. Давайте попробуем решить ее методом полного перебора вариантов.

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

Результаты #

Можно долго говорить, просто возьмите чашку кофе, включите это видео и всё увидите сами.

Это видео на YouTube

Вы убедитесь, что мы улучшили быстродействие системы в «1С:Предприятии» в 5000 раз (а если внимательно посмотрите видео - увидите, что более чем в 7000 раз).

Можно сказать, что это какой-то «костыль». Но не спешите, хорошо подумайте - возможно, вы найдете этой методике достойное применение.

Если у вас есть вопросы, можете заполнить форму на главной странице. Исходные коды к видео доступны в репозитории.