A few aspects of your code bother me. I could investigate the details, but I apologize that I'm feeling lazy. But, maybe just asking these questions would send you on the right path to discovery?

Sure, thanks for trying to help !


Your code is expecting to read and write entire 16K chunks, and even throws an error if it doesn't get a full 16K chunk. This goes against the normal API of sysread, though of course in this case it is virtual. Does SSL protocol or this particular implementation guarantee whole frames like this? Is 16K a magic SSL number that you can rely on, or will it sometimes give you smaller chunks? Or does it guarantee that you receive the whole chunks of whatever the other side sent?

This is all explained in the second link of my original post (section "Polling of SSL sockets"). I provided these links especially because IO::Socket::SSL has some specific aspects like this one. I could try to paraphrase here, but I'm afraid I wouldn't be as accurate as the original explanation. The fact that the server part is using this application buffer size is also playing a role here, this is what makes the sending SSL layer use the max SSL frame size. If you want you can consider the "die" instruction as a debug/check instruction. As you see the "die" is never executed in my case so it is safe to consider the sysread instructions at client side always return 16Ki data in this specific test case. The "die 'Unexpected pending data in SSL socket'" instruction is exactly the same: a debug instruction to show this never happens in this test case.


Packets have to be smaller than 1.5K for ethernet, so many physical receives will happen before you reach 16K, as you noticed in your subsequent post. Might your choice of 16K be the actual problem that causes lots of looping?

I'm not sure I understand your reasoning. Can you tell me which size you think would be better to use as sysread parameter, and then I will try to explain why I think it wouldn't improve anything ?
Also, as you can see in my previous post, Mojo::IOLoop suffers from the exact same problem (a CPU core is used at 100% when performing a transfer) whereas it uses a hardcoded value of 128Ki for the application buffer size


You mention configuring the "low water mark" on the socket, but that seems wrong. Your application packets are 16K, but the underlying TCP packets could be a variety of sizes, so insisting at the OS level that it not return data until 16K is available seems likely to break things (even if it didn't this time).

For the general case of course it is wrong. SO_RCVLOWAT comes with his own challenges when trying to use it in the general case. I only used SO_RCVLOWAT to check the origin of the problem really was what I though it was, in my specific test case (case of large data transfer on non-blocking SSL socket).


Using Time::HiRes, have you tried measuring the actual overhead of an "unproductive" sysread on IO::Socket::SSL which reads the underlying socket but delivers nothing? How does this compare to the time spent on a productive sysread? It seems to me that an unproductive sysread shouldn't take much longer than a sysread on the underlying socket.

It's not that simple. An "unproductive" sysread from application point of view is actually productive from SSL layer point of view: data are copied from the socket buffer to the internal SSL buffer. So each "unproductive" sysread call will actually make the later "productive" sysread call lighter, because a part of the SSL frame will already be inside the internal SSL buffer. The only way to measure the true overhead is to compare a productive sysread call with no preceding unproductive sysread call, to a productive sysread call with N preceding unproductive sysread calls.
But anyway, I wouldn't say there is an overhead in "unproductive" SSL sysread compared to "productive" SSL sysread, I would say there is an overhead in any SSL sysread (even the "unproductive" ones which don't decrypt anything yet, and that is the main problem in my opinion) compared to non-SSL sysread. That would explain why, in the case of large data transfer using SSL, it's important to save superfluous sysread calls, and not try to read before an entire SSL frame is available (or at least not after each single TCP packet is received).


If you call ->sysread as a class method instead of a tied-IO global function, is there any performance difference?

No, in both cases I have about 40000 sysread calls by second, and a CPU core is used at 100% instead of 55%


Have you verified that the code really does wait on select()? If fileno() didn't work as expected and the select() always returned immediately, it would result in really high CPU usage with no other hints that something was wrong.

Yes, I checked that already, by adding a sleep in the send code at server side, and checking the resulting number of sysread calls at client side. All works as expected. Also, the simple fact that using SO_RCVLOWAT instantly "fixes" the problem without touching the select code is a good indicator that the select call is working as expected.


In reply to Re^2: IO::Socket::SSL / Net::SSLeay inefficient in non-blocking mode ? by Yaribz
in thread IO::Socket::SSL / Net::SSLeay inefficient in non-blocking mode ? by Yaribz

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.