Improve performance of VariableOrigin instances

- The previous approach would create a std::unique_ptr and store it in
  a std::list in VariableValue (Origins)
- The new approach now stores Origins in a std::vector and constructs
  VariableOrigin elements in-place on insertion.
- Instead of having two heap-allocations for every added VariableOrigin
  instance, this performs only one.
- If multiple origins are added, std::vector's growth strategy may even
  prevent a heap-allocation. There's a cost on growing the size of the
  vector, because a copy of current elements will be necessary.
  - Introduced reserveOrigin method to notify that multiple insertions
    will be made, so that we can use std::vector's reserve and do a
    single allocation (and copy of previous elements), and then just
    initialize the new elements in-place.
This commit is contained in:
Eduardo Arias
2024-06-01 14:54:49 +00:00
parent 7c174e95fa
commit dc0a06fc70
9 changed files with 78 additions and 115 deletions

View File

@@ -18,7 +18,7 @@
#include <string>
#include <iostream>
#include <memory>
#include <list>
#include <vector>
#include <utility>
#endif
@@ -37,7 +37,7 @@ namespace modsecurity {
class Collection;
class VariableValue {
public:
using Origins = std::list<std::unique_ptr<VariableOrigin>>;
using Origins = std::vector<VariableOrigin>;
explicit VariableValue(const std::string *key,
const std::string *value = nullptr)
@@ -62,11 +62,9 @@ class VariableValue {
m_keyWithCollection(o->m_keyWithCollection),
m_value(o->m_value)
{
reserveOrigin(o->m_orign.size());
for (const auto &i : o->m_orign) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
origin->m_offset = i->m_offset;
origin->m_length = i->m_length;
m_orign.push_back(std::move(origin));
addOrigin(i);
}
}
@@ -98,8 +96,14 @@ class VariableValue {
}
void addOrigin(std::unique_ptr<VariableOrigin> origin) {
m_orign.push_back(std::move(origin));
void addOrigin(const VariableOrigin &origin) {
m_orign.emplace_back(origin);
}
template<typename... Args>
void addOrigin(Args&&... args) {
m_orign.emplace_back(args...);
}
@@ -107,6 +111,12 @@ class VariableValue {
return m_orign;
}
void reserveOrigin(Origins::size_type additionalSize) {
m_orign.reserve(m_orign.size() + additionalSize);
}
private:
Origins m_orign;
std::string m_collection;