Бенчмаркинг generate и verify

Производительность операций генерации хэша и проверки пароля является критическим параметром при выборе алгоритма хранения паролей. В контексте библиотеки password-hash в JavaScript основное внимание уделяется двум функциям: generate (создание хэша) и verify (проверка пароля). Эти операции обладают разной вычислительной сложностью и по-разному влияют на нагрузку сервера.


Архитектурные особенности операций generate и verify

generate (хэширование пароля)

Операция генерации хэша включает:

  • генерацию соли (salt);
  • применение криптографического алгоритма;
  • многократные итерации преобразования входной строки;
  • формирование итоговой строки хэша с метаданными.

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

Время выполнения зависит от:

  • сложности алгоритма;
  • количества итераций;
  • длины соли;
  • аппаратных характеристик CPU.

verify (проверка пароля)

Операция проверки включает:

  • извлечение параметров из сохранённого хэша;
  • повторное выполнение алгоритма generate с теми же параметрами;
  • сравнение полученного результата с сохранённым значением.

Несмотря на кажущуюся простоту, verify обычно выполняет тот же объём вычислений, что и generate, поскольку требуется полное повторение криптографического процесса.


Методология бенчмаркинга

Основные метрики

При оценке производительности используются следующие показатели:

  • Latency (задержка) — время выполнения одной операции;
  • Throughput (пропускная способность) — количество операций в секунду;
  • CPU usage (нагрузка на процессор);
  • Stability (разброс значений) — отклонение времени выполнения.

Инструменты измерения

В экосистеме JavaScript применяются:

  • process.hrtime.bigint() — высокоточное измерение времени в Node.js;
  • Benchmark.js — библиотека для статистически корректных замеров;
  • встроенные профилировщики Node.js (--prof, --inspect);
  • performance API (perf_hooks).

Бенчмаркинг generate

Базовый подход

Типовой тест генерации хэша:

import passwordHash from 'password-hash';

function measureGenerate(password, iterations = 100) {
  const start = process.hrtime.bigint();

  for (let i = 0; i < iterations; i++) {
    passwordHash.generate(password);
  }

  const end = process.hrtime.bigint();
  return Number(end - start) / 1e6; // миллисекунды
}

Интерпретация результатов

При анализе generate важно учитывать:

  • рост времени при увеличении итераций алгоритма;
  • влияние конкурентной нагрузки;
  • деградацию производительности при высокой частоте вызовов.

Типичные характеристики:

  • bcrypt-подобные алгоритмы: 50–500 мс на операцию;
  • более лёгкие схемы: 1–10 мс;
  • усиленные конфигурации (high cost factor): >500 мс.

Масштабирование нагрузки

При увеличении количества одновременных операций наблюдается:

  • линейное или сублинейное ухудшение производительности;
  • насыщение CPU;
  • рост очереди event loop в Node.js.

Особенно важно учитывать, что generate является CPU-bound операцией и не освобождает поток выполнения.


Бенчмаркинг verify

Базовая реализация теста

import passwordHash from 'password-hash';

const hash = passwordHash.generate('test-password');

function measureVerify(hash, password, iterations = 100) {
  const start = process.hrtime.bigint();

  for (let i = 0; i < iterations; i++) {
    passwordHash.verify(password, hash);
  }

  const end = process.hrtime.bigint();
  return Number(end - start) / 1e6;
}

Особенности поведения verify

Несмотря на кажущуюся простоту операции, verify:

  • повторяет полный процесс генерации;
  • извлекает параметры алгоритма из строки хэша;
  • выполняет идентичное число итераций, что и generate.

Поэтому производительность verify практически равна generate, с небольшими отклонениями в сторону меньшего времени из-за отсутствия генерации соли.


Характерные наблюдения

  • verify часто используется чаще, чем generate (аутентификация vs регистрация);
  • нагрузка на систему при массовом логине может превышать нагрузку регистрации;
  • оптимизация verify критична для высоконагруженных систем.

Сравнительный анализ generate и verify

Временные характеристики

Операция Среднее время CPU нагрузка Особенности
generate выше высокая включает генерацию соли
verify сопоставимо высокая повторяет вычисления

Выводы из профилирования

  1. Оба процесса являются CPU-интенсивными.
  2. Разница между generate и verify минимальна в большинстве алгоритмов.
  3. Основное отличие — наличие генерации соли в generate.
  4. Узким местом системы является не verify, а суммарная частота операций.

Поведение при нагрузочном тестировании

Однопоточное выполнение

В однопоточном режиме наблюдается:

  • стабильное время выполнения;
  • линейная деградация при увеличении cost factor;
  • предсказуемость результатов.

Многопоточное выполнение

При параллельных вызовах:

  • возрастает конкуренция за CPU;
  • увеличивается latency;
  • возможны скачки времени выполнения из-за планировщика задач Node.js.

Event Loop и блокировки

Обе операции блокируют event loop, что приводит к:

  • задержкам обработки HTTP-запросов;
  • снижению throughput сервера;
  • росту очередей входящих соединений.

Влияние параметров алгоритма на бенчмарки

Cost factor

Основной параметр, определяющий сложность:

  • увеличение cost factor в 2 раза ≈ экспоненциальный рост времени;
  • оптимальный баланс зависит от требований к безопасности и производительности.

Длина соли

Влияет незначительно, но:

  • увеличивает размер памяти;
  • влияет на сериализацию хэша;
  • минимально отражается на времени generate.

Тип алгоритма

Разные реализации дают различную производительность:

  • bcrypt — средняя скорость, высокая безопасность;
  • scrypt — более ресурсоёмкий (memory-hard);
  • PBKDF2 — быстрее, но менее устойчив к GPU-атакам.

Практическая интерпретация результатов бенчмарков

При анализе важно учитывать не только абсолютные значения, но и:

  • стабильность распределения времени;
  • поведение при пиковых нагрузках;
  • деградацию при масштабировании пользователей;
  • влияние одновременных verify-запросов на систему.

Типичные ошибки при измерении производительности

  • использование Date.now() вместо высокоточных таймеров;
  • недостаточное количество итераций;
  • отсутствие прогрева (warm-up phase);
  • игнорирование JIT-оптимизаций V8;
  • выполнение тестов в фоне с нестабильной нагрузкой.

Интерпретация результатов в реальных системах

В продакшене бенчмарки generate и verify применяются для:

  • расчёта максимального числа одновременных логинов;
  • выбора параметров cost factor;
  • планирования горизонтального масштабирования;
  • оценки необходимости offloading (worker threads, отдельные сервисы).

Поведение при масштабировании инфраструктуры

При увеличении числа инстансов:

  • общая пропускная способность растёт линейно;
  • latency отдельной операции остаётся стабильным;
  • verify становится основным фактором нагрузки при высоком трафике авторизации.

Связь с безопасностью

Увеличение времени generate и verify:

  • повышает устойчивость к brute-force атакам;
  • снижает эффективность GPU-ускоренного перебора;
  • увеличивает стоимость атаки для злоумышленника.

Однако чрезмерное увеличение cost factor приводит к:

  • деградации UX;
  • перегрузке серверов;
  • росту затрат на инфраструктуру.

Интерпретация профилировщиков Node.js

При анализе CPU flamegraph обычно наблюдается:

  • доминирование криптографических функций;
  • отсутствие I/O узких мест;
  • линейное распределение нагрузки между generate и verify.

Профилирование подтверждает, что оптимизация должна идти не на уровне JavaScript-кода, а на уровне алгоритмических параметров и архитектуры аутентификации.