Skip to content

Commit 551395f

Browse files
committed
Use default init allocator for vectors
This speeds up our case as we don't need to zero the memory first.
1 parent 1360667 commit 551395f

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/WebResponseImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#undef max
2828
#endif
2929
#include <vector>
30+
#include "default_init_allocator.h"
3031
// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
3132

3233
class AsyncBasicResponse: public AsyncWebServerResponse {
@@ -46,7 +47,7 @@ class AsyncAbstractResponse: public AsyncWebServerResponse {
4647
// This is inefficient with vector, but if we use some other container,
4748
// we won't be able to access it as contiguous array of bytes when reading from it,
4849
// so by gaining performance in one place, we'll lose it in another.
49-
std::vector<uint8_t> _packet, _cache;
50+
std::vector<uint8_t, default_init_allocator<uint8_t>> _packet, _cache;
5051
size_t _readDataFromCacheOrContent(uint8_t* data, const size_t len);
5152
size_t _fillBufferAndProcessTemplates(uint8_t* buf, size_t maxLen);
5253
protected:

src/default_init_allocator.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
// A C++ allocator that default-initializes objects
4+
// This principally useful for vectors of POD types, where default allocation is a no-op; so the vector can be resized "for free".
5+
//
6+
// Code shamelessly stolen from https://stackoverflow.com/a/21028912/8715474
7+
8+
#include <memory>
9+
10+
template <typename T, typename A = std::allocator<T>>
11+
class default_init_allocator : public A {
12+
typedef std::allocator_traits<A> a_t;
13+
public:
14+
// http://en.cppreference.com/w/cpp/language/using_declaration
15+
using A::A; // Inherit constructors from A
16+
17+
template <typename U> struct rebind {
18+
using other =
19+
default_init_allocator
20+
< U, typename a_t::template rebind_alloc<U> >;
21+
};
22+
23+
template <typename U>
24+
void construct(U* ptr)
25+
noexcept(std::is_nothrow_default_constructible<U>::value) {
26+
::new(static_cast<void*>(ptr)) U;
27+
}
28+
29+
template <typename U, typename...Args>
30+
void construct(U* ptr, Args&&... args) {
31+
a_t::construct(static_cast<A&>(*this),
32+
ptr, std::forward<Args>(args)...);
33+
}
34+
};

0 commit comments

Comments
 (0)