-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
Performance Regression: tls.createSecurePair() Not Buffering Connections in v10 #20263
Comments
@nodejs/crypto |
Thanks for the extensive work prior to reporting! I’ll definitely take a look as soon as I have the time.
I’m assigning this to myself because I agree that the patch identified by @alexfernandez is by far the most likely cause here, but if somebody else wants to investigate I don’t want to stand in the way. :) |
Thanks for looking into it, @addaleax! Sure, we have considered migrating to If you run the sample script under Node.js v8 or v9 with Note: the |
Excellent bug report @alexfernandez - just saying it out loud in case it's not obvious. If you'd like to work on the PR and get guidance/help from @addaleax if/when you're having issues with it that's also something we're very much in favor of. The report itself shows an understanding of the code and indicates a capability to do so. Of course, this is not a request but an offer - you are in under no obligation or pressure to work on a PR. I'm just saying clearly that it's welcome :) |
Hmm... I'm also seeing a massive regression somewhere along the way in v9.x in the Edit: The regression landed in 9.7.0. Will report when I have more info. |
@addaleax Reverting 82c43ae fixes the regression I experienced above (unrelated to the other one) and actually yields a performance improvement to 3.2mb/s. Any thoughts? Edit: After testing some more, I think we need a C++ nextTick... 😆 When using |
Thanks, @benjamingr! I will try to understand the code at a low level and maybe propose something. |
Can you elaborate on that a little? Promises don't actually make any guarantee about when they run except that they do when only platform code does (which the C++ qualifies as). We make no official guarantees on the current |
Yeah, it's probably not a big deal to interleave. Also the way I opened a PR in #20287 |
Fwiw, the reproduction in https://github.com/logtrust/tls-server-demo does not seem to work very reliably on Linux… :/ |
@addaleax Yes, it is not simple to reproduce and my script is not very polished. I think I have reduced it to a benchmark similar to |
@alexfernandez can you also try running the benchmark with #20287 applied? (curl -L https://github.com/nodejs/node/pull/20287.patch | git am in your node folder) |
@benjamingr I don't recommend it. It won't affect the SecurePair piece at all. (Hence only Refs not Fixes.)
|
@benjamingr Sure enough! Thanks for the |
@addaleax Now that c346cb6 has landed, we finally have a reliable way to reproduce this isssue! 😄 The procedure is explained in the PR #20344, basically just run |
Quick update now that Node.js 10.x is becoming LTS next week: 10.13.0 is still painfully slow when using
The results for using 2, 1024 and 104856 bytes-long packets using
In summary, anyone using |
cc @mcollina |
Sorry for replying this after a long time. I did not forget about this, just the last month has been very hectic. @addaleax maybe you can take another shot at this? or at least, can you take a look and point us into the right direction for a fix? |
Hi there!! I am taking over @alexfernandez's work on node and TLS and I was wondering if there's been any progress on this issue, @addaleax. This regression in performance is blocking us from upgrading to node 10 in production, and we would love to move up and enjoy the rest of improvements made in this version. Thanks in advance for your excellent work!! |
@alexfernandez @mcollina @tufosa I think #27861 has addressed this issue – feel free to double-check, though. |
@addaleax @mcollina @alexfernandez I've just run the benchmark in the repo and some others of my own and the results are spectacular: performs 4 times better than the old |
With the upcoming Node.js v10.0.0, performance of sockets created with
createSecurePair()
is degraded, with several effects as unresponsive event loop, crashing connections and general sluggishness.Steps To Reproduce
Create a proxy that receives encrypted TLS connections and resends to a plain socket server. It should be a regular socket server that uses
tls.createSecurePair()
to decrypt data, and send it unencrypted to the socket server. Bombard it with a lot of connections and relatively small packets. Soon enough the proxy will hog down and become unresponsive.It is best to create multiple workers to act as clients, since otherwise the main event loop will be too busy sending data.
Sample Script
Run the script
combined-tls.js
:Running the last line using Node.js v8 or v9 will produce a responsive server, that prints a trace every five seconds; using Node.js v10.0.0 pre will yield an unresponsive server that prints traces erratically, generates strange errors and takes ages to shut down after ^C'ing it.
See the README.md for runtime options such as modifying the number of incoming connections. The script uses the
stdio
module only for parsing options, and strictly Node.js core modules after that.Possible Explanation
After the great work by @addaleax in #17882, the unholy mess that was
lib/_tls_legacy.js
was greatly simplified to usenew tls.TLSSocket()
underneath. A crucial bit was not ported, though: the buffering capabilities oftls.SecurePair()
.As a consequence, the new code in
lib/internal/streams/duplexpair.js
sends events (eitherdata
orreadable
depending on the stream mode) as they are received and decrypted. When many small messages are sent to theTLSSocket
it will hog down. In contrast, the old code behaved like TCP: when heavily loaded it started buffering data and sending bigger and bigger packets to thecleartext
stream.The sample code shows an average of 32 bytes per event with
TLSSocket
(v10), the same exact value sent by the client per packet; while the originalcreateSecurePair()
(v8 and v9) shows a bigger rate that depends on system load: I have seen anything from 60 to 300 bytes/event. The number of events inTLSSocket
is so high with v10 that attempting to resend everything from the proxy makes the event loop unresponsive.A possible workaround is to buffer packets in the proxy server, but this is suboptimal as it means double-guessing what the stream is doing. Also, buffering in the proxy would minimize packet resend time, but we would still be processing a lot of unnecessary events.
Importance
This issue is critical for us since it affects our ability to ingest data using both secure and insecure connections to the same port.
The text was updated successfully, but these errors were encountered: