Skip to content

Commit dc0a06f

Browse files
committed
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.
1 parent 7c174e9 commit dc0a06f

9 files changed

+71
-108
lines changed

headers/modsecurity/anchored_set_variable_translation_proxy.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ class AnchoredSetVariableTranslationProxy {
4747
VariableValue *newVariableValue = new VariableValue(name, &l->at(i)->getKey(), &l->at(i)->getKey());
4848
const VariableValue *oldVariableValue = l->at(i);
4949
l->at(i) = newVariableValue;
50+
newVariableValue->reserveOrigin(oldVariableValue->getOrigin().size());
5051
for (const auto &oldOrigin : oldVariableValue->getOrigin()) {
51-
std::unique_ptr<VariableOrigin> newOrigin(new VariableOrigin);
52-
newOrigin->m_length = oldVariableValue->getKey().size();
53-
newOrigin->m_offset = oldOrigin->m_offset - oldVariableValue->getKey().size() - 1;
54-
newVariableValue->addOrigin(std::move(newOrigin));
52+
newVariableValue->addOrigin(
53+
oldVariableValue->getKey().size(),
54+
oldOrigin.m_offset - oldVariableValue->getKey().size() - 1
55+
);
5556
}
5657
delete oldVariableValue;
5758
}

headers/modsecurity/anchored_variable.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class AnchoredVariable {
6363
void append(const std::string &a, size_t offset,
6464
bool spaceSeparator = false);
6565
void append(const std::string &a, size_t offset,
66-
bool spaceSeparator, int size);
66+
bool spaceSeparator, size_t size);
6767

6868
void evaluate(std::vector<const VariableValue *> *l);
6969
std::string * evaluate();

headers/modsecurity/variable_origin.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#ifdef __cplusplus
1717
#include <string>
18+
#include <memory>
1819
#endif
1920

2021
#ifndef HEADERS_MODSECURITY_VARIABLE_ORIGIN_H_
@@ -36,14 +37,17 @@ class VariableOrigin {
3637
VariableOrigin()
3738
: m_length(0),
3839
m_offset(0) { }
40+
VariableOrigin(size_t length, size_t offset)
41+
: m_length(length),
42+
m_offset(offset) { }
3943

40-
std::string toText() {
41-
std::string offset = std::to_string(m_offset);
42-
std::string len = std::to_string(m_length);
44+
std::string toText() const {
45+
const auto offset = std::to_string(m_offset);
46+
const auto len = std::to_string(m_length);
4347
return "v" + offset + "," + len;
4448
}
4549

46-
int m_length;
50+
size_t m_length;
4751
size_t m_offset;
4852
};
4953

headers/modsecurity/variable_value.h

+18-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <string>
1919
#include <iostream>
2020
#include <memory>
21-
#include <list>
21+
#include <vector>
2222
#include <utility>
2323
#endif
2424

@@ -37,7 +37,7 @@ namespace modsecurity {
3737
class Collection;
3838
class VariableValue {
3939
public:
40-
using Origins = std::list<std::unique_ptr<VariableOrigin>>;
40+
using Origins = std::vector<VariableOrigin>;
4141

4242
explicit VariableValue(const std::string *key,
4343
const std::string *value = nullptr)
@@ -62,11 +62,9 @@ class VariableValue {
6262
m_keyWithCollection(o->m_keyWithCollection),
6363
m_value(o->m_value)
6464
{
65+
reserveOrigin(o->m_orign.size());
6566
for (const auto &i : o->m_orign) {
66-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
67-
origin->m_offset = i->m_offset;
68-
origin->m_length = i->m_length;
69-
m_orign.push_back(std::move(origin));
67+
addOrigin(i);
7068
}
7169
}
7270

@@ -98,15 +96,27 @@ class VariableValue {
9896
}
9997

10098

101-
void addOrigin(std::unique_ptr<VariableOrigin> origin) {
102-
m_orign.push_back(std::move(origin));
99+
void addOrigin(const VariableOrigin &origin) {
100+
m_orign.emplace_back(origin);
101+
}
102+
103+
104+
template<typename... Args>
105+
void addOrigin(Args&&... args) {
106+
m_orign.emplace_back(args...);
103107
}
104108

105109

106110
const Origins& getOrigin() const {
107111
return m_orign;
108112
}
109113

114+
115+
void reserveOrigin(Origins::size_type additionalSize) {
116+
m_orign.reserve(m_orign.size() + additionalSize);
117+
}
118+
119+
110120
private:
111121
Origins m_orign;
112122
std::string m_collection;

src/anchored_set_variable.cc

+2-12
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,16 @@ void AnchoredSetVariable::unset() {
5252

5353
void AnchoredSetVariable::set(const std::string &key,
5454
const std::string &value, size_t offset, size_t len) {
55-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
5655
VariableValue *var = new VariableValue(&m_name, &key, &value);
57-
58-
origin->m_offset = offset;
59-
origin->m_length = len;
60-
61-
var->addOrigin(std::move(origin));
56+
var->addOrigin(len, offset);
6257
emplace(key, var);
6358
}
6459

6560

6661
void AnchoredSetVariable::set(const std::string &key,
6762
const std::string &value, size_t offset) {
68-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
6963
VariableValue *var = new VariableValue(&m_name, &key, &value);
70-
71-
origin->m_offset = offset;
72-
origin->m_length = value.size();
73-
74-
var->addOrigin(std::move(origin));
64+
var->addOrigin(value.size(), offset);
7565
emplace(key, var);
7666
}
7767

src/anchored_variable.cc

+5-23
Original file line numberDiff line numberDiff line change
@@ -54,58 +54,40 @@ void AnchoredVariable::unset() {
5454

5555
void AnchoredVariable::set(const std::string &a, size_t offset,
5656
size_t offsetLen) {
57-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
58-
5957
m_offset = offset;
6058
m_value.assign(a.c_str(), a.size());
61-
origin->m_offset = offset;
62-
origin->m_length = offsetLen;
63-
m_var->addOrigin(std::move(origin));
59+
m_var->addOrigin(offsetLen, offset);
6460
}
6561

6662

6763
void AnchoredVariable::set(const std::string &a, size_t offset) {
68-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
69-
7064
m_offset = offset;
7165
m_value.assign(a.c_str(), a.size());
72-
origin->m_offset = offset;
73-
origin->m_length = m_value.size();
74-
m_var->addOrigin(std::move(origin));
66+
m_var->addOrigin(m_value.size(), offset);
7567
}
7668

7769

7870
void AnchoredVariable::append(const std::string &a, size_t offset,
7971
bool spaceSeparator) {
80-
std::unique_ptr<VariableOrigin> origin(
81-
new VariableOrigin());
82-
8372
if (spaceSeparator && !m_value.empty()) {
8473
m_value.append(" " + a);
8574
} else {
8675
m_value.append(a);
8776
}
8877
m_offset = offset;
89-
origin->m_offset = offset;
90-
origin->m_length = a.size();
91-
m_var->addOrigin(std::move(origin));
78+
m_var->addOrigin(a.size(), offset);
9279
}
9380

9481

9582
void AnchoredVariable::append(const std::string &a, size_t offset,
96-
bool spaceSeparator, int size) {
97-
std::unique_ptr<VariableOrigin> origin(
98-
new VariableOrigin());
99-
83+
bool spaceSeparator, size_t size) {
10084
if (spaceSeparator && !m_value.empty()) {
10185
m_value.append(" " + a);
10286
} else {
10387
m_value.append(a);
10488
}
10589
m_offset = offset;
106-
origin->m_offset = offset;
107-
origin->m_length = size;
108-
m_var->addOrigin(std::move(origin));
90+
m_var->addOrigin({size, offset});
10991
}
11092

11193

src/rule_with_operator.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ bool RuleWithOperator::evaluate(Transaction *trans,
317317
if (ret == true) {
318318
ruleMessage->m_match = m_operator->resolveMatchMessage(trans,
319319
key, value);
320-
for (auto &i : v->getOrigin()) {
321-
ruleMessage->m_reference.append(i->toText());
320+
for (const auto &i : v->getOrigin()) {
321+
ruleMessage->m_reference.append(i.toText());
322322
}
323323

324324
ruleMessage->m_reference.append(*valueTemp.second);

src/variables/remote_user.cc

+25-34
Original file line numberDiff line numberDiff line change
@@ -39,50 +39,41 @@ namespace variables {
3939
void RemoteUser::evaluate(Transaction *transaction,
4040
RuleWithActions *rule,
4141
std::vector<const VariableValue *> *l) {
42-
size_t pos;
43-
std::string base64;
44-
VariableValue *var;
45-
std::string header;
42+
std::vector<const VariableValue *> l2;
4643

47-
std::vector<const VariableValue *> *l2 = \
48-
new std::vector<const VariableValue *>();
49-
transaction->m_variableRequestHeaders.resolve("authorization", l2);
44+
transaction->m_variableRequestHeaders.resolve("authorization", &l2);
5045

51-
if (l2->size() < 1) {
52-
goto clear;
53-
}
46+
if (!l2.empty()) {
47+
const auto *v = l2[0];
5448

55-
header = std::string(l2->at(0)->getValue());
49+
const auto &header = v->getValue();
5650

57-
if (header.compare(0, 6, "Basic ") == 0) {
58-
base64 = std::string(header, 6, header.length());
59-
}
51+
std::string base64;
6052

61-
base64 = Utils::Base64::decode(base64);
53+
if (header.compare(0, 6, "Basic ") == 0) {
54+
base64 = std::string(header, 6, header.length());
55+
}
6256

63-
pos = base64.find(":");
64-
if (pos == std::string::npos) {
65-
goto clear;
66-
}
67-
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
57+
base64 = Utils::Base64::decode(base64);
6858

69-
var = new VariableValue(&l2->at(0)->getKeyWithCollection(),
70-
&transaction->m_variableRemoteUser);
59+
const auto pos = base64.find(":");
60+
if (pos != std::string::npos) {
61+
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
7162

72-
for (const auto &i : l2->at(0)->getOrigin()) {
73-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
74-
origin->m_offset = i->m_offset;
75-
origin->m_length = i->m_length;
76-
var->addOrigin(std::move(origin));
77-
}
78-
l->push_back(var);
63+
auto var = std::make_unique<VariableValue>(&v->getKeyWithCollection(),
64+
&transaction->m_variableRemoteUser);
65+
66+
var->reserveOrigin(v->getOrigin().size());
67+
for (const auto &i : v->getOrigin()) {
68+
var->addOrigin(i);
69+
}
70+
l->push_back(var.release());
71+
}
7972

80-
clear:
81-
for (auto &a : *l2) {
82-
delete a;
73+
for (auto &a : l2) {
74+
delete a;
75+
}
8376
}
84-
l2->clear();
85-
delete l2;
8677
}
8778

8879

src/variables/rule.h

+5-20
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,12 @@ class Rule_DictElement : public VariableDictElement { \
4949
if (!r || r->m_ruleId == 0) {
5050
return;
5151
}
52-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
5352
std::string *a = new std::string(std::to_string(r->m_ruleId));
5453
VariableValue *var = new VariableValue(&m_rule, &m_rule_id,
5554
a
5655
);
5756
delete a;
58-
origin->m_offset = 0;
59-
origin->m_length = 0;
60-
var->addOrigin(std::move(origin));
57+
var->addOrigin();
6158
l->push_back(var);
6259
}
6360

@@ -75,15 +72,12 @@ class Rule_DictElement : public VariableDictElement { \
7572
return;
7673
}
7774

78-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
7975
std::string *a = new std::string(r->m_rev);
8076
VariableValue *var = new VariableValue(&m_rule, &m_rule_rev,
8177
a
8278
);
8379
delete a;
84-
origin->m_offset = 0;
85-
origin->m_length = 0;
86-
var->addOrigin(std::move(origin));
80+
var->addOrigin();
8781
l->push_back(var);
8882
}
8983

@@ -98,15 +92,12 @@ class Rule_DictElement : public VariableDictElement { \
9892
}
9993

10094
if (r && r->hasSeverity()) {
101-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
10295
std::string *a = new std::string(std::to_string(r->severity()));
10396
VariableValue *var = new VariableValue(&m_rule, &m_rule_severity,
10497
a
10598
);
10699
delete a;
107-
origin->m_offset = 0;
108-
origin->m_length = 0;
109-
var->addOrigin(std::move(origin));
100+
var->addOrigin();
110101
l->push_back(var);
111102
}
112103
}
@@ -122,15 +113,12 @@ class Rule_DictElement : public VariableDictElement { \
122113
}
123114

124115
if (r && r->hasLogData()) {
125-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
126116
std::string *a = new std::string(r->logData(t));
127117
VariableValue *var = new VariableValue(&m_rule, &m_rule_logdata,
128118
a
129119
);
130120
delete a;
131-
origin->m_offset = 0;
132-
origin->m_length = 0;
133-
var->addOrigin(std::move(origin));
121+
var->addOrigin();
134122
l->push_back(var);
135123
}
136124
}
@@ -145,15 +133,12 @@ class Rule_DictElement : public VariableDictElement { \
145133
}
146134

147135
if (r && r->hasMsg()) {
148-
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
149136
std::string *a = new std::string(r->msg(t));
150137
VariableValue *var = new VariableValue(&m_rule, &m_rule_msg,
151138
a
152139
);
153140
delete a;
154-
origin->m_offset = 0;
155-
origin->m_length = 0;
156-
var->addOrigin(std::move(origin));
141+
var->addOrigin();
157142
l->push_back(var);
158143
}
159144
}

0 commit comments

Comments
 (0)