Re: Socket read tuning on Mac OS X
Re: Socket read tuning on Mac OS X
- Subject: Re: Socket read tuning on Mac OS X
- From: Jakub Bednar <email@hidden>
- Date: Wed, 7 Apr 2010 09:45:12 +0200
On Apr 3, 2010, at 1:06 AM, Terry Lambert wrote:
> On Apr 2, 2010, at 4:06 PM, Terry Lambert wrote:
>> On Apr 2, 2010, at 7:18 AM, Jakub Bednar wrote:
>>> I have tried SO_RCVLOWAT along with SO_RCVTIMEO options, but this
>>> is not the way. Poll() does not respect SO_RCVLOWAT and the socket
>>> will not give me less data but return an error when
>>> SO_RCVTIMEO timeout expires.
>>
>> SO_RCVLOWAT only applies to UNIX domain sockets or FIFOs, where
>> there is not potentially an administrative or system limit that will
>> prevent enough data accumulating in order to satisfy the low
>> watermark. It's going to have no effect because it's not supposed
>> to have any effect: you could starvation deadlock yourself
>> otherwise, which could be used to stage a local DOS. This is true
>> on most other UNIX-like systems as well. One exception is "accept
>> filters"-based systems with kernel pre-parsing of data contents for
>> recognition of complete messages; another is the NCP streams MUX in
>> NetWare for UNIX, which also recognizes complete messages, and does
>> not send unchunked data up to user space. These are dangerous from
>> a security perspective because they allow a user space process to
>> download interpreted code intended to run in supervisor mode.
>>
>> NB: As To A.M.'s suggestion, the NOTE_LOWAT for kqueue() is only
>> respected for sockets, pipes, and BPF (Berkeley Packet Filter);
>> unless you are doing raw ethernet frames via BPF, this will
>> unfortunately not help you out.
>
> I spoke too soon here, and misrepresented things.
>
> A.M.'s suggestion isn't going to work if the poll() didn't work as you
> note.
>
> The SO_RCVLOWAT is supposed to work on all sockets, so why it seems to
> not be working in your case is at this point unknown; there are a
> couple of theories so far. Stay tuned.
>
Thanks for a full-range explanation Terry,
anyway I generally do not know how much data will arrive and according to SO_RCVLOWAT and SO_RCVTIMEO documentation I'm not able to implement what I want using these options even if the poll() is working correctly. The poll will probably unblock when SO_RCVTIMEO is reached, signaling an error state on the socket. Subsequent read will also return error. I would need to change the socket option before read attempt to get the partial data available and then set the option back, leading to a syscall storm.
The idea with a reading thread is basically what I have currently in my code. I'm using poll()/read() on a socket and than put the data to a processing thread and go to another poll(). Currently the highest percentage of time spend according to Shark is in interrupt enabling/disabling (about 20% of the time) which I think means switching to the driver code. Second bottleneck is the synchronization with the worker thread. Putting sleep there works, decreasing CPU usage rapidly, but it also slows down download speed (to 6.4M/s from 10.1M/s). As the sleep is not necessary on some systems, I was looking for a better way how to do it.
Following your comments I will most probably end up collecting some statistics (e.g. how much data and how often is delivered to me) and add the short sleep only if needed. Btw. is there a way how to get my current CPU usage directly from the executable?
My other tests show that it is really a common problem. e.g. wget on one system eats 6.4% CPU and on the other 30%CPU. Both are downloading with the same speed on the same line from same source on my local LAN. Following Shark's system call trace it is just select()/read()/write to disk with no other overhead so 30% is quiet a lot. The CPU usage increase ratio corresponds to the one of my application.
Best regards,
Jakub _______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden