Re: Does CFSocket use efficient polling?
Re: Does CFSocket use efficient polling?
- Subject: Re: Does CFSocket use efficient polling?
- From: Josh Graessley <email@hidden>
- Date: Tue, 10 Feb 2009 10:40:38 -0800
Some day I'll proof read my emails before sending them. Sorry about
the errors.
-josh
On Feb 10, 2009, at 10:11 AM, Josh Graessley wrote:
As Quinn pointed out, CFSocket uses select. It's much worse than
that though.
Before going further, I just want to point out that the problem
CFSocket is trying to solve is a tough one and given what it has to
work with, it does a good job. It works great for most situations.
Also, the description below is based not based on reading through
the code but experience trying to debug some performance problems,
so the details may be slightly off.
CFSocket uses select in a second thread because there's no way on
Mac OS X to wait on an event on a mach port and a file descriptor at
the same time. The second thread has a loop that sits in select. It
doesn't exactly poll. It sits in select most of the time, not
costing much in the way of resources. When an event does occur on a
socket in the file descriptor list, select in the CFSocket thread
returns. The CFSocket thread sends a message on a mach port to wake
up the run loop and pulls file descriptor(s) in question off of the
list of descriptors passed to select. The CFSocket thread then goes
back in to select.
The run loop receives the mach message indicating that an event has
occurred on the file descriptor(s) and calls each CFSockets
callback. After the callback returns, if callbacks are still enabled
for the CFSocket, a message is sent to the CFSocket thread using
what I assume is a socketpair. This message indicates that the file
descriptor for that CFSocket should be added back to select. The
CFSocket threads select returns and the thread reads the message,
adding the file descriptor back to the list and calling select again
to wait for more events.
What does this mean for your code. There's a little bouncing between
threads every now and then when you read. It is important to keep in
mind:
1) Always use non-blocking sockets
2) When your callback is called, always read all data/packets until
you get an EWOULDBLOCK error
If you read just a bit of data and return, the run loop thread will
message the cfsocket thread which will call in to select and see
that read is still set for the file descriptor and message back to
the run loop thread causing your callback to be called. You just ate
a bunch of CPU time and got nothing for it.
With mDNSResponder on the iPhone we found that bouncing back and
forth between the threads was consuming a ridiculous amount of CPU,
even with the tips above of using non-blocking sockets and always
reading as much data as we could. The posix version of the code ran
with very little overhead on the same device. We decided to simulate
the CFSocket model but move all of the processing of packets to our
equivalent of the CFSocket thread. We made this decision because
mDNSResponders main job is handling packets from the network. The
only events we get on the run loop are notification of network state
changes. Those occur infrequently. This is unlikely to be the right
solution for any other apps, especially an app with UI.
CFSocket does a stand up job hiding the nasty details of
coordinating between two different sources of events (file
descriptors and mach ports). Unless you're absolutely certain that
CFSocket is the last remaining hotspot in your code, stick with it.
It is not unreasonable to imagine a day when there will be a way for
the system to wait on events for both mach ports and file
descriptors. When/if that day comes, the CFSocket implementation may
adopt the new mechanism and eliminate the extra thread. If you
depend on CFSocket, you will probably get the performance win for
free.
-josh
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden