I'm developing a small programming language for use in any project I have where I feel a small scripting language could be used well. I've written two emulators for the language, one in C++ and one in Java. The C++ performs faster except for any recursion in the language, in which it suddenly performs terribly!
Here is the code from my language that I am running which runs in 1.5s on the Java emulator and 4s on the C++ emulator:
dec i = 0;
recurse();
print i;
def recurse:
if i < 10000000:
i++;
recurse();
return;
This compiles down into the following instructions:
% i = 0; #define the alias i as being variable 0;
# i needs to be initialised;
STOREINT i 0;
CALL @recurse; #call the label recurse, push this line onto the stack;
PRINTINTLN $i;
END; #end of program;
@recurse; #define the function recurse;
# if i is < 10000000 then inc i;
GEQ $i 10000000;
JCMP @return; #jump to the return statement
INC i;
CALL @recurse;
@return;
RETURN; #return back to the line on the top of the stack;
The C++ implementation differs slightly from the Java implementation in that it uses an array of unions to store each "typeless" object, whereas Java just uses Object
. Other than that, the code is almost identical (with C++ not needing to do any casting because from the instructions we can be sure which field in the union we are using, and therefore we access the correct field instead of casting the Object
to the correct type in Java. C++ also doesn't need to use & 0xFF
in order to fix sign problems with the java byte type, as we can make unsigned char
s). The main difference between them seems to be the performance of the call stacks, which are implemented in each case as follows:
Java
public class ArrayStack<T> implements Stack<T>
{
private static final long serialVersionUID = 1L;
protected Object[] stack;
protected int capacity;
protected int pointer;
public ArrayStack(int capacity)
{
stack = new Object[capacity];
this.capacity = capacity;
clear();
}
public void push(T value)
{
stack[pointer++] = value;
}
public T pop()
{
return (T) stack[--pointer];
}
public T peek()
{
return (T) stack[pointer-1];
}
public boolean isEmpty()
{
return pointer == 0;
}
public boolean isFull()
{
return pointer == capacity;
}
public void clear()
{
pointer = 0;
}
public int size()
{
return pointer;
}
public int capacity()
{
return capacity;
}
}
C++
template <class T> class ArrayStack
{
private:
T* stack;
int capacity;
int pointer;
public:
ArrayStack(int capacity)
{
this->capacity = capacity;
stack = new T[capacity];
clear();
}
~ArrayStack() { delete stack; }
void push(T value) { stack[pointer++] = value; }
T pop() { return stack[--pointer]; }
T peek() const { return stack[pointer-1]; }
bool isEmpty() const { return pointer == 0; }
void clear() { pointer = 0; }
int size() const { return pointer; }
int getCapacity() { return capacity; }
};
I'll provide the case statements running during this program below if anybody wants to see them, but for now I'll leave them out to keep this post a little shorter!
To my eyes, the C++ looks like it should be either faster than or equal to the Java one, as even if new was the slow part of the C++ code, that isn't taken into account in the timing of the program execution, which starts timing as soon as the first instruction is executed. Could it be that I'm storing the stack as a member variable in the Emulator class, and not as a pointer or something like that, or something the JIT compiler can do that the static C++ compiler (on O3) can't?
delete[] stack
? Java stores just references in the stack and C++ stores objects and copies them if needed. This could get pretty slow ifT
is big. \$\endgroup\$Stack
instances, will you get a stackoverflow? \$\endgroup\$