Теперь у меня есть 2 важных примера, показывающих следующее время выполнения:
Java C++ FileSize Slowdown C++/Java
Пример 1: 85 с 533 с 2528699 6,2x Пример 2: 64 с 246 с 1031993 3,8x
Я уверен, что у моей грамматики есть проблемы (отдельная проблема, которую я начинаю решать), но что может быть возможной причиной медленности C++ по сравнению с реализацией Java? Весь код C++ (среда выполнения Java, сгенерированный синтаксический анализатор) компилируется с -O2 на машине Linux. Та же машина, та же грамматика, использовались те же файлы примеров. Я удостоверился, что сравниваю только время разбора. В любом случае ходьба по AST занимает 1 секунду.
Спасибо Ален
Я не могу в своем приложении, мне нужно обрабатывать файлы "холодно", мне нужно запускать новый парсер для каждого файла. Вы хотите сказать, что разминка в реализации на C++ тяжелее, чем в реализации на Java? Как вы объясняете разницу?
Позвольте мне добавить некоторую точность: в одном и том же исполнении (во время выполнения) я запускаю несколько потоков, которые анализируют биты и фрагменты файлов, я создаю и удаляю экземпляры лексеров и парсеров, но я предполагаю, что обучение кэшируется в каком-то глобальном (статическом) структура данных и не зависит от парсеров? Я предварительно компилирую некоторые большие файлы (пакеты) в одном потоке и сохраняю AST на диске, это примеры, на которые я указываю, когда я это делаю, он находится в другой среде выполнения, поэтому каждый запускается холодно. Здесь я вижу более резкую разницу между синтаксическим анализатором C++ и Java.
Да, разминка требуется для создания некоторых общих статических структур (DFA с конфигурациями ATN). Это требует больше времени на C++ из-за того, что требуется shared_ptr
, который относительно медленный. После кэширования данных вы можете создавать и удалять столько парсеров, сколько захотите. Все они используют эти общие данные.
Думаю, нам придется дождаться C++ 20: open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4162.pdf
У меня есть более серьезный вопрос: что послужило причиной статичности кеша? Почему бы не сделать его объектом, передаваемым анализаторам? и вообще не используйте shared_ptr, сделайте систему действительно независимой от потоков.
В моем случае каждый поток анализирует множество файлов, но я сначала вычисляю балансировку нагрузки по размеру файла (и / или разбиваю его на фрагменты), что в значительной степени гарантирует, что все потоки завершатся почти одновременно. В потоке я вижу полезность совместного использования кеша. Но между потоком, не совсем (Может, на память). Что нужно для такого изменения?
Кроме того, есть ли способ сохранить / восстановить DFA?
Вы запускали этап синтаксического анализа хотя бы два раза подряд? Есть фаза прогрева, которая значительно медленнее, чем последующие прогоны синтаксического анализа.