Pull to refresh

Comments 18

При сравнении SHA-256 была допущена неточность.

Для Node.js вы делаете await в цикле, а для GoLang wg.Wait(); после цикла. Если вы измеряете скорость параллельного вычисления, то имеет смысл в Node.js сделать с помощью Promise.all

Спасибо за интерес к статье и дельное замечание.
К счастью влияние на абсолютный результат - минимальны (перепроверил).

И в принципе логично, потому что CPU-bound работа идёт просто в том же потоке, но если бы модуль crypto имел асинхронные интерфейсы, то всё бы действительно выполнялось параллельно. А так async/await вешать на обычную функцию, пускай она и будет даже иметь обёртку в виде:

function hash(data, algo) {
  return new Promise(resolve => {
    resolve(crypto.createHash(algo).update(data).digest('hex'));
  });
}

Всё равно будет выполняться синхронно. Через node-gyp можно писать на C/C++ как раз модули, где и реализовать асинхронный интерфейс для функций хеширования (на npm даже вроде есть готовые пакеты).

Кстати, WASM - есть WASM, ему неважно на каком языке писали, поэтому у компилятора для Go на WASM тоже есть подводные камни.

Так что лучший перформанс можно получить, написав нативные модули к Node.js (например, с помощью node-gyp).

Да, готовые пакеты есть (скорее всего речь идет о crypto-async).
Что касается Go -> wasm, то с подводными камнями пока не знаком. Как раз для начала "раскопок" в этом направлении и была написана статья.

Если в 4 и 5 тестах убрать ненужный async/await, каковы будут результаты для js?

Различия незначительны. 1-2 мс что в одну, что в другую сторону.

Кайфанул при прочтении, большое спасибо :)

Второй "забег", очевидно, не стоит принимать во внимание - js там просто складывал два числа, а остальные предварительно приводили строку к числу.

4 и 5 - сравнение нативных реализаций, написанных скорее всего на плюсах. Это не сравнение языков.

Итого остается 1 и 3. Ну с первым всё понятно, нода рулит в io. А насчет третьего - может быть, оптимизирующий компилятор v8 недостаточно прогрел код?

Спасибо за отзыв.
Возможно ввел в заблуждение, но в Node.js тоже учитывалось приведение к числу.
Так же не хотел показать "сравнения языков". Скорее сравнение подходов по использованию Golang (как отдельный микросервис или wasm).
По поводу последнего ("прогретости") - вполне.

А почему не рассматривался 4-й вариант: написать Native Addon для Node.js использую https://nodejs.org/api/n-api.html#node-api ?

Даже если поблизости нет C или С++ программиста, то вроде бы в Go можно сделать библиотеку, экспортирующую функции в C стиле, и использовать их с Node-API

Спасибо за интересную мысль!

Не задумывался над такой возможностью именно в Go. Посмотрю в эту сторону.

а смысл? снизить нагрузку на ЦПУ?

Автор сделал ерунду. Первые два примера вообще ни о чем. А четвертый и пятый пример про хеш функции скорее всего сводится в вызову сишного кода под капотом. Только про фибоначи нормальный пример.

+1 Да и вообщевсе за ранее было понятно.

ИМХО, АПИ надо реализовывать на Go, фронты на NodeJS, все остальное от лукавого, либо легаси наследство.

Простите за оффтоп, но для себя открыл, что на m1 100000-е число Фибоначчи, считается в среднем за 74ms.

Методика замера:

const timeDiff = (begin, end) => (end - begin) / 1000000n;

const main = () => {
  const begin = process.hrtime.bigint();

  let num = 100000n
  let a = 1n, b = 0n, temp;
  while (num > 0n) {
    temp = a;
    a += b;
    b = temp;
    num -= 1n;
  }

  const end = process.hrtime.bigint();
  console.log(b, '\n');
  console.log('Время:', timeDiff(begin, end), ' ms.');
};
main();

Интересное исследование, пару месяцев назад делал аналогичное для Node.js+Rust WASM практически для тех же задач. Главная проблема с вызовом функций из WASM это оверхед при передаче/получении аргументов и результатов функций, поэтому задачи в стиле сложить два числа выполняются Node.js быстрее. В случае с хешом, Node.js под капотом использует плюсы и тут вряд-ли что-то можно оптимизировать.

Sign up to leave a comment.

Articles