我有一个处理一组规则的项目。目前,规则由一个或多个子句组成,其语法如下:
A
A & B
A & B & C
etc
这编成如下:
struct Rule {
list<Clause*> Clauses;
};
bool ProcessRule(const Rule* Rule) {
for (const auto& Clause : Rule->Clauses) {
if (!ProcessClause(Clause)) return false;
}
return true;
}
我的任务是实现一个互补的逻辑或构造,其语法如下:
A
A & B
A | B
A & B & C
A & B | C
A | B & C
A | B | C
etc
我选择了最明显的方法,并将Rule
结构的实现从使用列表更改为使用树:
enum NodeType {
LogicalAnd,
LogicalOr,
Leaf,
};
struct Node {
NodeType Type;
};
struct LogicalNode : Node {
list<Node*> Children;
};
struct LeafNode : Node {
Clause* Clause;
};
struct Rule {
Node* Root;
}
bool ProcessRule(const Rule* Rule) {
return ProcessNode(Rule->Root);
}
bool ProcessNode(const Node* Node) {
switch (Node->Type) {
case LogicalAnd:
for (const auto& Child : ((const LogicalNode*)Node)->Children) {
if (!ProcessNode(Child)) return false;
}
return true;
case LogicalOr:
for (const auto& Child : ((const LogicalNode*)Node)->Children) {
if (ProcessNode(Child)) return true;
}
return false;
case Leaf:
return ProcessClause(((const LeafNode*)Node)->Clause);
}
}
这一切似乎都非常简单,但问题是使用完全相同的规则集相对严重的性能下降,大约15%左右。我通过分析器运行了两个版本,并且降级是由于ProcessNode()
函数的开销,我假设由于switch语句和函数调用ProcessRule()
被调用了数百万次。有没有办法减轻这种开销?这似乎有点过分,所以我觉得我可能会遗漏一些明显的东西。
答案 0 :(得分:0)
删除开关并添加AndNode
和OrNode
类,并使用具有适当覆盖的虚函数。