benchmarks
benchmarks copied to clipboard
c++ for bench.b could be implemented 20% faster for x64 and twice faster for x86
numbers are with disabled print
namespace modified
{
enum op_type {
INC,
MOVE,
LOOP,
PRINT
};
struct Op;
using Ops = vector<Op>;
using data_t = ptrdiff_t;
struct Op
{
op_type op;
data_t val;
Ops loop;
Op(Ops v) : op(LOOP), loop(v) {}
Op(op_type _op, data_t v = 0) : op(_op), val(v) {}
};
class Tape
{
using vect = vector<data_t>;
vect tape;
vect::iterator pos;
public:
Tape()
{
tape.reserve(8);
tape.push_back(0);
pos = tape.begin();
}
inline data_t get() const
{
return *pos;
}
inline void inc(data_t x)
{
*pos += x;
}
inline void move(data_t x)
{
auto d = std::distance(tape.begin(), pos);
d += x;
if (d >= (data_t)tape.size())
tape.resize(d + 1);
pos = tape.begin();
std::advance(pos, d);
}
};
class Program
{
Ops ops;
public:
Program(const string& code)
{
auto iterator = code.cbegin();
ops = parse(&iterator, code.cend());
}
void run() const
{
Tape tape;
_run(ops, tape);
}
private:
static Ops parse(string::const_iterator *iterator, string::const_iterator end)
{
Ops res;
while (*iterator != end)
{
char c = **iterator;
*iterator += 1;
switch (c) {
case '+':
res.emplace_back(INC, 1);
break;
case '-':
res.emplace_back(INC, -1);
break;
case '>':
res.emplace_back(MOVE, 1);
break;
case '<':
res.emplace_back(MOVE, -1);
break;
case '.':
res.emplace_back(PRINT);
break;
case '[':
res.emplace_back(parse(iterator, end));
break;
case ']':
return res;
}
}
return res;
}
static void _run(const Ops &program, Tape &tape)
{
for (auto &op : program)
{
switch (op.op)
{
case INC:
tape.inc(op.val);
break;
case MOVE:
tape.move(op.val);
break;
case LOOP:
while (tape.get() > 0)
_run(op.loop, tape);
break;
case PRINT:
if (do_print())
{
printf("%c", (int)tape.get());
fflush(stdout);
}
break;
}
}
}
};
}
not really see what changed, seems parse
method, this not in main loop so it unimportant. move
method also called only to size 8
almost all changes was made to make just good modern c++ style. most important from performance point of view for this test is avoid to pointer arithmetic in every get()/inc() (using *pos instead of tape[pos]) also _run method does't need "this" so it could be static member and doesn't require to put hidden "this" argument