diff --git a/CHANGELOG.md b/CHANGELOG.md index 797e1fa..1bc7291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Changelog v2.4.0 ------ * Added pipe methods for efficiently encoding and decoding complex objects. +* Optimize reading and writing primitive arrays. v2.3.3 (2024-04-10) ------ diff --git a/src/main/java/org/cojen/dirmi/core/BufferedPipe.java b/src/main/java/org/cojen/dirmi/core/BufferedPipe.java index 2b9d3c3..12541e1 100644 --- a/src/main/java/org/cojen/dirmi/core/BufferedPipe.java +++ b/src/main/java/org/cojen/dirmi/core/BufferedPipe.java @@ -712,38 +712,109 @@ private String readString(int length) throws IOException { private boolean[] readBooleanArray(int length) throws IOException { var array = new boolean[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if (--avail <= 0) { + mInPos = pos; + break; + } + } } - return array; } private char[] readCharArray(int length) throws IOException { var array = new char[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if ((avail -= 2) < 2) { + mInPos = pos; + break; + } + } } - return array; } private float[] readFloatArray(int length) throws IOException { var array = new float[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if ((avail -= 4) < 4) { + mInPos = pos; + break; + } + } } - return array; } private double[] readDoubleArray(int length) throws IOException { var array = new double[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if ((avail -= 8) < 8) { + mInPos = pos; + break; + } + } } - return array; } private byte[] readByteArray(int length) throws IOException { @@ -754,29 +825,83 @@ private byte[] readByteArray(int length) throws IOException { private short[] readShortArray(int length) throws IOException { var array = new short[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if ((avail -= 2) < 2) { + mInPos = pos; + break; + } + } } - return array; } private int[] readIntArray(int length) throws IOException { var array = new int[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if ((avail -= 4) < 4) { + mInPos = pos; + break; + } + } } - return array; } private long[] readLongArray(int length) throws IOException { var array = new long[length]; - // TODO: Optimize by reading chunks. - for (int i=0; i= array.length) { + mInPos = pos; + return array; + } + if ((avail -= 8) < 8) { + mInPos = pos; + break; + } + } } - return array; } private Object[] readObjectArray(int length) throws IOException { @@ -1527,9 +1652,22 @@ final void writeString(String v) throws IOException { final void writeBooleanA(boolean[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_BOOLEAN_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(1); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + buf[end++] = v[off++] ? (byte) 1 : (byte) 0; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 1 > buf.length) { + mOutEnd = end; + break; + } + } } } } @@ -1540,9 +1678,23 @@ final void writeBooleanA(boolean[] v) throws IOException { final void writeCharA(char[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_CHAR_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(2); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + cShortArrayBEHandle.set(buf, end, (short) v[off++]); + end += 2; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 2 > buf.length) { + mOutEnd = end; + break; + } + } } } } @@ -1553,9 +1705,23 @@ final void writeCharA(char[] v) throws IOException { final void writeFloatA(float[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_FLOAT_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(4); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + cIntArrayBEHandle.set(buf, end, Float.floatToRawIntBits(v[off++])); + end += 4; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 4 > buf.length) { + mOutEnd = end; + break; + } + } } } } @@ -1566,9 +1732,23 @@ final void writeFloatA(float[] v) throws IOException { final void writeDoubleA(double[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_DOUBLE_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(8); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + cLongArrayBEHandle.set(buf, end, Double.doubleToRawLongBits(v[off++])); + end += 8; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 8 > buf.length) { + mOutEnd = end; + break; + } + } } } } @@ -1589,9 +1769,23 @@ final void writeByteA(byte[] v) throws IOException { final void writeShortA(short[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_SHORT_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(2); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + cShortArrayBEHandle.set(buf, end, v[off++]); + end += 2; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 2 > buf.length) { + mOutEnd = end; + break; + } + } } } } @@ -1602,9 +1796,23 @@ final void writeShortA(short[] v) throws IOException { final void writeIntA(int[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_INT_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(4); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + cIntArrayBEHandle.set(buf, end, v[off++]); + end += 4; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 4 > buf.length) { + mOutEnd = end; + break; + } + } } } } @@ -1615,9 +1823,23 @@ final void writeIntA(int[] v) throws IOException { final void writeLongA(long[] v) throws IOException { if (!tryWriteReference(v)) { writeVarTypeCode(T_LONG_ARRAY, v.length); - // TODO: Optimize by writing chunks. - for (int i=0; i 0) for (int off = 0;;) { + requireOutput(8); + byte[] buf = mOutBuffer; + int end = mOutEnd; + while (true) { + cLongArrayBEHandle.set(buf, end, v[off++]); + end += 8; + if (off >= v.length) { + mOutEnd = end; + return; + } + if (end + 8 > buf.length) { + mOutEnd = end; + break; + } + } } } } diff --git a/src/test/java/org/cojen/dirmi/core/PipeTest.java b/src/test/java/org/cojen/dirmi/core/PipeTest.java index da6d772..efbfa5d 100644 --- a/src/test/java/org/cojen/dirmi/core/PipeTest.java +++ b/src/test/java/org/cojen/dirmi/core/PipeTest.java @@ -363,22 +363,31 @@ public void arrays() throws Exception { Object[] arrays = { randomBooleanArray(rnd, 10, 200), randomBooleanArray(rnd, 300, 1000), + randomBooleanArray(rnd, 1000, 10000), randomCharArray(rnd, 10, 200), randomCharArray(rnd, 300, 1000), + randomCharArray(rnd, 1000, 10000), randomFloatArray(rnd, 10, 200), randomFloatArray(rnd, 300, 1000), + randomFloatArray(rnd, 1000, 10000), randomDoubleArray(rnd, 10, 200), randomDoubleArray(rnd, 300, 1000), + randomDoubleArray(rnd, 1000, 10000), randomByteArray(rnd, 10, 200), randomByteArray(rnd, 300, 1000), + randomByteArray(rnd, 1000, 10000), randomShortArray(rnd, 10, 200), randomShortArray(rnd, 300, 1000), + randomShortArray(rnd, 1000, 10000), randomIntArray(rnd, 10, 200), randomIntArray(rnd, 300, 1000), + randomIntArray(rnd, 1000, 10000), randomLongArray(rnd, 10, 200), randomLongArray(rnd, 300, 1000), + randomLongArray(rnd, 1000, 10000), randomStringArray(rnd, 10, 200), randomStringArray(rnd, 300, 1000), + randomStringArray(rnd, 1000, 10000), new Object[] { true, 'a', 1.23f, 2.34d, (byte) 3, (short) 4, 5, 6L,