Skip to content

crypto hash, hmac and cipher ops could be 2x-3x faster for "one-shot" small buffers #26748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jorangreef opened this issue Mar 18, 2019 · 7 comments
Labels
crypto Issues and PRs related to the crypto subsystem. feature request Issues that request new features to be added to Node.js. performance Issues and PRs related to the performance of Node.js. stale

Comments

@jorangreef
Copy link
Contributor

@ronomon/crypto-async recently added support for synchronous hash, hmac and cipher methods.

In the process, we noticed that Node's crypto equivalents are significantly slower than expected, partly because of calling back and forth into C++ multiple times, i.e. for initialization, updating and finalizing.

These calls add up to considerable overhead, on the order of a few hundred ns per call, which is especially noticeable for small buffers less than 1KB.

For use-cases which only need to hash a single small buffer, i.e. in "one shot", it should be possible to improve performance by 2x or even by as much as 3x, by making a single call into C++ (and by removing other overhead, more on this below).

Of course, not everyone calls update() only once, or hashes or encrypts only small buffers, but I think this is probably representative of a large proportion of use-cases, especially for hashing:

crypto.createHash('sha256').update(buffer).digest()

If we could make this use-case 2x to 3x faster (as in less latency) that should be worth doing.

How could this be done?

I think there are at least two approaches:

  1. Firstly, while the current interface must support the existing streams interface, Node could possibly do something transparently under the hood, at least for hashes, by batching calls to C++ for initialize, update and finalize. For example, for a hash, there's no need for Node to do anything when the hash is instantiated (except for error handling, checking for algorithm support etc), and no need to do anything for updates. Node could effectively wait until update() is called a second time before calling into C++, or until digest() is called. More generally, buffers could be batched until a high-watermark is reached, to amortize calls into C++. For ciphers, of course, this won't be possible, because the user expects update() to return something (and we need to support AEAD ciphers which are more complex in terms of interface). This approach won't entirely close the gap with @ronomon/crypto-async, because of the overhead of streams for small buffers.

  2. Secondly, it might be simpler and more optimal to introduce lightweight one-shot methods, to avoid the expense of streams for small buffers, which is significantly costly for small buffers, in addition to the multiple round-trips into C++. For example: hash(algorithm, buffer, [offset, size], [callback]). Introducing one-shot methods would also be a natural opportunity to add async multi-core support for large buffers (> 64KB), which would give a huge concurrent throughput boost for large buffers, and eliminate blocking in the event loop.

These are just some ideas, in case anyone is interested to run with this.

@sam-github
Copy link
Contributor

  1. is the typical crypto lib approach, note it is progress for sign already: crypto: add crypto.sign() and crypto.verify() #26611

@bnoordhuis bnoordhuis added crypto Issues and PRs related to the crypto subsystem. feature request Issues that request new features to be added to Node.js. performance Issues and PRs related to the performance of Node.js. labels Mar 19, 2019
@github-actions

This comment was marked as outdated.

@github-actions github-actions bot added the stale label Feb 26, 2022
tniessen added a commit to tniessen/node that referenced this issue Mar 6, 2022
@tniessen
Copy link
Member

tniessen commented Mar 6, 2022

Looks like this might be useful for hashing. #42233.

@tniessen tniessen removed the stale label Mar 6, 2022
@targos targos moved this to Pending Triage in Node.js feature requests Apr 4, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Sep 3, 2022

There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment.

For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot added the stale label Sep 3, 2022
@tniessen tniessen removed the stale label Sep 3, 2022
@tniessen
Copy link
Member

tniessen commented Sep 3, 2022

We might still want to pursue this, removing stale label.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2023

There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment.

For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot added the stale label Mar 3, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Apr 3, 2023

There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment.

For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 3, 2023
@targos targos moved this from Pending Triage to Stale in Node.js feature requests Apr 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Issues and PRs related to the crypto subsystem. feature request Issues that request new features to be added to Node.js. performance Issues and PRs related to the performance of Node.js. stale
Projects
None yet
Development

No branches or pull requests

4 participants