From aeb106ee12b94bcf630e87caa36143b3db72ec4f Mon Sep 17 00:00:00 2001 From: Roberto Navarro Date: Mon, 30 Jul 2018 10:13:54 +0200 Subject: [PATCH 1/3] Improve performance of readLong function unrolling loop and using bitwise operators instead of additions --- .../java/com/microsoft/sqlserver/jdbc/Util.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java index d1536e735..2f6e420fb 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java @@ -197,12 +197,14 @@ static BigDecimal readBigDecimal(byte valueBytes[], int valueLength, int scale) * @return long value as read from bytes. */ /* L0 */static long readLong(byte data[], int nOffset) { - long v = 0; - for (int i = 7; i > 0; i--) { - v += (long) (data[nOffset + i] & 0xff); - v <<= 8; - } - return v + (long) (data[nOffset] & 0xff); + return ((long) (data[nOffset + 7] & 0xff) << 56) + | ((long) (data[nOffset + 6] & 0xff) << 48) + | ((long) (data[nOffset + 5] & 0xff) << 40) + | ((long) (data[nOffset + 4] & 0xff) << 32) + | ((long) (data[nOffset + 3] & 0xff) << 24) + | ((long) (data[nOffset + 2] & 0xff) << 16) + | ((long) (data[nOffset + 1] & 0xff) << 8) + | ((long) (data[nOffset] & 0xff)); } /** From e52a793258cd74a8e0b535f3d301230ea3f1387c Mon Sep 17 00:00:00 2001 From: Roberto Navarro Date: Sun, 5 Aug 2018 13:10:48 +0200 Subject: [PATCH 2/3] Improve performance of readLong function unrolling loop and using bitwise operators instead of additions + unit test --- .../microsoft/sqlserver/jdbc/IOBuffer.java | 9 +------- .../com/microsoft/sqlserver/jdbc/Util.java | 21 +++++++++++++++++++ .../microsoft/sqlserver/jdbc/UtilTest.java | 18 ++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index f08262347..00820d0f6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -3629,14 +3629,7 @@ void writeLong(long value) throws SQLServerException { ((Buffer) logBuffer).position(((Buffer) logBuffer).position() + 8); } } else { - valueBytes[0] = (byte) ((value >> 0) & 0xFF); - valueBytes[1] = (byte) ((value >> 8) & 0xFF); - valueBytes[2] = (byte) ((value >> 16) & 0xFF); - valueBytes[3] = (byte) ((value >> 24) & 0xFF); - valueBytes[4] = (byte) ((value >> 32) & 0xFF); - valueBytes[5] = (byte) ((value >> 40) & 0xFF); - valueBytes[6] = (byte) ((value >> 48) & 0xFF); - valueBytes[7] = (byte) ((value >> 56) & 0xFF); + Util.writeLong(value, valueBytes, 0); writeWrappedBytes(valueBytes, 8); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java index 2f6e420fb..cefbd0a62 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java @@ -207,6 +207,27 @@ static BigDecimal readBigDecimal(byte valueBytes[], int valueLength, int scale) | ((long) (data[nOffset] & 0xff)); } + /** + * Writes a long to byte array. + * + * @param value + * long value to write. + * @param valueBytes + * the byte array. + * @param offset + * the offset inside byte array. + */ + public static void writeLong(long value, byte valueBytes[], int offset) { + valueBytes[offset++] = (byte) ((value) & 0xFF); + valueBytes[offset++] = (byte) ((value >> 8) & 0xFF); + valueBytes[offset++] = (byte) ((value >> 16) & 0xFF); + valueBytes[offset++] = (byte) ((value >> 24) & 0xFF); + valueBytes[offset++] = (byte) ((value >> 32) & 0xFF); + valueBytes[offset++] = (byte) ((value >> 40) & 0xFF); + valueBytes[offset++] = (byte) ((value >> 48) & 0xFF); + valueBytes[offset] = (byte) ((value >> 56) & 0xFF); + } + /** * Parse a JDBC URL into a set of properties. * diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/UtilTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/UtilTest.java index e19d02000..13c76c0f9 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/UtilTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/UtilTest.java @@ -28,4 +28,22 @@ public void readGUIDtoUUID() throws SQLException { assertEquals(expected, Util.readGUIDtoUUID(guid)); } + @Test + public void testLongConversions() { + writeAndReadLong(Long.MIN_VALUE); + writeAndReadLong(Long.MIN_VALUE / 2); + writeAndReadLong(-1); + writeAndReadLong(0); + writeAndReadLong(1); + writeAndReadLong(Long.MAX_VALUE / 2); + writeAndReadLong(Long.MAX_VALUE); + } + + private void writeAndReadLong(long valueToTest) { + byte[] buffer = new byte[8]; + Util.writeLong(valueToTest, buffer, 0); + long newLong = Util.readLong(buffer, 0); + assertEquals(valueToTest, newLong); + } + } From 310a52f36520bd6b422793f7c62c447c1c8388ea Mon Sep 17 00:00:00 2001 From: Roberto Navarro Date: Thu, 16 Aug 2018 06:54:26 +0200 Subject: [PATCH 3/3] Restrict writeLong method visibility --- src/main/java/com/microsoft/sqlserver/jdbc/Util.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java index cefbd0a62..f3501be4b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java @@ -217,7 +217,7 @@ static BigDecimal readBigDecimal(byte valueBytes[], int valueLength, int scale) * @param offset * the offset inside byte array. */ - public static void writeLong(long value, byte valueBytes[], int offset) { + static void writeLong(long value, byte valueBytes[], int offset) { valueBytes[offset++] = (byte) ((value) & 0xFF); valueBytes[offset++] = (byte) ((value >> 8) & 0xFF); valueBytes[offset++] = (byte) ((value >> 16) & 0xFF);