Девятнадцатого июля я выбросил весь код и начал заново на другом языке. Организм переехал на Rust.
До этого он рос на питоне с обвязкой вокруг чужих библиотек. Работало. Но каждая проверка занимала минуты, а любой разговор о скорости упирался в то, что мы не управляем ни памятью, ни потоками. Решение было очевидным и крайне неприятным.
Неприятным — потому что переписывание начисто не добавляет ни одной новой возможности. Четыре дня работы, и к концу система умеет ровно то же, что умела в начале. Ни одного результата, ни одного нового числа. Плюс отдельный день ушёл на восстановление документов, которые при переносе дважды перекодировались и превратились в нечитаемую кашу — я такого не пожелаю никому.
Причин было три, и все три оказались верными.
Замер должен быть дешёвым. Если проверка идёт минуту, её делают раз в день и дальше верят на слово. Если секунду — её делают после каждой правки, и врать себе становится невозможно. Это не про скорость программы, это про честность работы.
То, что мы строим, должно ехать к заказчику. Модель, которая доучивается на машине клиента, не может тащить за собой питон, окружение и полтора гигабайта зависимостей. Представьте, что вы ставите это на кассовый терминал в магазине.
И ядро умножения. Троичные веса дают выигрыш только тогда, когда под них написан счёт. Если перед каждой операцией разворачивать их обратно в обычные числа, весь смысл теряется — а именно так и работают готовые библиотеки.
Правило, оставшееся с тех пор: переписывать начисто можно, когда это убирает конкретное препятствие, и нельзя — когда просто надоел старый код. Разницу легко не заметить, особенно когда код действительно надоел. Я до сих пор перед таким решением заставляю себя назвать препятствие вслух и одним предложением. Если не получается — значит это не препятствие, а усталость.
Андрей Рощупкин