From fc1e4c575acf0a9a6aba67b5e37bfc132ae386be Mon Sep 17 00:00:00 2001 From: Robert Gemmell Date: Thu, 17 Feb 2011 16:16:45 +0000 Subject: QPID-3028: use a small array and companion HashMap to store the incomplete Methods, rather than pre-allocating a 64000 entry array git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1071675 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/qpid/transport/network/Assembler.java | 55 +++++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java index b3c419959c..1a85ab88a5 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java @@ -20,15 +20,12 @@ */ package org.apache.qpid.transport.network; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.nio.ByteBuffer; - -import org.apache.qpid.transport.codec.BBDecoder; - import org.apache.qpid.transport.Header; import org.apache.qpid.transport.Method; import org.apache.qpid.transport.ProtocolError; @@ -36,19 +33,22 @@ import org.apache.qpid.transport.ProtocolEvent; import org.apache.qpid.transport.ProtocolHeader; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.Struct; - +import org.apache.qpid.transport.codec.BBDecoder; /** * Assembler * */ - public class Assembler implements Receiver, NetworkDelegate { + // Use a small array to store incomplete Methods for low-value channels, instead of allocating a huge + // array or always boxing the channelId and looking it up in the map. This value must be of the form 2^X - 1. + private static final int ARRAY_SIZE = 0xFF; + private final Method[] _incompleteMethodArray = new Method[ARRAY_SIZE + 1]; + private final Map _incompleteMethodMap = new HashMap(); private final Receiver receiver; private final Map> segments; - private final Method[] incomplete; private static final ThreadLocal _decoder = new ThreadLocal() { public BBDecoder initialValue() @@ -61,7 +61,6 @@ public class Assembler implements Receiver, NetworkDelegate { this.receiver = receiver; segments = new HashMap>(); - incomplete = new Method[64*1024]; } private int segmentKey(Frame frame) @@ -190,7 +189,7 @@ public class Assembler implements Receiver, NetworkDelegate command.read(dec); if (command.hasPayload()) { - incomplete[channel] = command; + setIncompleteCommand(channel, command); } else { @@ -198,7 +197,7 @@ public class Assembler implements Receiver, NetworkDelegate } break; case HEADER: - command = incomplete[channel]; + command = getIncompleteCommand(channel); List structs = new ArrayList(2); while (dec.hasRemaining()) { @@ -207,14 +206,14 @@ public class Assembler implements Receiver, NetworkDelegate command.setHeader(new Header(structs)); if (frame.isLastSegment()) { - incomplete[channel] = null; + setIncompleteCommand(channel, null); emit(channel, command); } break; case BODY: - command = incomplete[channel]; + command = getIncompleteCommand(channel); command.setBody(segment); - incomplete[channel] = null; + setIncompleteCommand(channel, null); emit(channel, command); break; default: @@ -224,4 +223,34 @@ public class Assembler implements Receiver, NetworkDelegate dec.releaseBuffer(); } + private void setIncompleteCommand(int channelId, Method incomplete) + { + if ((channelId & ARRAY_SIZE) == channelId) + { + _incompleteMethodArray[channelId] = incomplete; + } + else + { + if(incomplete != null) + { + _incompleteMethodMap.put(channelId, incomplete); + } + else + { + _incompleteMethodMap.remove(channelId); + } + } + } + + private Method getIncompleteCommand(int channelId) + { + if ((channelId & ARRAY_SIZE) == channelId) + { + return _incompleteMethodArray[channelId]; + } + else + { + return _incompleteMethodMap.get(channelId); + } + } } -- cgit v1.2.1