2
votes

I heard that Intel uses little endian architecture, so giving byte buffers in little endian for the CPU is better/faster. I have also heard that the network works with big endian.

So can someone explain what should be used when doing network IO using Java NIO ByteBuffers, in other words, when sending bytes across the wire from one machine to another?

Just use little endian all the way? Does it matter?

2
Networks don't "work big-endian" (really, they don't care: they send octect streams, not integer streams :-). It is just that Network Byte Order is a synonym Big Endian. Don't ask me why. So when saying "Protocol X uses Network Byte Order .." or "Function Y expected a Network Byte Order packed value ..", etc, that's the contract defined for that API/protocol. It has nothing to do with "networks works with big endian".user166390
@pst If you have one node big and another node little, and you define your protocol little, one of the nodes will have to convert, right? As Peter said, the cost will be very little but it will be still a cost, correct? Better to have nodes with the same architecture talking to each other so none of them needs to convert.chrisapotek
That nodes have to "talk the same language": so as long as it's the same - BE (aka NBO), LE - then there is no issue at the byte-order level. The "cost" of conversion, if needed, will vary - and will not even by a practical concern in all but very extreme (and hypothetical at this point) cases: CPUs are extremely fast these days. The important thing is making sure everything is "talking the same thing". That is, the driving factor is the common language (which you are free to define as LE, unless using an existing protocol).user166390
Keep in mind, there is no automatic conversion by "the network" from LE to NBO and "Network Byte Order" is an unfortunate term if it implies any such conversion; if an octect stream of integers encoded in LE is sent, that is what is sent - byte by byte.user166390

2 Answers

3
votes

So can someone explain what should be used when doing network IO using Java NIO ByteBuffers,

it has to match what the other end expects.

when sending bytes across the wire from one machine to another?

If it doesn't matter I would leave the default because the performance gain you get is unlikely to matter, even for a 1 Gb network.

If you want to use the native endian of a machine you can use

ByteBuffer.order(ByteBuffer.nativeOrder());

Here is a comparison of how long it takes

public static void main(String... args) {
    ByteBuffer bb = ByteBuffer.allocateDirect( 1024 * 1024);
    for (int i = 0; i < 5; i++) {
        testEndian(bb.order(ByteOrder.LITTLE_ENDIAN));
        testEndian(bb.order(ByteOrder.BIG_ENDIAN));
    }
}

public static void testEndian(ByteBuffer bb) {
    long start = System.nanoTime();
    int runs = 100;
    for (int i = 0; i < runs; i++) {
        bb.clear();
        int count = 0;
        while (bb.remaining() > 3)
            bb.putInt(count++);
        bb.flip();
        int count2 = 0;
        while (bb.remaining() > 3)
            if (count2++ != bb.getInt())
                throw new AssertionError();
    }
    long time = System.nanoTime() - start;
    System.out.printf(bb.order() + " took %,d μs to write/read %,d ints%n", time / 1000 / runs, bb.capacity() / 4);

}

prints

LITTLE_ENDIAN took 1,357 μs to write/read 262,144 ints
BIG_ENDIAN took 1,484 μs to write/read 262,144 ints
LITTLE_ENDIAN took 867 μs to write/read 262,144 ints
BIG_ENDIAN took 880 μs to write/read 262,144 ints
LITTLE_ENDIAN took 860 μs to write/read 262,144 ints
BIG_ENDIAN took 881 μs to write/read 262,144 ints
LITTLE_ENDIAN took 853 μs to write/read 262,144 ints
BIG_ENDIAN took 879 μs to write/read 262,144 ints
LITTLE_ENDIAN took 858 μs to write/read 262,144 ints
BIG_ENDIAN took 871 μs to write/read 262,144 ints

In one MB of data, using little endian saved around 20 μs (1/1000th of 1 ms). To send 1 MB over 1 Gb takes about 9,000 μs.

0
votes

Basically never. Most network protocols are defined in 'network byte order', which is big-endian. If you know you have Intel architecture at the other end you can use little-endian, but do you really know that? Forever?