views:

123

answers:

5

We have a "print engine" which basically picks pre defined tasks to run against a file and these "tasks" are .NET 2.0 - 3.5 (in C#) command-line applications.

All it does is run one after the other and with the applications that we haven't developed internally, they run quite quickly, typically 10-30 ms.

However, our .NET applications, typically take 1-3 seconds, and when you're dealing with several executables per file and several files, all executed synchronously, we end up with really long wait times.

Typically these applications are doing a little bit of database work and some extremely basic file modification (plain text stuff). We have even stripped down some applications in order to see if it was just the overhead of the .NET Framework that was slowing everything down and everyone that has looked into it has just concluded that

".NET is just slow and it's not made to perform in this manner."

I was wondering if this is true and what techniques I can use to either track the problem down or alleviate the lag. I've tried using profilers but so far I haven't seen one that will repeatedly execute a command-line .NET application, which is what we do. Most just want to run an executable once and attach to it to profile it.

Ideally, we would like to opt out of using the print engine completely and develop our own more efficient engine, but that's just not going to happen.

+7  A: 

Typically these applications are doing a little bit of database work

There you go. The packaged native applications likely aren't talking to a database. That alone could easily take 10-30 ms+ for even a single short query.

Also, .NET does have some additional overhead required to establish an application domain. You might find that things work better if you can group some of your small applications into fewer larger ones, or perhaps use command-line parameters to configure them to run several tasks at once.

Joel Coehoorn
+3  A: 

Most (all?) of .NET slowdowns are related to assembly loading and JIT compilation.

If you can combine multiple tasks into the command-line, that will make it run MUCH faster. Remember when you execute a command line application over and over again for a single task that you are dynamically loading and compiling each assembly and all of its resources every time.

Additionally, if you use NGEN to make a precompiled image of the assembly/assemblies, this will decrease the startup time dramatically.

routeNpingme
jit only happens once per machine. Since these run frequently I doubt ngen would help, and might even slow it down since they no longer get to use machine-specific optimizations.
Joel Coehoorn
Thanks for that info Joel!
Allen
Unless assembly is NGENed, JIT happens every time a method is first called. If you restart the same application, same methods will be JITted again.
Pavel Minaev
+3  A: 

Inherently, it is not slow, but any operation is only as fast as its slowest step. Starting something up has object initialization, etc, but isn't that slow. So, what were the performance numbers like for the empty program? If that were taking several seconds, I would really wonder what is going on.

Steve
I will follow up with some concrete numbers and code snippets, as I'd really like to get to the bottom of this
Allen
+1 for first measuring with an empty app, this will show whether or not the overhead is really in the .Net 'overhead' (which I would doubt)...
jeroenh
+1  A: 

Difficult to make blanket statements like ".net apps are slow". You may have some JIT issues, but precompiling them can get rid of that. Look at what the apps are doing. if they are talking to a database, then expect a second or two to make the connection, execute the query, do somethign with it, quit.

When you get down to really fine tuning an app, outside of database connection and query latency, then a natively compiled application will tend to run faster than a .net app or a java app or a script ... that's assuming that the natively compiled app is coded efficiently & optimized.

James Conigliaro
+1  A: 

I would change the way you call these tasks from the print engine. It sounds like you are running them from the command line/create process? If this is the case you can load them at print engine start into your app domain, then call their Main method with the relevant perameters. This would drastically cut down on JIT and load times.

chris.w.mclean
interesting, so we'd still have our command line apps, but they'd just be calling stuff thats already loaded into the app domain?
Allen
Yes, you can load any .net assembly (exe or dll) into an app domain. You then have access to their methods via reflection, so you can call their Main method with the right string parameters.
chris.w.mclean
You'd want to do the main method on a new thread, probably from the thread pool, as otherwise you'll end up with your engine being single tasked...
chris.w.mclean