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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
foreach (post_t * initial_post, initial_posts) {
|
||||
if (! initial_post->has_flags(ITEM_GENERATED) &&
|
||||
predicate(*initial_post)) {
|
||||
if (initial_post->has_flags(ITEM_GENERATED))
|
||||
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) {
|
||||
amount_t post_amount;
|
||||
if (post->amount.is_null()) {
|
||||
|
|
|
|||
|
|
@ -146,16 +146,18 @@ class auto_xact_t : public xact_base_t
|
|||
{
|
||||
public:
|
||||
predicate_t predicate;
|
||||
bool try_quick_match;
|
||||
|
||||
auto_xact_t() {
|
||||
auto_xact_t() : try_quick_match(true) {
|
||||
TRACE_CTOR(auto_xact_t, "");
|
||||
}
|
||||
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");
|
||||
}
|
||||
auto_xact_t(const predicate_t& _predicate)
|
||||
: predicate(_predicate)
|
||||
: predicate(_predicate), try_quick_match(true)
|
||||
{
|
||||
TRACE_CTOR(auto_xact_t, "const predicate_t&");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue