I was doing some work in video streaming from mobile phones to PC recently and I was dealing with a lot of byte array streams from client to server, which I also needed to collocate on the server side.
I decided to write a class that simplifies the whole process, making the array management process as simple as using StringBuilder in Java; but for byte arrays.
"Why did you need to do that when you could use java.nio.ByteBuffer?" you may ask me, but well sometimes you need something simpler in usage and well you wonder secretly, if you can do it faster.
So I wrote ByteArrayBuilder.java
I didn't think of benchmarking it that much since I had little thought about it. I was more focused on the ease of use.
Recently however, I asked Github Copilot to analyze the file and it told me a lot about it, including the fact that I was better off with using java.nio.ByteBuffer . What I was doing was tantamount to reinventing the wheel according to the AI. It also advised me to run benchmarks of ByteArrayBuilder.java against java.nio.ByteBuffer. And that was what I did.
I wrote a benchmark found at: ByteArrayBuilderWars.java
Here are the results:
numberOfArrays
and each of these byte arrays had a size of dataArraySize
public static void main(String[] args) throws IOException {
int dataArraySize = 10000;
int numberOfArrays = 100000;
for (int i = 0; i < 10; i++) {
ByteArrayBuilder builder = ByteArrayBuilderWars.benchmarkAppendForByteArrayBuilder(dataArraySize, numberOfArrays);
ByteBuffer buffer = ByteArrayBuilderWars.benchmarkAppendForByteBuffer(dataArraySize, numberOfArrays);
ByteArrayBuilderWars.benchmarkReadBytes(builder);
ByteArrayBuilderWars.benchmarkReadBytes(buffer);
}
}
Here are the results:
arraySize | numArrays | ByteArrayBuilder(ms) | java.nio.ByteBuffer(ms) |
---|---|---|---|
10000 | 100 | 22.166 | 14.363 |
10000 | 100 | 11.36 | 10.988 |
10000 | 100 | 12.43 | 11.959 |
10000 | 100 | 10.382 | 11.187 |
10000 | 100 | 11.041 | 11.182 |
arraySize | numArrays | ByteArrayBuilder(ms) | java.nio.ByteBuffer(ms) |
---|---|---|---|
10000 | 100 | 0.005 | 0.477 |
10000 | 100 | 0.009 | 0.737 |
10000 | 100 | 0.005 | 0.589 |
10000 | 100 | 0.006 | 0.154 |
10000 | 100 | 0.005 | 0.146 |
arraySize | numArrays | ByteArrayBuilder(ms) | java.nio.ByteBuffer(ms) |
---|---|---|---|
10000 | 1000 | 120.38 | 110.924 |
10000 | 1000 | 104.201 | 105.941 |
10000 | 1000 | 103.048 | 102.265 |
10000 | 1000 | 103.61 | 102.372 |
10000 | 1000 | 102.899 | 101.902 |
arraySize | numArrays | ByteArrayBuilder(ms) | java.nio.ByteBuffer(ms) |
---|---|---|---|
10000 | 1000 | 0.008 | 5.089 |
10000 | 1000 | 0.006 | 2.847 |
10000 | 1000 | 0.005 | 2.734 |
10000 | 1000 | 0.005 | 2.896 |
10000 | 1000 | 0.007 | 2.681 |
arraySize | numArrays | ByteArrayBuilder(ms) | java.nio.ByteBuffer(ms) |
---|---|---|---|
10000 | 10000 | 1106.589 | 1077.174 |
10000 | 10000 | 1023.701 | 1012.844 |
10000 | 10000 | 1067.048 | 1041.951 |
10000 | 10000 | 1049.663 | 1029.896 |
10000 | 10000 | 1069.867 | 1046.699 |
arraySize | numArrays | ByteArrayBuilder(ms) | java.nio.ByteBuffer(ms) |
---|---|---|---|
10000 | 10000 | 0.005 | 30.745 |
10000 | 10000 | 0.006 | 22.519 |
10000 | 10000 | 0.003 | 24.707 |
10000 | 10000 | 0.003 | 24.299 |
10000 | 10000 | 0.003 | 25.242 |
The results say it all. I ran each result row and took the average of 10 samples of the quantity being measured, then I recorded 5 samples of the said average.
The append rates are very much similar, though java.nio.ByteBuffer consistently outperforms ByteArrayBuilder, even though, it is ever so slightly.
When it comes to reading the bytes though, it is a classic massacre.
The ByteArrayBuilder is thousands of time faster than the java.nio.ByteBuffer every single time.