diff options
author | Andrew Stitcher <astitcher@apache.org> | 2012-03-05 23:55:50 +0000 |
---|---|---|
committer | Andrew Stitcher <astitcher@apache.org> | 2012-03-05 23:55:50 +0000 |
commit | 9c8792e7e20fb73196326a31ca299d220e9a8078 (patch) | |
tree | 7f335ec84128ff2e5cf265d80ff81bf37a533060 | |
parent | 47fb332cc91310afbb49af74b5d0f11b1efdaaa1 (diff) | |
download | qpid-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.h | 4 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/framing/FieldTable.cpp | 36 |
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; } |