From b573526a0dc68d70846ccf7a3b031233e2f2bfcd Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 11 Sep 2010 21:48:36 +0300 Subject: [PATCH] optimized writeInt --- .../java/redis/clients/jedis/Protocol.java | 48 ++--------- .../redis/clients/util/RedisOutputStream.java | 79 ++++++++++++++++++- 2 files changed, 83 insertions(+), 44 deletions(-) diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 8cf6171..0b749be 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -11,12 +11,7 @@ import java.util.List; public class Protocol { public static final Charset CHARSET = Charset.forName("UTF-8"); - private static final ThreadLocal CHARSET_ENCODER = new ThreadLocal (){ - @Override - protected CharsetEncoder initialValue() { - return CHARSET.newEncoder(); - } - }; + private final CharsetEncoder CHARSET_ENCODER = CHARSET.newEncoder(); public static final String DOLLAR = "$"; public static final String ASTERISK = "*"; @@ -24,8 +19,7 @@ public class Protocol { public static final String MINUS = "-"; public static final String COLON = ":"; public static final String COMMAND_DELIMITER = "\r\n"; - public static final byte[] COMMAND_DELIMITER_BYTES = "\r\n" - .getBytes(CHARSET); + public static final byte[] COMMAND_DELIMITER_BYTES = "\r\n".getBytes(CHARSET); public static final int DEFAULT_PORT = 6379; public static final byte DOLLAR_BYTE = DOLLAR.getBytes(CHARSET)[0]; @@ -36,15 +30,13 @@ public class Protocol { public void sendCommand(RedisOutputStream os, String name, String... args) { try { - final CharsetEncoder encoder = CHARSET_ENCODER.get(); - os.write(ASTERISK_BYTE); - os.write(String.valueOf(args.length + 1), encoder); + os.writeInt(args.length + 1); os.write(COMMAND_DELIMITER_BYTES); os.write(DOLLAR_BYTE); - os.write(String.valueOf(name.length()), encoder); + os.writeInt(name.length()); os.write(COMMAND_DELIMITER_BYTES); - os.write(name, encoder); + os.writeString(name, CHARSET_ENCODER); os.write(COMMAND_DELIMITER_BYTES); for (String arg : args) { @@ -52,7 +44,7 @@ public class Protocol { int size = bytes.length; os.write(DOLLAR_BYTE); - os.write(String.valueOf(size), encoder); + os.writeInt(size); os.write(COMMAND_DELIMITER_BYTES); os.write(bytes); os.write(COMMAND_DELIMITER_BYTES); @@ -61,34 +53,6 @@ public class Protocol { } catch (IOException e) { throw new JedisException(e); } - -// try { -// os.write(os.toByteArray()); - /* - os.write(ASTERISK_BYTE); - os.write((new Integer(args.length + 1)).toString() - .getBytes(CHARSET)); - os.write(COMMAND_DELIMITER_BYTES); - os.write(DOLLAR_BYTE); - os.write((new Integer(name.length())).toString().getBytes(CHARSET)); - os.write(COMMAND_DELIMITER_BYTES); - os.write(name.getBytes(CHARSET)); - os.write(COMMAND_DELIMITER_BYTES); - - for (String arg : args) { - byte[] barg = arg.getBytes(CHARSET); - - os.write(DOLLAR_BYTE); - os.write((new Integer(barg.length)).toString() - .getBytes(CHARSET)); - os.write(COMMAND_DELIMITER_BYTES); - os.write(barg); - os.write(COMMAND_DELIMITER_BYTES); - } - */ -// } catch (IOException e) { -// throw new JedisException(e); -// } } public void processError(DataInputStream is) { diff --git a/src/main/java/redis/clients/util/RedisOutputStream.java b/src/main/java/redis/clients/util/RedisOutputStream.java index 18108fe..85d4324 100644 --- a/src/main/java/redis/clients/util/RedisOutputStream.java +++ b/src/main/java/redis/clients/util/RedisOutputStream.java @@ -61,7 +61,7 @@ public final class RedisOutputStream extends FilterOutputStream { } } - public void write(String str, CharsetEncoder encoder) throws IOException { + public void writeString(String str, CharsetEncoder encoder) throws IOException { final CharBuffer in = CharBuffer.wrap(str); if (in.remaining() == 0) return; @@ -91,8 +91,83 @@ public final class RedisOutputStream extends FilterOutputStream { } } + private final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; + + private final static byte [] DigitTens = { + '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', + '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', + '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', + '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', + '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', + '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', + '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', + '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', + '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', + '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', + } ; + + private final static byte [] DigitOnes = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + } ; + + private final static byte[] digits = { + '0' , '1' , '2' , '3' , '4' , '5' , + '6' , '7' , '8' , '9' , 'a' , 'b' , + 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , + 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , + 'o' , 'p' , 'q' , 'r' , 's' , 't' , + 'u' , 'v' , 'w' , 'x' , 'y' , 'z' + }; + + public void writeInt(int value) throws IOException { + if(value < 0) { + write('-'); + value = -value; + } + + int size = 0; + while (value > sizeTable[size]) + size++; + + size++; + if (size >= buf.length - count) { + flushBuffer(); + } + + int q, r; + int charPos = count + size; + char sign = 0; + + // Generate two digits per iteration + while ( value >= 65536) { + q = value / 100; + r = value - ((q << 6) + (q << 5) + (q << 2)); + value = q; + buf [--charPos] = DigitOnes[r]; + buf [--charPos] = DigitTens[r]; + } + + for (;;) { + q = (value * 52429) >>> (16+3); + r = value - ((q << 3) + (q << 1)); // r = i-(q*10) ... + buf [--charPos] = digits [r]; + value = q; + if (value == 0) break; + } + count += size; + } + public void flush() throws IOException { flushBuffer(); out.flush(); } -} +} \ No newline at end of file