Re: [boost] asio networking proposal 0.3.4

--- Beman Dawes <bdawes@acm.org> wrote:
Where did this idea come from that the only way to avoid an additional copy is to use a void *?
From: Christopher Kohlhoff [mailto:chris@kohlhoff.com]
It's not just avoiding a copy, it's avoiding a copy *and* allowing arbitrary data structures to be sent. IMHO an important use case for C++ and networking is being able to do things like:
struct message { int a; double b; int c_size; char c[0]; }; message* m = ...; sock.write(buffers(m, sizeof(message) + m->c_size));
Oh no! Please! Don't let us encourage bad code like that. It will work if the receiving socket belongs to the same program on the same machine. Otherwise it depends on: - sizeof(int) (16,32,64 bits) - endianness - representation of double (IEEE or IBM) ... and that's just the obvious, real-world, differences that can be encountered TODAY. The only safe datatype for transport over a socket is an array of unsigned char with a defined layout. Thus we would need somethink like: message* m = ...; std::vector<unsigned char> mbuf; mbuf.reserver(sizeof(m)+m->c_size); mbuf.push_back( m->a & 0xff ); mbuf.push_back( (m->a >> 8) & 0xff ); pushDouble( mbuf, m->b ); // pushDouble decodes the double and pushes // the bytes of a IEEE double onto mbuf. etc This looks like an application for something like serialization. For example, the result of right shifting a negative number is implementation defined and something more subtle is required for real portability. (Something like serialization, rather than the same as, because the user needs to specify "this field is 16 bits", "this field is 32 bits" independant of the size of the datatype used to store the field). (Or have I missed something terribly subtle in the "buffers" code which handles all this) -- Martin Bonner Martin.Bonner@Pitechnology.com Pi Technology, Milton Hall, Ely Road, Milton, Cambridge, CB4 6WZ, ENGLAND Tel: +44 (0)1223 441434

Hi Martin, --- Martin Bonner <martin.bonner@pitechnology.com> wrote:
struct message { int a; double b; int c_size; char c[0]; }; message* m = ...; sock.write(buffers(m, sizeof(message) + m->c_size));
Oh no! Please! Don't let us encourage bad code like that.
One person's bad code is another person's necessary performance optimisation :)
It will work if the receiving socket belongs to the same program on the same machine. Otherwise it depends on: - sizeof(int) (16,32,64 bits) - endianness - representation of double (IEEE or IBM)
... and that's just the obvious, real-world, differences that can be encountered TODAY.
It will in fact work across different machines that have the same architecture, where the programs use the same alignment etc. This may seem picky, but it is a vital point. The optimisation shown in the example, ugly though it looks, is in principle what is used in receiver-makes-right protocols, i.e. the cost associated with dealing with architecture differences is left to the receiver. That way if the data is sent between two machines of the same type, then those costs are eliminated. There's a large body of research and experience in these sorts of optimisations, e.g. MPI, and they are critical to high performance computing. I agree that code like that should not appear in typical applications and should not be generally encouraged. However there is a use case for it in domains that would also often use C++ for performance. Therefore I believe that a C++ networking library must not preclude such a usage.
The only safe datatype for transport over a socket is an array of unsigned char with a defined layout. Thus we would need somethink like: message* m = ...; std::vector<unsigned char> mbuf; mbuf.reserver(sizeof(m)+m->c_size); mbuf.push_back( m->a & 0xff ); mbuf.push_back( (m->a >> 8) & 0xff ); pushDouble( mbuf, m->b ); // pushDouble decodes the double and pushes // the bytes of a IEEE double onto mbuf. etc
The people who worry about high performance enough to use receiver-makes-right would look at that and see a lot of redundant copying! :) Cheers, Chris
participants (2)
-
Christopher Kohlhoff
-
Martin Bonner