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 | 276c7869ea23f5c1933cff91d90fb2387e9e2fcd (patch) | |
| tree | 38c1a3441807298eae643d54afb8245194e71352 /cpp/src | |
| parent | 61eeb68cc7b14382aface77cc8c76f7e8cc2b4c3 (diff) | |
| download | qpid-python-276c7869ea23f5c1933cff91d90fb2387e9e2fcd.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/qpid@1297290 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
| -rw-r--r-- | cpp/src/qpid/framing/FieldTable.cpp | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp index 9d33093df8..b696b5e54f 100644 --- a/cpp/src/qpid/framing/FieldTable.cpp +++ b/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; } |
