Spot optimization for simple automated xact exprs
This reduces parsing time in the optimized build by 25%, and was a safe, easy patch. If the "quick predicate evaluator" fails, we disable it from that point on go back to what the standard code does.
This commit is contained in:
parent
d71f0867f9
commit
e3064b9520
2 changed files with 70 additions and 5 deletions
67
src/xact.cc
67
src/xact.cc
|
|
@ -538,6 +538,50 @@ bool xact_t::valid() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool post_pred(expr_t::ptr_op_t op, post_t& post)
|
||||||
|
{
|
||||||
|
switch (op->kind) {
|
||||||
|
case expr_t::op_t::VALUE:
|
||||||
|
return op->as_value().to_boolean();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case expr_t::op_t::O_MATCH:
|
||||||
|
if (op->left()->kind == expr_t::op_t::IDENT &&
|
||||||
|
op->left()->as_ident() == "account" &&
|
||||||
|
op->right()->kind == expr_t::op_t::VALUE &&
|
||||||
|
op->right()->as_value().is_mask())
|
||||||
|
return op->right()->as_value().as_mask()
|
||||||
|
.match(post.reported_account()->fullname());
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
case expr_t::op_t::O_NOT:
|
||||||
|
return ! post_pred(op->left(), post);
|
||||||
|
|
||||||
|
case expr_t::op_t::O_AND:
|
||||||
|
return post_pred(op->left(), post) && post_pred(op->right(), post);
|
||||||
|
|
||||||
|
case expr_t::op_t::O_OR:
|
||||||
|
return post_pred(op->left(), post) || post_pred(op->right(), post);
|
||||||
|
|
||||||
|
case expr_t::op_t::O_QUERY:
|
||||||
|
if (post_pred(op->left(), post))
|
||||||
|
return post_pred(op->right()->left(), post);
|
||||||
|
else
|
||||||
|
return post_pred(op->right()->right(), post);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw_(calc_error, _("Unhandled operator"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
void auto_xact_t::extend_xact(xact_base_t& xact)
|
void auto_xact_t::extend_xact(xact_base_t& xact)
|
||||||
{
|
{
|
||||||
posts_list initial_posts(xact.posts.begin(), xact.posts.end());
|
posts_list initial_posts(xact.posts.begin(), xact.posts.end());
|
||||||
|
|
@ -547,8 +591,27 @@ void auto_xact_t::extend_xact(xact_base_t& xact)
|
||||||
bool needs_further_verification = false;
|
bool needs_further_verification = false;
|
||||||
|
|
||||||
foreach (post_t * initial_post, initial_posts) {
|
foreach (post_t * initial_post, initial_posts) {
|
||||||
if (! initial_post->has_flags(ITEM_GENERATED) &&
|
if (initial_post->has_flags(ITEM_GENERATED))
|
||||||
predicate(*initial_post)) {
|
continue;
|
||||||
|
|
||||||
|
bool matches_predicate = false;
|
||||||
|
if (try_quick_match) {
|
||||||
|
try {
|
||||||
|
// Since the majority of people who use automated transactions simply
|
||||||
|
// match against account names, try using a *much* faster version of
|
||||||
|
// the predicate evaluator.
|
||||||
|
matches_predicate = post_pred(predicate.get_op(), *initial_post);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
DEBUG("xact.extend.fail",
|
||||||
|
"The quick matcher failed, going back to regular eval");
|
||||||
|
try_quick_match = false;
|
||||||
|
matches_predicate = predicate(*initial_post);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
matches_predicate = predicate(*initial_post);
|
||||||
|
}
|
||||||
|
if (matches_predicate) {
|
||||||
foreach (post_t * post, posts) {
|
foreach (post_t * post, posts) {
|
||||||
amount_t post_amount;
|
amount_t post_amount;
|
||||||
if (post->amount.is_null()) {
|
if (post->amount.is_null()) {
|
||||||
|
|
|
||||||
|
|
@ -146,16 +146,18 @@ class auto_xact_t : public xact_base_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
predicate_t predicate;
|
predicate_t predicate;
|
||||||
|
bool try_quick_match;
|
||||||
|
|
||||||
auto_xact_t() {
|
auto_xact_t() : try_quick_match(true) {
|
||||||
TRACE_CTOR(auto_xact_t, "");
|
TRACE_CTOR(auto_xact_t, "");
|
||||||
}
|
}
|
||||||
auto_xact_t(const auto_xact_t& other)
|
auto_xact_t(const auto_xact_t& other)
|
||||||
: xact_base_t(), predicate(other.predicate) {
|
: xact_base_t(), predicate(other.predicate),
|
||||||
|
try_quick_match(other.try_quick_match) {
|
||||||
TRACE_CTOR(auto_xact_t, "copy");
|
TRACE_CTOR(auto_xact_t, "copy");
|
||||||
}
|
}
|
||||||
auto_xact_t(const predicate_t& _predicate)
|
auto_xact_t(const predicate_t& _predicate)
|
||||||
: predicate(_predicate)
|
: predicate(_predicate), try_quick_match(true)
|
||||||
{
|
{
|
||||||
TRACE_CTOR(auto_xact_t, "const predicate_t&");
|
TRACE_CTOR(auto_xact_t, "const predicate_t&");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue