in reply to Re^2: IO::Socket::SSL / Net::SSLeay inefficient in non-blocking mode ?
in thread IO::Socket::SSL / Net::SSLeay inefficient in non-blocking mode ?
In the best case, the implementation of IO::Socket::SSL's sysread would look something like this:
sub sysread(...) { if ($self->{decoded_remaining}) { return ... } else if (sysread($self->{underlying_socket}, $self->{buffer}, ...) +> 0) { $self->{next_frame_size} //= decode_frame_size($self->{buffer}); if (length $self->{buffer} >= $self->{next_frame_size}) { ... # decode it return ... } $SSL_ERROR= ...; return undef; } }
and that should run reasonably efficiently if you call it a bunch of times and the length() test is false. In fact, it shouldn't be too much worse than the same written in C, because there's just not much happening aside from a syscall and a few tests. In fact, I'd expect the syscall to be more than 75% of the execution time of that example code. Of course, long-lived code is seldom this simple and could have all sorts of extra checks going on making it way more expensive than just the syscall. It might be decoding the frame size on every call instead of caching it, or doing lots of other unnecessary work, or even making multiple syscalls for some reason. Have you tried systrace on it to see the actual calls? If you see unexpected things, then its time to dive into the internals of SSL and see if there is a way to avoid triggering that. You could end up reporting a bug that helps everyone.
On the other hand, just executing 40,000 syscalls even in a compiled language is expensive, and could possibly peg a CPU. By comparing the calls that return data (which execute the decode step) with the calls that don't, it could give a hint about that.
If perl is not adding excessive overhead, then you could be up against the limits of nonblocking reads to the TCP stack. You want there to be fewer sysreads, but the TCP stack is returning smaller fragments of data than are useful to process, and waking your rogram too often. In this case, you could implement your own variant of Nagle's algorithm, and just delay a number of milliseconds after the socket is readable before performing the read, thus collecting more data per read for better throughput, and not hurting the latency too much since you are doing bulk transfers and not tiny two-way signaling. Of course this assumption only works when you know the sender is writing large packets, otherwise you'd be delaying the processing of small packets. I'd suggest making the delay dynamic, in response to the number of unproductive reads. This way, the code can auto-tune itself to systems with vastly different network or processor speeds.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: IO::Socket::SSL / Net::SSLeay inefficient in non-blocking mode ?
by Yaribz (Beadle) on Jun 25, 2022 at 11:19 UTC | |
by NERDVANA (Priest) on Jun 26, 2022 at 03:56 UTC | |
by Yaribz (Beadle) on Jun 26, 2022 at 16:49 UTC | |
by NERDVANA (Priest) on Jun 27, 2022 at 18:06 UTC | |
by Yaribz (Beadle) on Jun 27, 2022 at 20:06 UTC | |
by Yaribz (Beadle) on Jun 26, 2022 at 10:13 UTC | |
by Yaribz (Beadle) on Jun 26, 2022 at 12:03 UTC |