Skip to content

Commit

Permalink
Use memset() to optimize prevector::resize()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
eklitzke committed Feb 27, 2018
1 parent e46be25 commit 5aad635
Showing 1 changed file with 25 additions and 6 deletions.
31 changes: 25 additions & 6 deletions src/prevector.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
#include <stdint.h>
#include <string.h>

#include <cstddef>
#include <iterator>
#include <type_traits>

#include <compat.h>

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

void fill(T* dst, size_type count, const T& value) {
for (size_type i = 0; i < count; ++i) {
void fill(T* dst, ptrdiff_t count) {
if (IS_TRIVIALLY_CONSTRUCTIBLE<T>::value) {
// The most common use of prevector is where T=unsigned char. For
// trivially constructible types, we can use memset() to avoid
// looping.
::memset(dst, 0, count * sizeof(T));
} else {
for (auto i = 0; i < count; ++i) {
new(static_cast<void*>(dst + i)) T();
}
}
}

void fill(T* dst, ptrdiff_t count, const T& value) {
for (auto i = 0; i < count; ++i) {
new(static_cast<void*>(dst + i)) T(value);
}
}
Expand Down Expand Up @@ -310,16 +326,19 @@ class prevector {

void resize(size_type new_size) {
size_type cur_size = size();
if (cur_size == new_size) {
return;
}
if (cur_size > new_size) {
erase(item_ptr(new_size), end());
return;
}
if (new_size > capacity()) {
change_capacity(new_size);
}
for (T* p = item_ptr(0); cur_size < new_size; cur_size++) {
_size++;
new(static_cast<void*>(p + cur_size)) T();
}
ptrdiff_t increase = new_size - cur_size;
fill(item_ptr(cur_size), increase);
_size += increase;
}

void reserve(size_type new_capacity) {
Expand Down

0 comments on commit 5aad635

Please sign in to comment.