summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Stitcher <astitcher@apache.org>2012-03-05 23:55:50 +0000
committerAndrew Stitcher <astitcher@apache.org>2012-03-05 23:55:50 +0000
commit9c8792e7e20fb73196326a31ca299d220e9a8078 (patch)
tree7f335ec84128ff2e5cf265d80ff81bf37a533060
parent47fb332cc91310afbb49af74b5d0f11b1efdaaa1 (diff)
downloadqpid-python-9c8792e7e20fb73196326a31ca299d220e9a8078.tar.gz
QPID-3883: Using application headers in messages causes a very large slowdown
Some more tidying up of the FieldTable implementation: - implement a more selective copy constructor - keep the encoded data in case we are used again - more careful raw bytes cache flush git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1297290 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/cpp/include/qpid/framing/FieldTable.h4
-rw-r--r--qpid/cpp/src/qpid/framing/FieldTable.cpp36
2 files changed, 32 insertions, 8 deletions
diff --git a/qpid/cpp/include/qpid/framing/FieldTable.h b/qpid/cpp/include/qpid/framing/FieldTable.h
index b404a06c9a..2592e8f124 100644
--- a/qpid/cpp/include/qpid/framing/FieldTable.h
+++ b/qpid/cpp/include/qpid/framing/FieldTable.h
@@ -58,7 +58,9 @@ class FieldTable
typedef ValueMap::value_type value_type;
QPID_COMMON_EXTERN FieldTable();
- // Compiler default copy, assignment and destructor are fine
+ QPID_COMMON_EXTERN FieldTable(const FieldTable&);
+ QPID_COMMON_EXTERN FieldTable& operator=(const FieldTable&);
+ // Compiler default destructor fine
QPID_COMMON_EXTERN uint32_t encodedSize() const;
QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
QPID_COMMON_EXTERN void decode(Buffer& buffer);
diff --git a/qpid/cpp/src/qpid/framing/FieldTable.cpp b/qpid/cpp/src/qpid/framing/FieldTable.cpp
index 9d33093df8..b696b5e54f 100644
--- a/qpid/cpp/src/qpid/framing/FieldTable.cpp
+++ b/qpid/cpp/src/qpid/framing/FieldTable.cpp
@@ -36,6 +36,25 @@ FieldTable::FieldTable() :
{
}
+FieldTable::FieldTable(const FieldTable& ft) :
+ cachedBytes(ft.cachedBytes),
+ cachedSize(ft.cachedSize)
+{
+ // Only copy the values if we have no raw data
+ // - copying the map is expensive and we can
+ // reconstruct it if necessary from the raw data
+ if (!cachedBytes && !ft.values.empty()) values = ft.values;
+}
+
+FieldTable& FieldTable::operator=(const FieldTable& ft)
+{
+ FieldTable nft(ft);
+ values.swap(nft.values);
+ cachedBytes.swap(nft.cachedBytes);
+ cachedSize = nft.cachedSize;
+ return (*this);
+}
+
uint32_t FieldTable::encodedSize() const {
if (cachedSize != 0) {
return cachedSize;
@@ -211,18 +230,23 @@ void FieldTable::encode(Buffer& buffer) const {
if (cachedBytes) {
buffer.putRawData(&cachedBytes[0], cachedSize);
} else {
+ uint32_t p = buffer.getPosition();
buffer.putLong(encodedSize() - 4);
buffer.putLong(values.size());
for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) {
buffer.putShortString(i->first);
i->second->encode(buffer);
}
+ // Now create raw bytes in case we are used again
+ cachedSize = buffer.getPosition() - p;
+ cachedBytes = boost::shared_array<uint8_t>(new uint8_t[cachedSize]);
+ buffer.setPosition(p);
+ buffer.getRawData(&cachedBytes[0], cachedSize);
}
}
// Decode lazily - just record the raw bytes until we need them
void FieldTable::decode(Buffer& buffer){
- clear();
if (buffer.available() < 4)
throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
uint32_t p = buffer.getPosition();
@@ -232,6 +256,8 @@ void FieldTable::decode(Buffer& buffer){
if ((available < len) || (available < 4))
throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
}
+ // Throw away previous stored values
+ values.clear();
// Copy data into our buffer
cachedBytes = boost::shared_array<uint8_t>(new uint8_t[len + 4]);
cachedSize = len + 4;
@@ -260,16 +286,12 @@ void FieldTable::realDecode() const
values[name] = ValuePtr(value);
}
}
- cachedSize = len + 4;
- // We've done the delayed decoding throw away the raw data
- // (later on we may find a way to keep this and avoid some
- // other allocations)
- cachedBytes.reset();
}
void FieldTable::flushRawCache() const
{
- cachedBytes.reset();
+ // Avoid recreating shared array unless we actually have one.
+ if (cachedBytes) cachedBytes.reset();
cachedSize = 0;
}