summaryrefslogtreecommitdiffstats
path: root/base/pickle.cc
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-31 04:03:02 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-31 04:03:02 +0000
commitd1b319fc3f77e744fb325a5a28b6ae448072a9ae (patch)
treecd4b30de4c88a730eaf2fe04cf02c6b10f227a25 /base/pickle.cc
parenta979d27b84e0c363e0a3e640890a098374a5883b (diff)
downloadchromium_src-d1b319fc3f77e744fb325a5a28b6ae448072a9ae.zip
chromium_src-d1b319fc3f77e744fb325a5a28b6ae448072a9ae.tar.gz
chromium_src-d1b319fc3f77e744fb325a5a28b6ae448072a9ae.tar.bz2
Pickle::Write* micro-optimizations
Pickle is hot in some benchmarks. This helps by reworking WriteBytes in a few of ways: 1- Fold BeginWrite and EndWrite into WriteBytes since it's the only caller now. 2- keep track of the write offset, always aligned, separately, so that we can do alignment checks on the field sizes rather than the payload size (for next point). 3- provides a template version of WriteBytes with specializations for predefined sizes, that inline/optimize away alignment checks, padding, and memcpy. 4- change the meaning of capacity_ to not take the header size into account. This simplifies some arithmetic. BUG=307480 R=jar@chromium.org Review URL: https://codereview.chromium.org/34413002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231987 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/pickle.cc')
-rw-r--r--base/pickle.cc117
1 files changed, 58 insertions, 59 deletions
diff --git a/base/pickle.cc b/base/pickle.cc
index 1d06af3..c88503c 100644
--- a/base/pickle.cc
+++ b/base/pickle.cc
@@ -153,7 +153,8 @@ bool PickleIterator::ReadBytes(const char** data, int length) {
Pickle::Pickle()
: header_(NULL),
header_size_(sizeof(Header)),
- capacity_(0) {
+ capacity_after_header_(0),
+ write_offset_(0) {
Resize(kPayloadUnit);
header_->payload_size = 0;
}
@@ -161,7 +162,8 @@ Pickle::Pickle()
Pickle::Pickle(int header_size)
: header_(NULL),
header_size_(AlignInt(header_size, sizeof(uint32))),
- capacity_(0) {
+ capacity_after_header_(0),
+ write_offset_(0) {
DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header));
DCHECK_LE(header_size, kPayloadUnit);
Resize(kPayloadUnit);
@@ -171,7 +173,8 @@ Pickle::Pickle(int header_size)
Pickle::Pickle(const char* data, size_t data_len)
: header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
header_size_(0),
- capacity_(kCapacityReadOnly) {
+ capacity_after_header_(kCapacityReadOnly),
+ write_offset_(0) {
if (data_len >= sizeof(Header))
header_size_ = data_len - header_->payload_size;
@@ -189,15 +192,15 @@ Pickle::Pickle(const char* data, size_t data_len)
Pickle::Pickle(const Pickle& other)
: header_(NULL),
header_size_(other.header_size_),
- capacity_(0) {
+ capacity_after_header_(0),
+ write_offset_(other.write_offset_) {
size_t payload_size = header_size_ + other.header_->payload_size;
- bool resized = Resize(payload_size);
- CHECK(resized); // Realloc failed.
+ Resize(payload_size);
memcpy(header_, other.header_, payload_size);
}
Pickle::~Pickle() {
- if (capacity_ != kCapacityReadOnly)
+ if (capacity_after_header_ != kCapacityReadOnly)
free(header_);
}
@@ -206,19 +209,19 @@ Pickle& Pickle::operator=(const Pickle& other) {
NOTREACHED();
return *this;
}
- if (capacity_ == kCapacityReadOnly) {
+ if (capacity_after_header_ == kCapacityReadOnly) {
header_ = NULL;
- capacity_ = 0;
+ capacity_after_header_ = 0;
}
if (header_size_ != other.header_size_) {
free(header_);
header_ = NULL;
header_size_ = other.header_size_;
}
- bool resized = Resize(other.header_size_ + other.header_->payload_size);
- CHECK(resized); // Realloc failed.
+ Resize(other.header_->payload_size);
memcpy(header_, other.header_,
other.header_size_ + other.header_->payload_size);
+ write_offset_ = other.write_offset_;
return *this;
}
@@ -249,64 +252,31 @@ bool Pickle::WriteData(const char* data, int length) {
return length >= 0 && WriteInt(length) && WriteBytes(data, length);
}
-bool Pickle::WriteBytes(const void* data, int data_len) {
- DCHECK_NE(kCapacityReadOnly, capacity_) << "oops: pickle is readonly";
-
- char* dest = BeginWrite(data_len);
- if (!dest)
- return false;
-
- memcpy(dest, data, data_len);
-
- EndWrite(dest, data_len);
+bool Pickle::WriteBytes(const void* data, int length) {
+ WriteBytesCommon(data, length);
return true;
}
-void Pickle::Reserve(size_t additional_capacity) {
- // Write at a uint32-aligned offset from the beginning of the header.
- size_t offset = AlignInt(header_->payload_size, sizeof(uint32));
-
- size_t new_size = offset + additional_capacity;
- size_t needed_size = header_size_ + new_size;
- if (needed_size > capacity_)
- Resize(capacity_ * 2 + needed_size);
-}
-
-char* Pickle::BeginWrite(size_t length) {
- // Write at a uint32-aligned offset from the beginning of the header.
- size_t offset = AlignInt(header_->payload_size, sizeof(uint32));
-
- size_t new_size = offset + length;
- size_t needed_size = header_size_ + new_size;
- if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
- return NULL;
-
+void Pickle::Reserve(size_t length) {
+ size_t data_len = AlignInt(length, sizeof(uint32));
+ DCHECK_GE(data_len, length);
#ifdef ARCH_CPU_64_BITS
- DCHECK_LE(length, kuint32max);
+ DCHECK_LE(data_len, kuint32max);
#endif
-
- header_->payload_size = static_cast<uint32>(new_size);
- return mutable_payload() + offset;
-}
-
-void Pickle::EndWrite(char* dest, int length) {
- // Zero-pad to keep tools like valgrind from complaining about uninitialized
- // memory.
- if (length % sizeof(uint32))
- memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32)));
+ DCHECK_LE(write_offset_, kuint32max - data_len);
+ size_t new_size = write_offset_ + data_len;
+ if (new_size > capacity_after_header_)
+ Resize(capacity_after_header_ * 2 + new_size);
}
-bool Pickle::Resize(size_t new_capacity) {
+void Pickle::Resize(size_t new_capacity) {
new_capacity = AlignInt(new_capacity, kPayloadUnit);
- CHECK_NE(capacity_, kCapacityReadOnly);
- void* p = realloc(header_, new_capacity);
- if (!p)
- return false;
-
+ CHECK_NE(capacity_after_header_, kCapacityReadOnly);
+ void* p = realloc(header_, header_size_ + new_capacity);
+ CHECK(p);
header_ = reinterpret_cast<Header*>(p);
- capacity_ = new_capacity;
- return true;
+ capacity_after_header_ = new_capacity;
}
// static
@@ -327,3 +297,32 @@ const char* Pickle::FindNext(size_t header_size,
return (payload_end > end) ? NULL : payload_end;
}
+
+template <size_t length> void Pickle::WriteBytesStatic(const void* data) {
+ WriteBytesCommon(data, length);
+}
+
+template void Pickle::WriteBytesStatic<2>(const void* data);
+template void Pickle::WriteBytesStatic<4>(const void* data);
+template void Pickle::WriteBytesStatic<8>(const void* data);
+
+inline void Pickle::WriteBytesCommon(const void* data, size_t length) {
+ DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
+ << "oops: pickle is readonly";
+ size_t data_len = AlignInt(length, sizeof(uint32));
+ DCHECK_GE(data_len, length);
+#ifdef ARCH_CPU_64_BITS
+ DCHECK_LE(data_len, kuint32max);
+#endif
+ DCHECK_LE(write_offset_, kuint32max - data_len);
+ size_t new_size = write_offset_ + data_len;
+ if (new_size > capacity_after_header_) {
+ Resize(std::max(capacity_after_header_ * 2, new_size));
+ }
+
+ char* write = mutable_payload() + write_offset_;
+ memcpy(write, data, length);
+ memset(write + length, 0, data_len - length);
+ header_->payload_size = static_cast<uint32>(write_offset_ + length);
+ write_offset_ = new_size;
+}