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

Side by Side Diff: webrtc/base/buffer.h

Issue 2078873005: rtc::Buffer: Grow capacity by at least 1.5x to prevent quadratic behavior (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 6 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
« no previous file with comments | « no previous file | webrtc/base/buffer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 } 212 }
213 213
214 // The AppendData functions add data to the end of the buffer. They accept 214 // The AppendData functions add data to the end of the buffer. They accept
215 // the same input types as the constructors. 215 // the same input types as the constructors.
216 template <typename U, 216 template <typename U,
217 typename std::enable_if< 217 typename std::enable_if<
218 internal::BufferCompat<T, U>::value>::type* = nullptr> 218 internal::BufferCompat<T, U>::value>::type* = nullptr>
219 void AppendData(const U* data, size_t size) { 219 void AppendData(const U* data, size_t size) {
220 RTC_DCHECK(IsConsistent()); 220 RTC_DCHECK(IsConsistent());
221 const size_t new_size = size_ + size; 221 const size_t new_size = size_ + size;
222 EnsureCapacity(new_size); 222 EnsureCapacityWithHeadroom(new_size, true);
223 static_assert(sizeof(T) == sizeof(U), ""); 223 static_assert(sizeof(T) == sizeof(U), "");
224 std::memcpy(data_.get() + size_, data, size * sizeof(U)); 224 std::memcpy(data_.get() + size_, data, size * sizeof(U));
225 size_ = new_size; 225 size_ = new_size;
226 RTC_DCHECK(IsConsistent()); 226 RTC_DCHECK(IsConsistent());
227 } 227 }
228 228
229 template <typename U, 229 template <typename U,
230 size_t N, 230 size_t N,
231 typename std::enable_if< 231 typename std::enable_if<
232 internal::BufferCompat<T, U>::value>::type* = nullptr> 232 internal::BufferCompat<T, U>::value>::type* = nullptr>
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 size_ = old_size + written_elements; 265 size_ = old_size + written_elements;
266 RTC_DCHECK(IsConsistent()); 266 RTC_DCHECK(IsConsistent());
267 return written_elements; 267 return written_elements;
268 } 268 }
269 269
270 // Sets the size of the buffer. If the new size is smaller than the old, the 270 // Sets the size of the buffer. If the new size is smaller than the old, the
271 // buffer contents will be kept but truncated; if the new size is greater, 271 // buffer contents will be kept but truncated; if the new size is greater,
272 // the existing contents will be kept and the new space will be 272 // the existing contents will be kept and the new space will be
273 // uninitialized. 273 // uninitialized.
274 void SetSize(size_t size) { 274 void SetSize(size_t size) {
275 EnsureCapacity(size); 275 EnsureCapacityWithHeadroom(size, true);
sprang_webrtc 2016/06/20 09:27:44 Do we really want with headroom here, as it's an e
kwiberg-webrtc 2016/06/20 09:51:31 It's an explicit *size* request, but the caller do
sprang_webrtc 2016/06/20 09:56:28 Acknowledged.
276 size_ = size; 276 size_ = size;
277 } 277 }
278 278
279 // Ensure that the buffer size can be increased to at least capacity without 279 // Ensure that the buffer size can be increased to at least capacity without
280 // further reallocation. (Of course, this operation might need to reallocate 280 // further reallocation. (Of course, this operation might need to reallocate
281 // the buffer.) 281 // the buffer.)
282 void EnsureCapacity(size_t capacity) { 282 void EnsureCapacity(size_t capacity) {
283 RTC_DCHECK(IsConsistent()); 283 // Don't allocate extra headroom, since the user is asking for a specific
284 if (capacity <= capacity_) 284 // capacity.
285 return; 285 EnsureCapacityWithHeadroom(capacity, false);
286 std::unique_ptr<T[]> new_data(new T[capacity]);
287 std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T));
288 data_ = std::move(new_data);
289 capacity_ = capacity;
290 RTC_DCHECK(IsConsistent());
291 } 286 }
292 287
293 // Resets the buffer to zero size without altering capacity. Works even if the 288 // Resets the buffer to zero size without altering capacity. Works even if the
294 // buffer has been moved from. 289 // buffer has been moved from.
295 void Clear() { 290 void Clear() {
296 size_ = 0; 291 size_ = 0;
297 RTC_DCHECK(IsConsistent()); 292 RTC_DCHECK(IsConsistent());
298 } 293 }
299 294
300 // Swaps two buffers. Also works for buffers that have been moved from. 295 // Swaps two buffers. Also works for buffers that have been moved from.
301 friend void swap(BufferT& a, BufferT& b) { 296 friend void swap(BufferT& a, BufferT& b) {
302 using std::swap; 297 using std::swap;
303 swap(a.size_, b.size_); 298 swap(a.size_, b.size_);
304 swap(a.capacity_, b.capacity_); 299 swap(a.capacity_, b.capacity_);
305 swap(a.data_, b.data_); 300 swap(a.data_, b.data_);
306 } 301 }
307 302
308 private: 303 private:
304 void EnsureCapacityWithHeadroom(size_t capacity, bool extra_headroom) {
305 RTC_DCHECK(IsConsistent());
306 if (capacity <= capacity_)
307 return;
308
309 // If the caller asks for extra headroom, ensure that the new capacity is
310 // >= 1.5 times the old capacity. Any constant > 1 is sufficient to prevent
311 // quadratic behavior; as to why we pick 1.5 in particular, see
312 // https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md and
313 // http://www.gahcep.com/cpp-internals-stl-vector-part-1/.
314 const size_t new_capacity =
315 extra_headroom ? std::max(capacity, capacity_ + capacity_ / 2)
316 : capacity;
sprang_webrtc 2016/06/20 09:27:44 This seems a little odd. If capacity > 1.5 * capac
kwiberg-webrtc 2016/06/20 09:51:31 capacity is the requested capacity. If that's >= 1
sprang_webrtc 2016/06/20 09:56:28 OK, fair enough.
317
318 std::unique_ptr<T[]> new_data(new T[new_capacity]);
319 std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T));
320 data_ = std::move(new_data);
321 capacity_ = new_capacity;
322 RTC_DCHECK(IsConsistent());
323 }
324
309 // Precondition for all methods except Clear and the destructor. 325 // Precondition for all methods except Clear and the destructor.
310 // Postcondition for all methods except move construction and move 326 // Postcondition for all methods except move construction and move
311 // assignment, which leave the moved-from object in a possibly inconsistent 327 // assignment, which leave the moved-from object in a possibly inconsistent
312 // state. 328 // state.
313 bool IsConsistent() const { 329 bool IsConsistent() const {
314 return (data_ || capacity_ == 0) && capacity_ >= size_; 330 return (data_ || capacity_ == 0) && capacity_ >= size_;
315 } 331 }
316 332
317 // Called when *this has been moved from. Conceptually it's a no-op, but we 333 // Called when *this has been moved from. Conceptually it's a no-op, but we
318 // can mutate the state slightly to help subsequent sanity checks catch bugs. 334 // can mutate the state slightly to help subsequent sanity checks catch bugs.
(...skipping 14 matching lines...) Expand all
333 size_t capacity_; 349 size_t capacity_;
334 std::unique_ptr<T[]> data_; 350 std::unique_ptr<T[]> data_;
335 }; 351 };
336 352
337 // By far the most common sort of buffer. 353 // By far the most common sort of buffer.
338 using Buffer = BufferT<uint8_t>; 354 using Buffer = BufferT<uint8_t>;
339 355
340 } // namespace rtc 356 } // namespace rtc
341 357
342 #endif // WEBRTC_BASE_BUFFER_H_ 358 #endif // WEBRTC_BASE_BUFFER_H_
OLDNEW
« no previous file with comments | « no previous file | webrtc/base/buffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698