Comments 6
В очередной раз стало интересно: а как у вас с разбором вещей типа цепочки ифов, после автогенераторов?
if (test1) { ... } else
if (test2) { ... } else
... (100500 cases)
Графы в памяти не разбухают? Анализатор не начинает тормозить как Гомер после пива? :D
У нас периодически обнаруживаются просадки по памяти, которые приходится оперативно устранять, но с ифами такого не было. Да и в целом именно с памятью там вряд ли проблемы должны быть, от любых других операций условия не отличаются.
С производительностью в теории могут, но ещё не встречал (если забыть об описанном в статье случае). Хотя на огромных автогенерённых файлах тестировать как-то не приходилось. Может, зря.
Когда о потенциальных проблемах думал, прикидывал, что можно просто A* для игнорирования всяких неважных рёбер использовать. Плюс уже есть кэш для внутрипроцедурного обхода, его тоже на такие случаи можно расширить при необходимости.
Просто краевые случаи на которых распухают ASTы это самые тривиальные вещи -- (((((((((((((((((((((((((((((((((((((((((((2+2))))))))))))))))))))))))))))))))))))))
, if() else if() else
и так далее -- когда бинарность дерева начинает кусаться. И сколько бы не пытался их обойти {я собственноручно грамматики многократно перепиливал чтоб 2+2+2+2+2
сворачивалось в ('+', [2, 2, 2, 2, ...])
вместо ('+', 2, ('+', 2, ('+', 2, ('+', ...))))
} -- а всё равно где-нибудь встретишь ужасы типа цепочки в 100500 ифов, и по очереди то out-of-mem, то out-of-stack, то просто на бэктрекинге на минуты зависает из-за квадратичного нежданчика.
И да, встречается в живом коде, не только синтетика.
А если интересно синтетику на которой можно пошатать деревья разбора и обхода их -- советую подглядеть в глубинные тесты у ZetaSQL: этим подходом я очень много яблок с деревьев стряс, заодно убедил избавиться от javacc :))
Интересно, спасибо за ссылку.
Что до AST, то с ним у нас больших проблем нет. Да, потребление памяти на больших проектах внушительное, но даже на гигантах типа Idea на всё про всё хватит просто мощной машины разработчика, а анализ частенько оказывается на удивление быстрым.
При этом оптимизаций в дереве у нас не так много, иначе было бы сильно сложнее искать опечатки для GA диагностик, да и польза не всегда очевидна. Из указанного только полностью от скобочек избавляемся.
Я так понимаю, всё же профиль "запуск локальный и для кода, который и так разработчик обрабатывает" предполагает, что если только что-то внезапно совсем плохо не окажется, то обработка должна быть на уровне времени работы компилятора, то есть "медленно, но терпимо".
Я помню игрался с триальной версией PVS на большом проекте -- время проверки было где-то 60% от времени полной компиляции. То есть можно было сходить за кофе -- но не на обед :)
Ну, в случае с java анализатором примерно так и есть. Долго анализируются только огромные проекты, которые и скомпилируются очень не сразу. Но рост времени анализа всё-таки напрямую связан с количеством и глубиной диагностических правил, так что анализатору простительна сравнительно более долгая работа.
Поиск потенциальных уязвимостей в коде, часть 2: практика