Private fields are not free
Here the benchmark:
enum OpT {INC, MOVE, PRINT, LOOP}
namespace Test {
struct Op {
public OpT op;
public int v;
public Op[] loop;
public Op(OpT _op, int _v) { op = _op; v = _v; loop = null; }
public Op.vnull(OpT _op, Op[] _l) { op = _op; loop = _l; v = 0; }
}
class Tape {
private int pos = 0;
private int[] tape = new int[1];
public int Get() { return tape[pos]; }
public void Inc(int x) { tape[pos] += x; }
public void Move(int x) { pos += x; while (pos >= tape.length) tape.resize(tape.length*2);}
}
class Program {
public string code;
public int pos = 0;
public Op[] ops;
Program(string text) {
code = text;
ops = parse();
}
private Op[] parse() {
Op[] res = {};
while (pos < code.length) {
char c = code[pos];
pos++;
switch (c) {
case '+': res += (Op(OpT.INC, 1)); break;
case '-': res += (Op(OpT.INC, -1)); break;
case '>': res += (Op(OpT.MOVE, 1)); break;
case '<': res += (Op(OpT.MOVE, -1)); break;
case '.': res += (Op(OpT.PRINT, 0)); break;
case '[': res += (Op.vnull(OpT.LOOP, parse())); break;
case ']': return res;
}
}
return res;
}
public void run() {
_run(ops, new Tape());
}
private void _run(Op[] program, Tape tape) {
for (int i=0;i<program.length;i++) {
switch (program[i].op) {
case OpT.INC: tape.Inc(program[i].v); break;
case OpT.MOVE: tape.Move(program[i].v); break;
case OpT.LOOP: while (tape.Get() > 0) _run(program[i].loop, tape); break;
case OpT.PRINT: stdout.printf("%c", (char)tape.Get()); stdout.flush(); break;
}
}
}
static void main(string[] args) {
string text;
try {
FileUtils.get_contents(args[1], out text);
} catch (FileError e) {
stdout.printf("Error: %s\n", e.message);
}
if (text.length == 0) {
Process.exit(1);
}
var timer = new Timer();
new Program(text).run();
timer.stop();
message("time: " + timer.elapsed().to_string() + " s");
}
}
}
BrainFuck program:
Benchmark brainf*ck program
>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
[>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
++++++++[>++++++++++[>++++++++++[>++++++++++[>+
+++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.
If I change pos and tape fields from public to public I have 25-30% better results(2.2 vs 2.8).
Now private fields is struct ClassNamePrivate in ClassName struct in C
struct _Sas {
GTypeInstance parent_instance;
volatile int ref_count;
SasPrivate * priv;
gint a;
};
struct _SasPrivate {
gint b;
};
I suggest placing all the private fields in the same structure with the public ones, with the Private
prefix, or finding another solution to the problem that doesn't add an overhead. It seems to me that the main thing is that access to private fields is controlled by Vala, and it is not so important to ensure the privacy of fields on the C side.
Edited by gavr