Skip to content

Commit b281d3f

Browse files
committed
Add cache member variable to parse_t.
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.
1 parent c3a919f commit b281d3f

File tree

2 files changed

+53
-13
lines changed

2 files changed

+53
-13
lines changed

libchecktestdata.cc

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,24 @@ void unsetvars(const args_t& varlist)
261261
value_t value(const expr& x)
262262
{
263263
debug("value '%s'",x.val.c_str());
264+
if ( x.cache.val.which()!=value_none ) {
265+
debug("eval cached");
266+
return x.cache;
267+
}
264268

265-
if ( x.op=='S' ) return value_t(x.val);
269+
if ( x.op=='S' ) return x.cache = value_t(x.val);
266270
if ( isalpha(x.val[0]) ) return getvar(x);
267271

268272
mpz_class intval;
269273
mpf_class fltval;
270-
if ( intval.set_str(x.val,0)==0 ) return value_t(intval);
274+
if ( intval.set_str(x.val,0)==0 ) return x.cache = value_t(intval);
271275
else if ( fltval.set_str(x.val,0)==0 ) {
272276
// Set sufficient precision:
273277
if ( fltval.get_prec()<4*x.val.length() ) {
274278
fltval.set_prec(4*x.val.length());
275279
fltval.set_str(x.val,0);
276280
}
277-
return value_t(fltval);
281+
return x.cache = value_t(fltval);
278282
}
279283
return value_t();
280284
}
@@ -418,27 +422,60 @@ value_t evalfun(args_t funargs)
418422
exit(exit_failure);
419423
}
420424

425+
bool cachable(const expr& e)
426+
{
427+
switch ( e.op ) {
428+
case 'I':
429+
case 'F':
430+
case 'S':
431+
return true;
432+
433+
case '+':
434+
case '-':
435+
case '*':
436+
case '%':
437+
case '/':
438+
case '^':
439+
case 'n':
440+
case '?':
441+
case '|':
442+
case '&':
443+
case '!':
444+
case 'f':
445+
for(size_t i=0; i<e.nargs(); i++) if ( !cachable(e.args[i]) ) return false;
446+
return true;
447+
}
448+
return false;
449+
}
450+
421451
value_t eval(const expr& e)
422452
{
423453
debug("eval op='%c', val='%s', #args=%d",e.op,e.val.c_str(),(int)e.args.size());
454+
if ( e.cache.val.which()!=value_none ) {
455+
debug("eval cached");
456+
return e.cache;
457+
}
458+
value_t res;
424459
switch ( e.op ) {
425460
case 'I':
426461
case 'F':
427462
case 'S':
428-
case 'v': return value(e);
429-
case 'n': return -eval(e.args[0]);
430-
case '+': return eval(e.args[0]) + eval(e.args[1]);
431-
case '-': return eval(e.args[0]) - eval(e.args[1]);
432-
case '*': return eval(e.args[0]) * eval(e.args[1]);
433-
case '/': return eval(e.args[0]) / eval(e.args[1]);
434-
case '%': return eval(e.args[0]) % eval(e.args[1]);
435-
case '^': return pow(eval(e.args[0]),eval(e.args[1]));
436-
case 'f': return evalfun(e.args);
463+
case 'v': res = value(e); break;
464+
case 'n': res = -eval(e.args[0]); break;
465+
case '+': res = eval(e.args[0]) + eval(e.args[1]); break;
466+
case '-': res = eval(e.args[0]) - eval(e.args[1]); break;
467+
case '*': res = eval(e.args[0]) * eval(e.args[1]); break;
468+
case '/': res = eval(e.args[0]) / eval(e.args[1]); break;
469+
case '%': res = eval(e.args[0]) % eval(e.args[1]); break;
470+
case '^': res = pow(eval(e.args[0]),eval(e.args[1])); break;
471+
case 'f': res = evalfun(e.args); break;
437472
default:
438473
cerr << "unknown arithmetic operator '" << e.op << "' in "
439474
<< program[prognr] << endl;
440475
exit(exit_failure);
441476
}
477+
if ( cachable(e) ) e.cache = res;
478+
return res;
442479
}
443480

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

10921129
while ( true ) {
1093-
command cmd = currcmd = program[prognr];
1130+
const command &cmd = program[prognr];
1131+
currcmd = cmd;
10941132

10951133
if ( cmd.name()=="EOF" ) {
10961134
if ( gendata ) {

parsetype.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct parse_t {
7878
~ uninitialized object, to detect unset default arguments
7979
*/
8080

81+
mutable checktestdata::value_t cache;
82+
8183
parse_t(): val(), args(), op('~') {}
8284
parse_t(args_t _args): val(), args(_args), op(' ') {}
8385
parse_t(val_t _val, args_t _args): val(_val), args(_args), op(' ') {}

0 commit comments

Comments
 (0)