Perf: Use container pointer rather than copy. (#4)
* feat: add benchmark and profiling.
* chore: update readme
* fix: fix compile headers error and fix cmake.
* perf: use container pointer rather than copy.
Signed-off-by: stonex <1479765922@qq.com>
diff --git a/cvaluate/StagePlanner.cpp b/cvaluate/StagePlanner.cpp
index 31e4fe2..baf1a26 100644
--- a/cvaluate/StagePlanner.cpp
+++ b/cvaluate/StagePlanner.cpp
@@ -49,18 +49,25 @@
{OperatorSymbol::SEPARATE, SeparatorStage},
};
+ const static std::vector<TokenKind> kPrefixKind = {TokenKind::PREFIX};
+ const static std::vector<TokenKind> kModifierKind = {TokenKind::MODIFIER};
+ const static std::vector<TokenKind> kComparatorKind = {TokenKind::COMPARATOR};
+ const static std::vector<TokenKind> kLogicalopKind = {TokenKind::LOGICALOP};
+ const static std::vector<TokenKind> kTernaryKind = {TokenKind::TERNARY};
+ const static std::vector<TokenKind> kSeparatorKind = {TokenKind::SEPARATOR};
+
Precedent planFunctions = PlanFunctions;
- PrecedencePlanner planPrefix(kPrefixSymbols, {TokenKind::PREFIX}, nullptr, planFunctions);
- PrecedencePlanner planExponential(kExponentialSymbolsS, {TokenKind::MODIFIER}, planFunctions, nullptr);
- PrecedencePlanner planMultiplicative(kMultiplicativeSymbols, {TokenKind::MODIFIER}, planExponential, nullptr);
- PrecedencePlanner planAdditive(kAdditiveSymbols, {TokenKind::MODIFIER}, planMultiplicative, nullptr);
- PrecedencePlanner planShift(kBitwiseShiftSymbols, {TokenKind::MODIFIER}, planAdditive, nullptr);
- PrecedencePlanner planBitwise(kBitwiseSymbols, {TokenKind::MODIFIER}, planShift, nullptr);
- PrecedencePlanner planComparator(kComparatorSymbols, {TokenKind::COMPARATOR}, planBitwise, nullptr);
- PrecedencePlanner planLogicalAnd({{"&&", OperatorSymbol::AND}}, {TokenKind::LOGICALOP}, planComparator, nullptr);
- PrecedencePlanner planLogicalOr({{"||", OperatorSymbol::OR}}, {TokenKind::LOGICALOP}, planLogicalAnd, nullptr);
- PrecedencePlanner planTernary(kTernarySymbols, {TokenKind::TERNARY}, planLogicalOr, nullptr);
- PrecedencePlanner planSeparator(kSeparatorSymbols, {TokenKind::SEPARATOR}, planTernary, nullptr);
+ PrecedencePlanner planPrefix(&kPrefixSymbols, &kPrefixKind, nullptr, planFunctions);
+ PrecedencePlanner planExponential(&kExponentialSymbolsS, &kModifierKind, planFunctions, nullptr);
+ PrecedencePlanner planMultiplicative(&kMultiplicativeSymbols, &kModifierKind, planExponential, nullptr);
+ PrecedencePlanner planAdditive(&kAdditiveSymbols, &kModifierKind, planMultiplicative, nullptr);
+ PrecedencePlanner planShift(&kBitwiseShiftSymbols, &kModifierKind, planAdditive, nullptr);
+ PrecedencePlanner planBitwise(&kBitwiseSymbols, &kModifierKind, planShift, nullptr);
+ PrecedencePlanner planComparator(&kComparatorSymbols, &kComparatorKind, planBitwise, nullptr);
+ PrecedencePlanner planLogicalAnd(&kLogicalAndSymbols, &kLogicalopKind, planComparator, nullptr);
+ PrecedencePlanner planLogicalOr(&kLogicalOrSymbols, &kLogicalopKind, planLogicalAnd, nullptr);
+ PrecedencePlanner planTernary(&kTernarySymbols, &kTernaryKind, planLogicalOr, nullptr);
+ PrecedencePlanner planSeparator(&kSeparatorSymbols, &kSeparatorKind, planTernary, nullptr);
/*
Creates a `evaluationStageList` object which represents an execution plan (or tree)
@@ -68,7 +75,7 @@
The three stages of evaluation can be thought of as parsing strings to tokens, then tokens to a stage list, then evaluation with parameters.
*/
std::shared_ptr<EvaluationStage> PlanStages(std::vector<ExpressionToken>& tokens) {
- auto stream = TokenStream(tokens);
+ TokenStream stream(tokens);
auto stage = PlanTokens(stream);
@@ -133,8 +140,8 @@
Most stages use the same logic
*/
std::shared_ptr<EvaluationStage> PrecedencePlanner::PlanPrecedenceLevel(TokenStream& stream,
- StringOperatorSymbolMap valid_symbols, std::vector<TokenKind> valid_kinds,
- Precedent right_precedent, Precedent left_precedent) {
+ const StringOperatorSymbolMap* valid_symbols, const std::vector<TokenKind>* valid_kinds,
+ Precedent& right_precedent, Precedent& left_precedent) {
ExpressionToken token;
OperatorSymbol symbol = OperatorSymbol::VALUE;
std::shared_ptr<EvaluationStage> right_stage = nullptr;
@@ -149,18 +156,18 @@
while (stream.HasNext()) {
token = *stream.Next();
- if (valid_kinds.size() > 0) {
+ if (valid_kinds->size() > 0) {
key_found = false;
- auto find_key = std::find(valid_kinds.begin(), valid_kinds.end(), token.Kind);
- key_found = (find_key != valid_kinds.end());
+ auto find_key = std::find(valid_kinds->begin(), valid_kinds->end(), token.Kind);
+ key_found = (find_key != valid_kinds->end());
if (!key_found) {
break;
}
}
- if (!valid_symbols.empty()) {
+ if (!valid_symbols->empty()) {
auto data = GetTokenValueData(token.Value);
if (!IsString(data)) {
break;
@@ -168,10 +175,10 @@
auto token_string = data.get<std::string>();
- if (valid_symbols.find(token_string) == valid_symbols.end()) {
+ if (valid_symbols->find(token_string) == valid_symbols->end()) {
break;
} else {
- symbol = valid_symbols[token_string];
+ symbol = valid_symbols->at(token_string);
}
}
diff --git a/include/cvaluate/OperatorSymbol.h b/include/cvaluate/OperatorSymbol.h
index 8597e21..114b14f 100644
--- a/include/cvaluate/OperatorSymbol.h
+++ b/include/cvaluate/OperatorSymbol.h
@@ -156,5 +156,13 @@
{",", OperatorSymbol::SEPARATE}
};
+ const StringOperatorSymbolMap kLogicalAndSymbols = {
+ {"&&", OperatorSymbol::AND}
+ };
+
+ const StringOperatorSymbolMap kLogicalOrSymbols = {
+ {"||", OperatorSymbol::OR}
+ };
+
} // Cvaluate
#endif
\ No newline at end of file
diff --git a/include/cvaluate/StagePlanner.h b/include/cvaluate/StagePlanner.h
index a79a82f..c53fae5 100644
--- a/include/cvaluate/StagePlanner.h
+++ b/include/cvaluate/StagePlanner.h
@@ -30,12 +30,12 @@
class PrecedencePlanner {
public:
- StringOperatorSymbolMap valid_symbols;
- std::vector<TokenKind> valid_kinds;
+ const StringOperatorSymbolMap* valid_symbols = nullptr;
+ const std::vector<TokenKind>* valid_kinds = nullptr;
Precedent next;
Precedent next_right;
- PrecedencePlanner(StringOperatorSymbolMap valid_symbols, std::vector<TokenKind> valid_kinds,
+ PrecedencePlanner(const StringOperatorSymbolMap* valid_symbols, const std::vector<TokenKind>* valid_kinds,
Precedent next, Precedent next_right) {
this->valid_symbols = valid_symbols;
this->valid_kinds = valid_kinds;
@@ -43,31 +43,36 @@
this->next_right = next_right;
};
+ PrecedencePlanner(PrecedencePlanner const& other) {
+ this->valid_symbols = other.valid_symbols;
+ this->valid_kinds = other.valid_kinds;
+ this->next = other.next;
+ this->next_right = other.next_right;
+ };
+
std::shared_ptr<EvaluationStage> PlanPrecedenceLevel(TokenStream& stream,
- StringOperatorSymbolMap vlaid_symbols, std::vector<TokenKind> valid_kinds,
- Precedent right_precedent, Precedent left_precedent);
+ const StringOperatorSymbolMap* vlaid_symbols, const std::vector<TokenKind>* valid_kinds,
+ Precedent& right_precedent, Precedent& left_precedent);
std::shared_ptr<EvaluationStage> operator()(TokenStream& stream) {
Precedent generated = nullptr;
- Precedent nextRight = nullptr;
+ Precedent* nextRight = &this->next_right;
generated = [&] (TokenStream& stream) -> std::shared_ptr<EvaluationStage> {
return PlanPrecedenceLevel(
stream,
this->valid_symbols,
this->valid_kinds,
- nextRight,
+ *nextRight,
this->next
);
};
// left precence > current, right precence >= current
- if (this->next_right != nullptr) {
- nextRight = this->next_right;
- } else {
- nextRight = generated;
- }
-
+ if (this->next_right == nullptr) {
+ nextRight = &generated;
+ }
+
return generated(stream);
}
};
diff --git a/include/cvaluate/TokenStream.h b/include/cvaluate/TokenStream.h
index 5f88228..e1e4b1e 100644
--- a/include/cvaluate/TokenStream.h
+++ b/include/cvaluate/TokenStream.h
@@ -22,10 +22,10 @@
namespace Cvaluate {
class TokenStream {
private:
- std::vector<ExpressionToken> tokens;
+ std::vector<ExpressionToken>& tokens;
std::vector<ExpressionToken>::iterator index;
public:
- TokenStream(std::vector<ExpressionToken> _tokens) : tokens(_tokens) {
+ TokenStream(std::vector<ExpressionToken>& _tokens) : tokens(_tokens) {
this->index = tokens.begin();
};