[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [dferry] serialization: Arguments::Writer: space optimization for variant signatures.
From: Andreas Hartmetz <ahartmetz () gmail ! com>
Date: 2016-10-12 0:57:07
Message-ID: E1bu7r1-0007PZ-Sd () code ! kde ! org
[Download RAW message or body]
Git commit ddc7350648da7929c30c735cc5d55dadff187f39 by Andreas Hartmetz.
Committed on 11/10/2016 at 22:08.
Pushed by ahartmetz into branch 'master'.
Arguments::Writer: space optimization for variant signatures.
- Estimate the output buffer size more tightly
- Don't store the null terminator in m_data, add it later. This
is more about access patterns, and thus time, than space.
- Also some micro-optimizations for time, not space
M +26 -16 serialization/arguments.cpp
http://commits.kde.org/dferry/ddc7350648da7929c30c735cc5d55dadff187f39
diff --git a/serialization/arguments.cpp b/serialization/arguments.cpp
index f2a1070..f5193d0 100644
--- a/serialization/arguments.cpp
+++ b/serialization/arguments.cpp
@@ -152,6 +152,7 @@ public:
Private()
: m_signature(m_initialDataBuffer, 0),
m_signaturePosition(0),
+ m_variantSignaturesWastedSpace(0),
m_data(m_initialDataBuffer),
m_dataCapacity(InitialDataCapacity),
m_dataPosition(MaxFullSignatureLength),
@@ -191,6 +192,7 @@ public:
NestingWithParenCounter m_nesting;
cstring m_signature;
uint32 m_signaturePosition;
+ int32 m_variantSignaturesWastedSpace;
byte *m_data;
uint32 m_dataCapacity;
@@ -202,7 +204,6 @@ public:
enum {
InitialDataCapacity = 512,
// max signature length w/ length prefix (1 byte) and terminator (1 byte)
- // TODO can we add the length prefix during variant signature fixup?
MaxFullSignatureLength = MaxSignatureLength + 1
};
@@ -2026,6 +2027,9 @@ void Arguments::Writer::advanceState(cstring signatureFragment, \
IoState newState
// (This is a peculiarity of empty arrey handling in this API and has \
nothing to // do with the wire format)
VALID_IF(d->m_signaturePosition > 0, Error::EmptyVariant);
+ assert(d->m_signaturePosition <= MaxSignatureLength); // should have \
been caught earlier + d->m_variantSignaturesWastedSpace += -1 // we don't \
store the null terminator but output does + + \
Private::MaxFullSignatureLength - d->m_signaturePosition; }
d->m_signature.ptr[-1] = byte(d->m_signaturePosition);
@@ -2236,18 +2240,14 @@ void Arguments::Writer::finishInternal()
}
VALID_IF(d->m_nesting.total() == 0, Error::CannotEndArgumentsHere);
assert(!d->m_nilArrayNesting);
+
assert(d->m_signaturePosition <= MaxSignatureLength); // this should have been \
caught before
- d->m_signature.ptr[d->m_signaturePosition] = '\0';
+ // we're going to use the following identity to help the compiler
+ assert(d->m_signature.ptr == reinterpret_cast<char *>(d->m_data) + 1);
d->m_signature.length = d->m_signaturePosition;
- if (d->m_args.d->m_memOwnership) {
- free(d->m_args.d->m_memOwnership);
- }
-
bool success = true;
const uint32 count = d->m_elements.size();
- const uint32 dataSize = d->m_dataPosition;
- d->m_dataPosition = Private::MaxFullSignatureLength;
if (count) {
// Note: if one of signature or data is nonempty, the other must also be \
nonempty. @@ -2261,15 +2261,25 @@ void Arguments::Writer::finishInternal()
// Structs and dict entries are always 8 byte aligned so they add a maximum \
blowup of 7 bytes // each (when they contain a byte).
// Those estimates are very conservative (but easy!), so some space \
optimization is possible. +
+ // This one gets no length prefix, it's just the backing buffer for a \
cstring instance!
const uint32 alignedSigLength = align(d->m_signature.length + 1, 8);
- // TODO dataSize may be hugely oversized if there are many signatures in it, \
make it smaller!
- const uint32 bufferSize = alignedSigLength +
- dataSize * 2 + d->m_nesting.parenCount * 7;
+
+ const uint32 safeEstimatedDataSize =
+ 2 * (d->m_dataPosition - Private::MaxFullSignatureLength // signature is \
in alignedSigLength + - d->m_variantSignaturesWastedSpace)
+ + d->m_nesting.parenCount * 7 // max alignment padding in front of data \
structures + + alignedSigLength;
+
byte *buffer = reinterpret_cast<byte \
*>(malloc(std::max(uint32(Private::InitialDataCapacity),
- bufferSize)));
- memcpy(buffer, d->m_signature.ptr, d->m_signature.length + 1);
- uint32 bufferPos = d->m_signature.length + 1;
- zeroPad(buffer, 8, &bufferPos);
+ \
safeEstimatedDataSize))); + memcpy(buffer, d->m_data + 1, \
d->m_signature.length); + uint32 bufferPos = d->m_signature.length;
+ for (; bufferPos < alignedSigLength; bufferPos++) {
+ buffer[bufferPos] = '\0';
+ }
+
+ d->m_dataPosition = Private::MaxFullSignatureLength;
std::vector<ArrayLengthField> lengthFieldStack;
@@ -2323,7 +2333,7 @@ void Arguments::Writer::finishInternal()
}
break;
case Private::ElementInfo::VariantSignature: {
- // fill in signature (should already include trailing null)
+ // fill in signature and add null terminator
const uint32 length = d->m_data[d->m_dataPosition] + 1; // + \
length prefix
memcpy(buffer + bufferPos, d->m_data + d->m_dataPosition, \
length); buffer[bufferPos + length] = '\0';
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic