Skip to content

Commit

Permalink
Add cache member variable to parse_t.
Browse files Browse the repository at this point in the history
Improves performance #3.

On the problems ascendingphoto and factorfree from NWERC 2017
this speeds things up about 10% and 40% respectively. This cache
may especially help if the checktestdata script contains constant
expressions like "INT(1,5*10^6)" where the 5*10^6 would previously
incur performing exponentiation and multiplication every time the
command was executed.
  • Loading branch information
eldering committed Apr 27, 2018
1 parent c3a919f commit b281d3f
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 13 deletions.
64 changes: 51 additions & 13 deletions libchecktestdata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -261,20 +261,24 @@ void unsetvars(const args_t& varlist)
value_t value(const expr& x)
{
debug("value '%s'",x.val.c_str());
if ( x.cache.val.which()!=value_none ) {
debug("eval cached");
return x.cache;
}

if ( x.op=='S' ) return value_t(x.val);
if ( x.op=='S' ) return x.cache = value_t(x.val);
if ( isalpha(x.val[0]) ) return getvar(x);

mpz_class intval;
mpf_class fltval;
if ( intval.set_str(x.val,0)==0 ) return value_t(intval);
if ( intval.set_str(x.val,0)==0 ) return x.cache = value_t(intval);
else if ( fltval.set_str(x.val,0)==0 ) {
// Set sufficient precision:
if ( fltval.get_prec()<4*x.val.length() ) {
fltval.set_prec(4*x.val.length());
fltval.set_str(x.val,0);
}
return value_t(fltval);
return x.cache = value_t(fltval);
}
return value_t();
}
Expand Down Expand Up @@ -418,27 +422,60 @@ value_t evalfun(args_t funargs)
exit(exit_failure);
}

bool cachable(const expr& e)
{
switch ( e.op ) {
case 'I':
case 'F':
case 'S':
return true;

case '+':
case '-':
case '*':
case '%':
case '/':
case '^':
case 'n':
case '?':
case '|':
case '&':
case '!':
case 'f':
for(size_t i=0; i<e.nargs(); i++) if ( !cachable(e.args[i]) ) return false;
return true;
}
return false;
}

value_t eval(const expr& e)
{
debug("eval op='%c', val='%s', #args=%d",e.op,e.val.c_str(),(int)e.args.size());
if ( e.cache.val.which()!=value_none ) {
debug("eval cached");
return e.cache;
}
value_t res;
switch ( e.op ) {
case 'I':
case 'F':
case 'S':
case 'v': return value(e);
case 'n': return -eval(e.args[0]);
case '+': return eval(e.args[0]) + eval(e.args[1]);
case '-': return eval(e.args[0]) - eval(e.args[1]);
case '*': return eval(e.args[0]) * eval(e.args[1]);
case '/': return eval(e.args[0]) / eval(e.args[1]);
case '%': return eval(e.args[0]) % eval(e.args[1]);
case '^': return pow(eval(e.args[0]),eval(e.args[1]));
case 'f': return evalfun(e.args);
case 'v': res = value(e); break;
case 'n': res = -eval(e.args[0]); break;
case '+': res = eval(e.args[0]) + eval(e.args[1]); break;
case '-': res = eval(e.args[0]) - eval(e.args[1]); break;
case '*': res = eval(e.args[0]) * eval(e.args[1]); break;
case '/': res = eval(e.args[0]) / eval(e.args[1]); break;
case '%': res = eval(e.args[0]) % eval(e.args[1]); break;
case '^': res = pow(eval(e.args[0]),eval(e.args[1])); break;
case 'f': res = evalfun(e.args); break;
default:
cerr << "unknown arithmetic operator '" << e.op << "' in "
<< program[prognr] << endl;
exit(exit_failure);
}
if ( cachable(e) ) e.cache = res;
return res;
}

bool compare(const expr& cmp)
Expand Down Expand Up @@ -1090,7 +1127,8 @@ void checktestdata(ostream &datastream)
datastream << setprecision(float_precision);

while ( true ) {
command cmd = currcmd = program[prognr];
const command &cmd = program[prognr];
currcmd = cmd;

if ( cmd.name()=="EOF" ) {
if ( gendata ) {
Expand Down
2 changes: 2 additions & 0 deletions parsetype.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ struct parse_t {
~ uninitialized object, to detect unset default arguments
*/

mutable checktestdata::value_t cache;

parse_t(): val(), args(), op('~') {}
parse_t(args_t _args): val(), args(_args), op(' ') {}
parse_t(val_t _val, args_t _args): val(_val), args(_args), op(' ') {}
Expand Down

0 comments on commit b281d3f

Please sign in to comment.