slow key generation #1727
Description
As part of the benchmarking initiative, we have identified a first bottleneck in js-ipfs.
Adding a file to a local empty repo creates a new public/private key (see https://github.com/ipfs/benchmarks/blob/master/tests/local-add.js). This operation takes 3-6 seconds on our laptop, making the user experience on new repositories problematic. Also, it skews all the possible benchmarks, because it is hard to gain 3-6 seconds lost in this activity. During our call earlier this week, we talked about using a pre-generated certificate for benchmarking/improving the actual data transfer. However, this does not solve the problem for creating a new repository and new users.
We have conducted our analysis using node clinic. Here is a doctor visualization of that benchmark:
As it's evident, the event loop is blocking for a severe amount of time. We generated a flamegraph of the same activity:
As you can see, the vast majority of time is spent in the https://www.npmjs.com/package/keypair module. We can see two recommendations:
- Replace the usage of keypair with https://nodejs.org/dist/latest-v11.x/docs/api/crypto.html#crypto_crypto_generatekeypair_type_options_callback; it reduces the time taken to generate a key from 3+ seconds to 70ms. It is currently not compatible due to some format difference, but I think it could be fixed.
- investigate the feasibility of porting keypair to webassembly in some form (rust, C, etc...), using some already available library or writing one from scratch.
Note that approach 1 only works for Node.js, while 2 is essentially needed for browser environments.