Бенчмаркинг операций Web Crypto API требует учета асинхронной природы API, влияния окружения выполнения (браузер, версия движка, аппаратное ускорение), а также особенностей работы с бинарными данными в JavaScript. Любые измерения должны опираться не только на время выполнения отдельных вызовов, но и на устойчивые метрики пропускной способности, стабильность результатов и поведение под нагрузкой.
Основной инструмент измерения в браузере —
performance.now(), обеспечивающий высокоточное время в
миллисекундах с дробной частью. При этом важно учитывать, что единичные
измерения почти всегда нерепрезентативны из-за JIT-компиляции,
кэширования и фоновых процессов.
Web Crypto API построен вокруг SubtleCrypto, и все
операции выполняются асинхронно через промисы:
crypto.subtle.digestcrypto.subtle.encryptcrypto.subtle.decryptcrypto.subtle.signcrypto.subtle.verifycrypto.subtle.generateKeycrypto.subtle.importKeycrypto.subtle.exportKeyИзмерение должно учитывать:
Типовой шаблон измерения операции выглядит следующим образом:
async function benchmark(fn, iterations = 1000) {
// прогрев
for (let i = 0; i < 50; i++) {
await fn();
}
const start = performance.now();
for (let i = 0; i < iterations; i++) {
await fn();
}
const end = performance.now();
return {
iterations,
totalTime: end - start,
opsPerSecond: (iterations / (end - start)) * 1000
};
}
Такой подход позволяет получить усредненную пропускную способность, а не случайные всплески производительности.
Операция crypto.subtle.digest часто используется как
базовый ориентир производительности Web Crypto API.
Пример SHA-256:
const data = new TextEncoder().encode("benchmark data".repeat(1000));
async function hash() {
return crypto.subtle.digest("SHA-256", data);
}
Особенности измерения:
Uint8ArrayПри увеличении размера входа наблюдается почти линейное масштабирование времени, что удобно для оценки пропускной способности в MB/s.
Для AES-GCM:
const key = await crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const data = crypto.getRandomValues(new Uint8Array(1024 * 1024));
async function encryptOp() {
return crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
key,
data
);
}
При измерении важно разделять:
Отдельное измерение каждого этапа позволяет выявить узкие места.
RSA и ECDSA значительно дороже по вычислениям, поэтому количество итераций обычно меньше.
Пример ECDSA подписи:
const keyPair = await crypto.subtle.generateKey(
{
name: "ECDSA",
namedCurve: "P-256"
},
true,
["sign", "verify"]
);
const data = new TextEncoder().encode("message");
async function signOp() {
return crypto.subtle.sign(
{ name: "ECDSA", hash: "SHA-256" },
keyPair.privateKey,
data
);
}
При бенчмаркинге асимметричных алгоритмов важно учитывать:
Практически все операции Web Crypto API масштабируются по-разному:
Для корректного анализа используется серия тестов:
const sizes = [16, 256, 4096, 65536, 1048576];
for (const size of sizes) {
const data = crypto.getRandomValues(new Uint8Array(size));
// измерение операции
}
Критическая ошибка в бенчмарках — включение лишних затрат:
Uint8Array внутри тестаTextEncoder в каждой итерацииПравильный подход:
Хотя Web Crypto API выглядит как обычный Promise-based API, фактическое выполнение часто происходит вне основного потока (иногда с использованием нативных ускорений).
Это приводит к эффектам:
Поэтому измерение должно учитывать “плато производительности”, а не отдельные вызовы.
Для более точных результатов используется Web Worker:
// worker.js
self.onmess age = async (e) => {
const { data } = e.data;
const start = performance.now();
for (let i = 0; i < 1000; i++) {
await crypto.subtle.digest("SHA-256", data);
}
const end = performance.now();
self.postMessage({ time: end - start });
};
Причины использования воркеров:
При анализе Web Crypto API используются несколько ключевых метрик:
Производительность сильно зависит от:
Одни и те же тесты могут отличаться в разы на разных устройствах.
Корректный бенчмарк всегда строится как набор независимых тестов:
Сравнение должно учитывать не только скорость, но и масштабируемость при увеличении объема данных.
Полученные значения нельзя рассматривать изолированно. Важны:
Резкие колебания обычно указывают на влияние внешних факторов: JIT-компиляции, фоновых задач или особенностей планировщика потоков браузера.