New issue
Advanced search Search tips

Issue 701188 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 435790
Owner: ----
Closed: Mar 2017
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug



Sign in to add a comment

WebCrypto AES-CBC performance is slow compared to third-party JS libraries

Reported by kyle.spe...@gmail.com, Mar 14 2017

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

Steps to reproduce the problem:
1. Download benchmarks.html test case that is attached.
2. Open dev tools.
3. Click encrypt/decrypt buttons to compare benchmarks.

What is the expected behavior?
WebCrypto to be fastest benchmark.

What went wrong?
I am evaluating how WebCrypto performance compares to popular third-party crypto libraries SJCL and Forge. I would expect WebCrypto to be much faster since it is a native browser implementation.

I have implemented the following tests using Benchmark.js to test key derivation (PBKDF2-SHA256), encrypt (AES-CBC), and decrypt (AES-CBC). These tests show WebCrypto to be significantly slower than both SJCL and Forge for encrypt/decrypt.

==================

Starting test: Encrypt
SJCL x 42,618 ops/sec ±1.43% (60 runs sampled)
Forge x 76,653 ops/sec ±1.76% (60 runs sampled)
WebCrypto x 18,011 ops/sec ±5.16% (47 runs sampled)
Fastest is Forge

Starting test: Decrypt
SJCL x 79,352 ops/sec ±2.51% (50 runs sampled)
Forge x 154,463 ops/sec ±2.12% (61 runs sampled)
WebCrypto x 22,368 ops/sec ±4.08% (53 runs sampled)
Fastest is Forge

==================

I suspect that this is due to AES invocation overhead since running the same benchmarks with larger payloads shows WebCrypto to be faster, however, small payloads (as shown in the benchmarks attached) cause WebCrypto to be slower than popular third-party libraries by a very large factor.

Did this work before? N/A 

Does this work in other browsers? No
 Testing in Firefox latest stable also produces similar results.

Chrome version: 56.0.2924.87  Channel: stable
OS Version: 10.0
Flash Version: 

Maybe I am using the API incorrectly?
 
benchmarks.html
11.5 KB View Download
For convenience, there is also a fiddle of the benchmarks here: https://jsfiddle.net/kspearrin/1Lzvpzkz/
Summary: WebCrypto AES-CBC performance is slow compared to third-party JS libraries (was: WebCrypto AES-CBC performance is slow compared to third-party libraries)
Note: It is expected that there will be slowness compared to a raw JS implementation, due to JS getting heavily JIT'ed in ways that make it insecure for crypto - which is part of the core reason for WebCrypto's existence, which is the inability to make reasoned guarantees about the timing safety of the crypto.

There is also expected overheads for smaller payloads due to (safely) expanding the key schedule, which may be amortized over larger blobs - this is both a cost of correctness and the cost of the optimizations involved.

Finally, there is a cost involved with the invocation overhead, due to WebCrypto requiring a thread transition as currently implemented, due to the need to not block the event loop from processing other events, whereas JS can be paused/interrupted arbitrarily during execution by the engine. This could be improved if we synchronously completed things on Workers, but as discussed in the W3C Web Crypto WG (before it shut down), that itself is problematic from a compat perspective.

All of these things contribute to 'correct' vs 'fast', which is a common trade-off in security sensitive, timing-dependent operations.

(This isn't to excuse looking for optimizations where they exist, but also to make sure to set realistic fundamental expectations)

Comment 3 by eroman@chromium.org, Mar 14 2017

Mergedinto: 435790
Status: Duplicate (was: Unconfirmed)
Thanks for the benchmark!

I believe the biggest difference in performance seen here on small operations is due to the asynchronous API + Chrome's multi-threaded implementation.

These computationally small tasks end up copying the data buffers and posting to another thread, waiting to be scheduled there, and then again waiting to be scheduled when posted back to JS thread.

There are some other internal costs like needing to make an extra copy of data buffers in case algorithm normalization mutates them , and delivery of the result through a Promise can also hit scheduling bottlenecks.

Issue 435790 has a suggested optimization that should speed up this particular benchmark (I agree these results are disappointing) so I will tentatively dupe against that on the assumption that the performance problems you saw here were the scheduling ones.

For high performance Web Crypto I think we want a synchronous mode for Web Workers, as that solves both the scheduling overheads, as well as the lack of parallelism controls (raised in other bugs as a limiting factor for throughput).

Sign in to add a comment