Бенчмарки: сравнение rounds и времени выполнения

В bcrypt.js ключевой параметр производительности — cost factor (rounds). Он определяет, сколько итераций хэш-функции будет выполнено при генерации хэша пароля. Каждый дополнительный шаг увеличивает время вычисления экспоненциально.

Формально зависимость времени можно выразить так:

T ^{cost}

где cost — это значение rounds (обычно от 8 до 15+), а T — относительное время выполнения.

Важно учитывать, что bcrypt специально разработан как медленный алгоритм, чтобы усложнить brute-force атаки. Поэтому увеличение rounds всегда является компромиссом между безопасностью и производительностью.


Природа роста времени выполнения

Каждое увеличение cost на 1 удваивает вычислительную нагрузку. Это означает:

  • cost 8 → базовый уровень
  • cost 9 → примерно ×2 времени
  • cost 10 → примерно ×4 времени
  • cost 12 → примерно ×16 времени
  • cost 14 → примерно ×64 времени

Такой рост делает подбор паролей вычислительно дорогим даже для современных GPU-ферм.


Практическое измерение времени в Node.js

Для измерения производительности bcrypt.js используется простая схема бенчмарка:

import bcrypt from 'bcryptjs';

async function benchmark(cost) {
  const password = 'secure_password_123';
  const salt = bcrypt.genSaltSync(cost);

  const start = process.hrtime.bigint();
  bcrypt.hashSync(password, salt);
  const end = process.hrtime.bigint();

  return Number(end - start) / 1e6; // миллисекунды
}

(async () => {
  for (let cost = 8; cost <= 14; cost++) {
    const time = await benchmark(cost);
    console.log(`cost ${cost}: ${time.toFixed(2)} ms`);
  }
})();

Методика:

  • используется фиксированный пароль
  • синхронный режим исключает влияние event loop
  • измеряется чистое CPU-время через process.hrtime.bigint()

Типичные результаты на современном CPU

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

Cost Время хэширования
8 ~2–5 ms
9 ~4–10 ms
10 ~8–20 ms
11 ~15–40 ms
12 ~30–80 ms
13 ~60–160 ms
14 ~120–320 ms

При этом важно учитывать:

  • Node.js среда добавляет небольшие накладные расходы
  • синхронные вызовы блокируют event loop
  • асинхронная версия распределяет нагрузку лучше в production

Логарифмическая природа роста нагрузки

Рост времени можно представить как экспоненциальную функцию:

T(c) = T_0 ^{(c - c_0)}

где:

  • T(c) — время при cost = c
  • T_0 — базовое время при минимальном cost
  • c_0 — базовый уровень (например, 8)

Эта модель хорошо согласуется с реальными измерениями bcrypt.


Почему нельзя выбирать cost произвольно

Выбор rounds напрямую влияет на:

1. Безопасность

Чем выше cost, тем дороже атака перебором. При cost ≥ 12 brute-force становится практически нецелесообразным для большинства атакующих.

2. Производительность сервера

Каждая регистрация или смена пароля блокирует CPU на время хэширования.

3. Масштабируемость системы

При высокой нагрузке время хэширования становится узким местом.


Баланс между безопасностью и нагрузкой

На практике часто используют следующие диапазоны:

  • cost 8–10: тестовые окружения, низкая безопасность
  • cost 10–12: стандартные production-системы
  • cost 12–14: повышенные требования безопасности
  • cost 14+: специализированные системы с ограниченным числом операций

Сравнение синхронного и асинхронного выполнения

bcrypt.js предоставляет два подхода:

Синхронный вариант

  • блокирует event loop
  • подходит только для CLI или тестов
  • проще измерять производительность

Асинхронный вариант

  • не блокирует поток
  • использует libuv thread pool
  • предпочтителен в серверных приложениях

Разница особенно заметна при высоких cost:

  • cost 10: влияние минимальное
  • cost 12+: нагрузка распределяется, но latency увеличивается
  • cost 14+: требуется контроль очередей задач

Влияние аппаратного обеспечения

Производительность bcrypt зависит от:

  • архитектуры CPU (Intel vs ARM)
  • количества ядер (параллелизм через async)
  • тактовой частоты
  • наличия нагрузок на систему

GPU ускорение в bcrypt.js не применяется, так как алгоритм намеренно защищён от массового параллелизма.


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

Бенчмарки bcrypt нельзя рассматривать как линейную метрику производительности. Они используются для:

  • выбора безопасного cost
  • оценки нагрузки при регистрации пользователей
  • прогнозирования latency auth-системы
  • тестирования деградации производительности при росте базы пользователей

Главный вывод из измерений:

увеличение cost всегда улучшает безопасность, но делает операции входа и регистрации всё более дорогими по CPU, причём рост стоимости носит экспоненциальный характер.