#include <iostream>
int main (void) {
/* faster */
struct big {
int x;
int y;
int z;
};
/* smaller */
struct small {
shortunsignedint x :4;
shortunsignedint y :4;
shortunsignedint z :4;
};
std::cout << sizeof(big) << std::endl;
std::cout << sizeof(small) << std::endl;
std::cin.get();
return 0;
}
Result:
1 2
12
2
Being the curious person I am, I was thinking about ways that I would optimize information that I would send over the network. I looked into 4-bit integers. I was thinking that 4 bit integers are smaller to send over the network, but integers are faster for the computer to work with.
I guess my question is: Is this worth doing? Would this impact the speed that information travels on my network? (If I am sending a lot of information. My internet up-speed is terrible.)
Depends. Unless you marshall the bits, it is not portable across C++ implementations.
> Would this impact the speed that information travels on my network?
The network bandwidth will remain the same. But if the payload (amount of data) that is sent is smaller, it will take less time; as for example sending files in compressed form. It will have a measurable impact on network performance only if the total number of bytes transmitted at one time is not very small.
> I am sending a lot of information. My internet up-speed is terrible.
There may be other alternatives depending on your context. For instance, if periodic status updates are being transmitted, it may be possible to reduce the payload by transmitting only the delta (status information that has changed since the last send).
I was wondering, what do you mean by "marshall the bits"?
It means that you do the bit twiddling yourself rather than letting the compiler do it for you with bit fields, as you're doing above. For example,
1 2 3 4 5 6 7 8 9 10 11
//TODO: Change to a type with a well-defined size, such as boost::uint32_t, instead of just 'unsigned'.
inlineunsigned store_triple(unsigned x, unsigned y, unsigned x){
return ((x&0xF)<<8)|((y&0xF)<<4)|(z&0xF);
}
inlinevoid retrieve_triple(unsigned &x, unsigned &y, unsigned &z, unsigned src){
x=(src>>8)&0xF;
y=(src>>4)&0xF;
z=src&0xF;
}
> I was wondering, what do you mean by "marshall the bits"?
Converting the in-memory representation into a representation that can be transmitted over a network; such that it can be unmarshalled at the other end to create the logically equivalent the in-memory representation on that platform. Size, ordering of fields, padding and alignment, endianness etc. could be different across implementations; marshalling is a way transfer data in a consistent manner across across different implementations.
#include <cstdint>
int main()
{
struct big
{
int x, y, z ;
};
struct small
{
using byte = unsignedchar ;
byte x, y, z ;
};
std::cout << sizeof(big) << '\n' // 12
<< sizeof(small) << '\n' ; // 3
}
Assuming that std::uint8_t is available at both ends (in practice, it is) and the representation of std::uint8_t is the same at both ends (again, in practice, it is), this elides the whole issue of marshalling, at the cost of one extra byte. struct small can be sent across the wire in an unmarshalled form.
Sorry for taking a while to reply. I had to teach myself bitwise. For some reason or other, I was completely unaware of its existence. I don't think many C++ tutorials that I have read included it.
It means that you do the bit twiddling yourself rather than letting the compiler do it for you with bit fields, as you're doing above. For example,
1 2 3 4 5 6 7 8 9 10 11
//TODO: Change to a type with a well-defined size, such as boost::uint32_t, instead of just 'unsigned'.
inlineunsigned store_triple(unsigned x, unsigned y, unsigned x){
return ((x&0xF)<<8)|((y&0xF)<<4)|(z&0xF);
}
inlinevoid retrieve_triple(unsigned &x, unsigned &y, unsigned &z, unsigned src){
x=(src>>8)&0xF;
y=(src>>4)&0xF;
z=src&0xF;
}
Okay, I think that I understand. This code is storing unsigned integers x, y, and z into and unsigned integer.
Does &0xF mean that it is only taking the lower 4 bits from a byte? So would &0xF0 take the upper 4 bits from a byte? And &0xFF take an entire byte? (That is what I could gather from reading the internet and playing around with HEX to Binary convertors.)
Converting the in-memory representation into a representation that can be transmitted over a network; such that it can be unmarshalled at the other end to create the logically equivalent the in-memory representation on that platform. Size, ordering of fields, padding and alignment, endianness etc. could be different across implementations; marshalling is a way transfer data in a consistent manner across across different implementations.
Thanks for telling me about marshalling, there was a huge part of C++ that I didn't know about, because I didn't know about marshalling. Sorry for not responding quickly, it took me a day to learn it.
I am considering your resolution, because I don't think 1 byte is that huge a deal. It is also simple.