Re: pushing the envelope with sockets
- From: Helge Jensen <helge.jensen@xxxxxxx>
- Date: Tue, 23 May 2006 22:29:01 +0200
Dan Ritchie wrote:
I'm using asynchronous I/O, and in the receive handler I issue another BeginReceiveFrom immediately in order to have an I/O ready to receive as quickly as possible. This works very well, but I find that my CPU usage will
Async IO can potentially avoid spending threads in massively parallel applications, but why would it reduce CPU-load?
suddenly (and apparently randomly) increase dramatically (ie, from < 30% to about 60% on average). I've added performance counters, and identified that
During IO, or changing from blocking to non-blocking IO?
30 vs. 60% of how long? comparing relative CPU-usage doesn't make much sense if it's not known what it's relative to.
Try timing:
- receiving the way you do now
- receiving into a large buffer, but less often -- while still not exceeding the OS-buffer-size, something like:
byte[] large_buf = ...;
while ( true ) {
Receive(large_buf, ...);
Thread.Sleep(TimeSpan.FromSeconds(0.1));
}
Which spends more cpu? (it's not the same as which completes first!)
the majority of the increase in CPU time is spent in the BeginReceiveFrom call. This is surprising to me for a couple of reasons. First, this is a non-blocking call, so I would expect it to return quickly whether data is received or not. I also don't see any corresponding increase/decrease in
BeginReceiveFrom may complete synchronously, or it may need to queue in an IO-completion-port for the next receive. The latter will probably spend more or less CPU (although I haven't measured it).
Have you tried reading synchronously with a very large buffer, just to see how that measures up to your async-IO?
If you re-issue BeginReceive immidiatly you must be allocating a new receive-buffer for each receive. Perhaps a less CPU-intensive approach would be to only have one buffer and process that before re-issuing receive?
either the number packets received per second or the number of reads I complete per second (which tracks very closely to UDP packets/second), so I don't believe the number of BeginReceiveFrom calls I'm making is changing commensurately.
You may be seeing switch-overhead. The faster you BeginReceive, the fewer packages the OS will have queued up for you and the more calls to Begin/End-Receive will be executed.
So my question is, is there anything in the Socket implementation that might be causing this unexpected increase in CPU time? I've looked at BeginReceiveFrom with .Net Reflector, and I'm wondering if perhaps the call to ThreadPool.RegisterWaitForSingleObject might be stalling. I'm issuing on the order of about 3500 I/Os per second, but I don't see my ThreadPool availability being impinged. Any ideas? Thanks.
I would try reading in large chunks instead of small ones if low cpu-usage is the goal, at least just to see if there's a difference.
It's another matter if low latency or efficient usage of the number-of-threads resource is required than if you are trying to minimize CPU-usage.
--
Helge
.
- Follow-Ups:
- Re: pushing the envelope with sockets
- From: Dan Ritchie
- Re: pushing the envelope with sockets
- Prev by Date: Type Substitution over web services?
- Next by Date: Re: C# 3.0 Proposals
- Previous by thread: Type Substitution over web services?
- Next by thread: Re: pushing the envelope with sockets
- Index(es):
Relevant Pages
|