Monday, 19 January 2009

Some are more equal than others!

I've been trying to evaluate some scripting solutions for a Delphi application I'm working on. One of the things we do a lot of is repetitive calculations. So we wrote a small test example to try this out. It's a very contrived example, but it should give us an idea of how fast these solutions are. We basically nested two loops, and did some random mathematical functions inside the inner loop and put the results into an array of doubles. The details are not too important, but the first thing that stood out is how blindingly fast Delphi is. And by contrast how excruciatingly slow these scripting solutions can be. Some were better than others, but all were magnitudes slower than the native code. I kind of expected that, but not by such a margin. The best solution was surprisingly VBA at five times slower than native Delphi. Not sure if Microsoft still licence it though. I guess we may have to rethink how scripting will work in our application.

Now to the title. What's equal to what? Well, I was wondering how fast the same code would be if I wrote it in .NET. I chose C#, and was surprised to find it marginally faster than native Delphi code. Well, not that surprised. I expected it to be fast, maybe as fast as, but not faster than Delphi though. It wasn't by a lot, but it was impressive nonetheless. I guess the optimisation's that are now possible when using a JIT compiler are beginning to outweigh native codes inherent speed. I'm sure there are some things always suited to native code, but for most things, the fear that .NET is going to be slow is unfounded.

Just for the sake of it, I decided to rewrite it in VB.NET, expecting the same result. Wow, almost twice as slow. I wonder why. And the executable is more than twice the size of the C# equivalent. Ok, now I was really interested, so I wrote the whole thing in Delphi Prism. Syntax wise, apart from the usual begins and ends, the Delphi Prism version feels more like the C# version than the .NET version, and the performance is almost exactly the same as the C# version. The executable is 4 times the size of the C# one though. I managed to get it slightly smaller by getting rid of the icon, but it's still larger. Why? I'll investigate later with reflector.

Finally, I wanted to try and use the asynchronous features of Delphi Prism. Nothing too complicated. So I just split up the outer loop into ranges, and used Delphi Prisms async keyword.

var x := async ExecuteIt(0, 2000);
x; //Waits for the async method to execute

Since I was timing how long the whole process took, I used the waitable result of the asynchronous statement to make sure each of my chunks were ready before I stopped the clock (but I made sure they didn't wait on each other). On my dual core CPU, the resultant application ran almost twice as fast as the synchronous version. The extra method call, plus switching overhead making sure it wasn't exactly double. Pretty cool stuff, and I've only just touched the surface.


Anonymous said...

Delphi codes is slower than C# - reason: Delphi does not generate optimized codes for latest CPU

Macedonczyk said...

Do you have tried Lua? I think it is the quickest script. Secend possibility is PaxPascal. It is compiler (jit in form of delphi component) and goes with the same speed as delphi.
Net contra delphi - delphi has slow floating point calculations so this main reason why c# was quicker. But if you have bigger application with forms (very slow in net) and many objects (gc doesn't like many objects to life together especially with many dependecy) then delphi will be run 30-40% quicker.

Anonymous said...

> for latest CPU

If it only was "for latest CPU". Delphi optimizes for CPUs from the last century.

Marshall Fryman said...

For your scripting support, have you tried either RemObjects free PascalScript or DevExpresses InnerFuse Pascal Script? I've been thinking about using one or the other but never quite seem to get the time to test them.

Anonymous said...

I use FastScript, and one thing I really like (maybe has it also) is that you can create your own Delphi routines and call them inside the script so you can have full Delphi power (or inline asm!!) for some tasks

Anonymous said...

Depending on what you're computing, a powerful solution could be to use SQLite (in in-memory mode): interface your data via virtual tables (it's fairly easy to map them to arrays in your language of choice), add custom math functions if required or to provide support for SSE2-enhanced computations.
SQLite can be quite a convenient math cruncher, and the SQL language is a very powerful and convenient language when working with arrays of data, much more so than our OO languages in many cases.
Of course you've got to wrap your mind around SQL, which is more about describing what you want done rather than how you want it done.

Anonymous said...

You should try PaxCompiler. Very very fast.