Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: base/pickle.cc

Issue 34413002: Pickle::Write* micro-optimizations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/pickle.h" 5 #include "base/pickle.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <algorithm> // for max() 9 #include <algorithm> // for max()
10 10
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 *data = read_from; 147 *data = read_from;
148 return true; 148 return true;
149 } 149 }
150 150
151 // Payload is uint32 aligned. 151 // Payload is uint32 aligned.
152 152
153 Pickle::Pickle() 153 Pickle::Pickle()
154 : header_(NULL), 154 : header_(NULL),
155 header_size_(sizeof(Header)), 155 header_size_(sizeof(Header)),
156 capacity_(0), 156 capacity_(0),
157 variable_buffer_offset_(0) { 157 variable_buffer_offset_(0),
158 offset_(0) {
158 Resize(kPayloadUnit); 159 Resize(kPayloadUnit);
159 header_->payload_size = 0; 160 header_->payload_size = 0;
160 } 161 }
161 162
162 Pickle::Pickle(int header_size) 163 Pickle::Pickle(int header_size)
163 : header_(NULL), 164 : header_(NULL),
164 header_size_(AlignInt(header_size, sizeof(uint32))), 165 header_size_(AlignInt(header_size, sizeof(uint32))),
165 capacity_(0), 166 capacity_(0),
166 variable_buffer_offset_(0) { 167 variable_buffer_offset_(0),
168 offset_(0) {
167 DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); 169 DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header));
168 DCHECK_LE(header_size, kPayloadUnit); 170 DCHECK_LE(header_size, kPayloadUnit);
169 Resize(kPayloadUnit); 171 Resize(kPayloadUnit);
170 header_->payload_size = 0; 172 header_->payload_size = 0;
171 } 173 }
172 174
173 Pickle::Pickle(const char* data, int data_len) 175 Pickle::Pickle(const char* data, int data_len)
174 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), 176 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
175 header_size_(0), 177 header_size_(0),
176 capacity_(kCapacityReadOnly), 178 capacity_(kCapacityReadOnly),
177 variable_buffer_offset_(0) { 179 variable_buffer_offset_(0),
180 offset_(0) {
178 if (data_len >= static_cast<int>(sizeof(Header))) 181 if (data_len >= static_cast<int>(sizeof(Header)))
179 header_size_ = data_len - header_->payload_size; 182 header_size_ = data_len - header_->payload_size;
180 183
181 if (header_size_ > static_cast<unsigned int>(data_len)) 184 if (header_size_ > static_cast<unsigned int>(data_len))
182 header_size_ = 0; 185 header_size_ = 0;
183 186
184 if (header_size_ != AlignInt(header_size_, sizeof(uint32))) 187 if (header_size_ != AlignInt(header_size_, sizeof(uint32)))
185 header_size_ = 0; 188 header_size_ = 0;
186 189
187 // If there is anything wrong with the data, we're not going to use it. 190 // If there is anything wrong with the data, we're not going to use it.
188 if (!header_size_) 191 if (!header_size_)
189 header_ = NULL; 192 header_ = NULL;
190 } 193 }
191 194
192 Pickle::Pickle(const Pickle& other) 195 Pickle::Pickle(const Pickle& other)
193 : header_(NULL), 196 : header_(NULL),
194 header_size_(other.header_size_), 197 header_size_(other.header_size_),
195 capacity_(0), 198 capacity_(0),
196 variable_buffer_offset_(other.variable_buffer_offset_) { 199 variable_buffer_offset_(other.variable_buffer_offset_),
200 offset_(0) {
197 size_t payload_size = header_size_ + other.header_->payload_size; 201 size_t payload_size = header_size_ + other.header_->payload_size;
198 bool resized = Resize(payload_size); 202 bool resized = Resize(payload_size);
199 CHECK(resized); // Realloc failed. 203 CHECK(resized); // Realloc failed.
200 memcpy(header_, other.header_, payload_size); 204 memcpy(header_, other.header_, payload_size);
201 } 205 }
202 206
203 Pickle::~Pickle() { 207 Pickle::~Pickle() {
204 if (capacity_ != kCapacityReadOnly) 208 if (capacity_ != kCapacityReadOnly)
205 free(header_); 209 free(header_);
206 } 210 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 if (new_length < 0 || new_length > *cur_length) { 301 if (new_length < 0 || new_length > *cur_length) {
298 NOTREACHED() << "Invalid length in TrimWriteData."; 302 NOTREACHED() << "Invalid length in TrimWriteData.";
299 return; 303 return;
300 } 304 }
301 305
302 // Update the payload size and variable buffer size 306 // Update the payload size and variable buffer size
303 header_->payload_size -= (*cur_length - new_length); 307 header_->payload_size -= (*cur_length - new_length);
304 *cur_length = new_length; 308 *cur_length = new_length;
305 } 309 }
306 310
311 void Pickle::Reserve(size_t length) {
312 size_t needed_size = header_->payload_size + length;
313 if (needed_size > capacity_)
314 Resize(std::max(capacity_ * 2, needed_size));
danakj 2013/10/22 17:22:05 This will generally cause 2 resizes instead of one
danakj 2013/10/22 17:23:16 Maybe add them instead of max?
danakj 2013/10/22 18:23:54 I added another test with 1000 render passes inste
piman 2013/10/24 06:17:14 I rebased on top of your patch (that does this).
315 }
316
307 char* Pickle::BeginWrite(size_t length) { 317 char* Pickle::BeginWrite(size_t length) {
308 // write at a uint32-aligned offset from the beginning of the header 318 size_t data_len = AlignInt(length, sizeof(uint32));
309 size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); 319 size_t new_size = header_->payload_size + data_len;
310 320 if (new_size > capacity_)
311 size_t new_size = offset + length; 321 Resize(std::max(capacity_ * 2, new_size));
312 size_t needed_size = header_size_ + new_size;
313 if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
314 return NULL;
piman 2013/10/22 06:05:58 behavior change: Resize can only fail when realloc
315 322
316 #ifdef ARCH_CPU_64_BITS 323 #ifdef ARCH_CPU_64_BITS
317 DCHECK_LE(length, kuint32max); 324 DCHECK_LE(length, kuint32max);
318 #endif 325 #endif
319 326
320 header_->payload_size = static_cast<uint32>(new_size); 327 char* data = mutable_payload() + header_->payload_size;
321 return mutable_payload() + offset; 328 header_->payload_size = new_size;
piman 2013/10/22 06:05:58 behavior change: header_->payload_size now counts
piman 2013/10/24 06:17:14 I fixed this.
329 offset_ = new_size;
330 return data;
322 } 331 }
323 332
324 void Pickle::EndWrite(char* dest, int length) { 333 void Pickle::EndWrite(char* dest, int length) {
325 // Zero-pad to keep tools like valgrind from complaining about uninitialized 334 // Zero-pad to keep tools like valgrind from complaining about uninitialized
326 // memory. 335 // memory.
327 if (length % sizeof(uint32)) 336 if (length % sizeof(uint32))
328 memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32))); 337 memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32)));
329 } 338 }
330 339
331 bool Pickle::Resize(size_t new_capacity) { 340 bool Pickle::Resize(size_t new_capacity) {
danakj 2013/10/22 17:22:05 make it void?
piman 2013/10/24 06:17:14 rebased on top of your patch that does this.
332 new_capacity = AlignInt(new_capacity, kPayloadUnit); 341 new_capacity = AlignInt(new_capacity, kPayloadUnit);
333 342
334 CHECK_NE(capacity_, kCapacityReadOnly); 343 CHECK_NE(capacity_, kCapacityReadOnly);
335 void* p = realloc(header_, new_capacity); 344 void* p = realloc(header_, new_capacity + header_size_);
336 if (!p) 345 if (!p)
337 return false; 346 return false;
338 347
339 header_ = reinterpret_cast<Header*>(p); 348 header_ = reinterpret_cast<Header*>(p);
340 capacity_ = new_capacity; 349 capacity_ = new_capacity;
341 return true; 350 return true;
342 } 351 }
343 352
344 // static 353 // static
345 const char* Pickle::FindNext(size_t header_size, 354 const char* Pickle::FindNext(size_t header_size,
346 const char* start, 355 const char* start,
347 const char* end) { 356 const char* end) {
348 DCHECK_EQ(header_size, AlignInt(header_size, sizeof(uint32))); 357 DCHECK_EQ(header_size, AlignInt(header_size, sizeof(uint32)));
349 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); 358 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
350 359
351 if (static_cast<size_t>(end - start) < sizeof(Header)) 360 if (static_cast<size_t>(end - start) < sizeof(Header))
352 return NULL; 361 return NULL;
353 362
354 const Header* hdr = reinterpret_cast<const Header*>(start); 363 const Header* hdr = reinterpret_cast<const Header*>(start);
355 const char* payload_base = start + header_size; 364 const char* payload_base = start + header_size;
356 const char* payload_end = payload_base + hdr->payload_size; 365 const char* payload_end = payload_base + hdr->payload_size;
357 if (payload_end < payload_base) 366 if (payload_end < payload_base)
358 return NULL; 367 return NULL;
359 368
360 return (payload_end > end) ? NULL : payload_end; 369 return (payload_end > end) ? NULL : payload_end;
361 } 370 }
371
372 #if 1
373 template <size_t length> void Pickle::WriteBytesStatic(const void* data) {
374 DCHECK_NE(kCapacityReadOnly, capacity_) << "oops: pickle is readonly";
375 #ifdef ARCH_CPU_64_BITS
376 DCHECK_LE(length, kuint32max);
377 #endif
378 size_t data_len = AlignInt(length, sizeof(uint32));
piman 2013/10/22 06:05:58 This gets optimized out for length%4==0
379 size_t new_size = offset_ + data_len;
380 if (new_size > capacity_) {
381 Resize(std::max(capacity_ * 2, new_size));
piman 2013/10/22 06:05:58 I tried to amortize the cost of this with the Rese
danakj 2013/10/22 17:22:05 If Reserve gave you a buffer larger than just what
382 }
383
384 char* write = mutable_payload() + offset_;
385 memcpy(write, data, length);
386 memset(write + length, 0, data_len - length);
piman 2013/10/22 06:05:58 This gets optimized out too for length%4==0
387 offset_ = new_size;
388 header_->payload_size = new_size;
389 }
390
391 template void Pickle::WriteBytesStatic<2>(const void* data);
392 template void Pickle::WriteBytesStatic<4>(const void* data);
393 template void Pickle::WriteBytesStatic<8>(const void* data);
394 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698