Sign in to follow this  

Receiving and sending data efficiently

This topic is 2850 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i am writing a client and a server and am thinking about using UDP as my protocol. I am going to use boost::asio for my networking library since it seems well written and is cross-platform and it provides asynchronous support. I have also noticed that it supports scatter/gather. I was thinking of using this feature, but was unsure of the impact it might have and didn't know if it is worth it. I know it is supported at the API level on Windows, but I don't if it is supported elsewhere. Here is my plan

#define MAX_DATA_SIZE 256 //max size allowed for a single message.
struct Message
{
   MsgHeader header;
   void data[MAX_DATA_SIZE];
};


my first buffer would be a pointer to the message header. My second would be to the actual data. This way, using one system call, the data is copied to the correct locations. If I do not use scatter/gather, then I will have to read all of it into one big buffer, and then copy the data to the Message struct using 2 memcpys. Am I implementing scatter/gather correctly? Is this an efficient way of reading data from a UDP socket? Also, this would only seem to work with UDP because it is received one packet at a time whereas TCP, the packets are all streamed together (this causes message boundary problems). How would you implement something similar in TCP if I decided to use that instead (though this is doubtful)?

Share this post


Link to post
Share on other sites
IMHO, this is not useful application of scatter gather.

For example, you might decide to compress the packets, or change structure for some types, or in other way affect them.

Also - UDP packet arrives as one, or not at all. So it will be one call anyway. S/G would just add a ton of complications vs. what is a single recv() with single buffer anyway. And user space processing of two bytes is trivial vs. whatever generic work S/G would need to do in kernel.


S/G can be used for ring buffers with TCP, where you pass both ends and they are filled as much as possible.

One case for S/G would be where destination buffers are separate, perhaps spread over multiple instances or similar, but I cannot really come up with a realistic case where this would be beneficial, since there will always be at least some validation logic involved in accepting raw data from network.

It might make more sense in some controlled environment, perhaps compute cluster, but even there the validation isn't all that costly, nor is manipulation of data compared to trouble of broken data.

Share this post


Link to post
Share on other sites
Have you profiled your application to prove that memcpy() of the buffer is a worthwhile optimization?

Hint: unless you're running on 20 year old hardware, or hooking up your gaming rig to a 10 gigabit internet connection, there's nothing you can do to a network packet's worth of data that will register on a profiler.

Let's do the math:

20 Mbit/s internet connection (because we're m4d l33t!)
-> at most 2.5 Mbyte/s of data throughput
8.0 GB/s memory bus (old Core 2 consumer level -- Core i7 gives you 24 GB/s)
2.5 M / 8.0G == 0.03% of available memory bandwidth

If the biggest CPU hog in your application is a memcpy() step that can't possibly take more than 0.03% of your execution time, I'd be really, really surprised!

And, if you want to separate headers and data, just receive it all into a big buffer, and pass along pointers to the data through casting.

Share this post


Link to post
Share on other sites
So what is a good example of when to use scatter/gather. I agree that an extra memcpy operation would be the least of my efficiency problems. When doing research on scatter/gather I found this:

Vectored IO

And you know if it is in Wikipedia, it has to be right. ;)

This suggested that concatenating output was a reason to use it. It does seem like a weak example. The only time I can think to use it is when you are using tcp/ip and you buffer size may need to change often. Scatter/gather would allow you to change your buffer size without destroying and copying your old buffer. What are some good examples of when to use scatter/gather.

(Note: I am not trying to force myself to use scatter/gather. I am just trying to learn about it so that I know when it could possibly be beneficial.)

Share this post


Link to post
Share on other sites

This topic is 2850 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this