Reputation: 92795
I'm working on my solution to the Cult of the Bound Variable problem.
Part of the problem has you implement an interpreter for the "ancient" Universal Machine. I've implemented an intepreter for the machine they describe and now I'm running a benchmark program that the university provided to test it.
My C# implementation of this interpreter is slow!
I fired up my program in the ANTS profiler to see where the slowdown is and I can see that over 96% of my time is taken up by the "Load Program" operation.
The specification of this operator is as follows:
#12. Load Program.
The array identified by the B register is duplicated
and the duplicate shall replace the '0' array,
regardless of size. The execution finger is placed
to indicate the platter of this array that is
described by the offset given in C, where the value
0 denotes the first platter, 1 the second, et
cetera.
The '0' array shall be the most sublime choice for
loading, and shall be handled with the utmost
velocity.
Here is my code for this operator:
case 12: // Load Program
_platters[0] = (UInt32[])_platters[(int)_registers[B]].Clone();
_finger = _registers[C];
break;
The source code to my whole "Universal Machine" interpreter is here.
What can I do to make this faster? There are other implementations of this interpreter written in C which complete the entire benchmark significantly faster.
Upvotes: 11
Views: 388
Reputation: 3742
Aside from the question at hand, the real reason your VM benchmarks so poorly is that you should be handling 0 "with the utmost velocity" as the spec says ;)
Essentially, regular jumps are performed by doing a load from 0 to 0. This is extremely common in the codex code. You should avoid cloning completely and only update the "finger" in that particular case.
Upvotes: 0
Reputation: 244757
Depending on how are the two resulting arrays used, you could use a modification of copy-on-write:
You won't use arrays directly, but using a wrapper. To clone an array, just create another wrapper. If you try to write to an array that is shared by more than one wrapper, you do the actual cloning and decouple the wrappers.
Upvotes: 0
Reputation: 269298
You could try using Buffer.BlockCopy
, although I'd be surprised if it makes any massive difference in this case:
case 12: // Load Program
uint[] src = _platters[(int)_registers[B]];
_platters[0] = new uint[src.Length];
Buffer.BlockCopy(src, 0, _platters[0], 0, src.Length * 4);
_finger = _registers[C];
break;
Upvotes: 7
Reputation: 11210
Use the BlockCopy method described here: http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/42189513-2106-4467-af9a-3b1810509cc8/
Upvotes: 4
Reputation: 115691
Buffer.BlockCopy
promises to be much faster, as per this MSDN thread.
Upvotes: 7