Странная производительность Node.js - PullRequest
3 голосов
/ 15 мая 2019

Я написал большой алгоритм , который анализирует строку (5 МБ в длину, как проверено). После некоторых изменений я заметил значительное снижение производительности, примерно на 30% -35%, поэтому я начал отлаживать его с помощью различных измерений производительности и обнаружил нечто странное.

Оказывается, мой алгоритм резко замедлился после того, как я удалил следующую строку в начале алгоритма, которая была вызвана только один раз:

text.match(/\n/g);

Если я просто поставлю эту строку наверху алгоритма, даже не используя его результаты, производительность увеличится на 30-35%, а остальные изменения в алгоритме, похоже, не будут иметь никакого значения.

Кажется, что выполнение такой строки каким-то образом внутренне дает Node.js стимул для дальнейшей обработки строки, что я не могу объяснить или проанализировать дальше.

Затем я начал тестировать его в разных версиях Node.js и обнаружил, что это происходит в текущей версии 10.15.3, но в v4.x или v12.x происходит горячее обновление.

Такое огромное несоответствие и совершенно загадочное влияние на производительность, я не знаю, что с этим делать.

Кто-нибудь может пролить свет на то, почему такой дополнительный поиск в RegEx может внезапно повысить уровень Node.js? Или это как-то конкретно в моем случае?

UPDATE

Я зарегистрировал проблему для Node.js для этого .

1 Ответ

3 голосов
/ 15 мая 2019

В зависимости от того, как была создана строка в V8, она сохраняется либо в виде последовательного массива, либо в виде «среза» (двоичное дерево). Двоичное дерево гораздо менее дружественно к кешу, и его обход несколько раз приведет к значительному снижению производительности из-за остановок конвейера, вызванных пропаданием кеша.

Побочным эффектом ReGex match() в V8 был вызов String::Flatten. Это приведет к тому, что строка будет упорядочена в памяти. Этот побочный эффект, к сожалению, был удален в более поздней версии V8.

Узел 10 предоставляет новую функцию %FlattenString, которую можно использовать для явного секвенирования строки.

В качестве независимого от версии решения вы можете использовать модуль flatstr. В зависимости от версии V8 он либо вызывает %FlattenString(s) или Number(s) (полагаясь на побочный эффект).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...