Skip to content

Commit 5aad635

Browse files
committed
Use memset() to optimize prevector::resize()
Further optimize prevector::resize() (which is called by a number of other prevector methods) to use memset to initialize memory when the prevector contains trivial types.
1 parent e46be25 commit 5aad635

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

src/prevector.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
#include <stdint.h>
1111
#include <string.h>
1212

13+
#include <cstddef>
1314
#include <iterator>
1415
#include <type_traits>
1516

17+
#include <compat.h>
18+
1619
#pragma pack(push, 1)
1720
/** Implements a drop-in replacement for std::vector<T> which stores up to N
1821
* elements directly (without heap allocation). The types Size and Diff are
@@ -194,8 +197,21 @@ class prevector {
194197
T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
195198
const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
196199

197-
void fill(T* dst, size_type count, const T& value) {
198-
for (size_type i = 0; i < count; ++i) {
200+
void fill(T* dst, ptrdiff_t count) {
201+
if (IS_TRIVIALLY_CONSTRUCTIBLE<T>::value) {
202+
// The most common use of prevector is where T=unsigned char. For
203+
// trivially constructible types, we can use memset() to avoid
204+
// looping.
205+
::memset(dst, 0, count * sizeof(T));
206+
} else {
207+
for (auto i = 0; i < count; ++i) {
208+
new(static_cast<void*>(dst + i)) T();
209+
}
210+
}
211+
}
212+
213+
void fill(T* dst, ptrdiff_t count, const T& value) {
214+
for (auto i = 0; i < count; ++i) {
199215
new(static_cast<void*>(dst + i)) T(value);
200216
}
201217
}
@@ -310,16 +326,19 @@ class prevector {
310326

311327
void resize(size_type new_size) {
312328
size_type cur_size = size();
329+
if (cur_size == new_size) {
330+
return;
331+
}
313332
if (cur_size > new_size) {
314333
erase(item_ptr(new_size), end());
334+
return;
315335
}
316336
if (new_size > capacity()) {
317337
change_capacity(new_size);
318338
}
319-
for (T* p = item_ptr(0); cur_size < new_size; cur_size++) {
320-
_size++;
321-
new(static_cast<void*>(p + cur_size)) T();
322-
}
339+
ptrdiff_t increase = new_size - cur_size;
340+
fill(item_ptr(cur_size), increase);
341+
_size += increase;
323342
}
324343

325344
void reserve(size_type new_capacity) {

0 commit comments

Comments
 (0)