View Full Version : Legacy Code Performance Issues with .Net
kturok
08-28-2003, 05:05 PM
I have been able to compile a large portion of legacy Fortran code to the .Net platform into a class library. I have written a new application that utilizes our new Fortran .Net library, but the performance is really bad. To illustrate, when I run my code against the new .Net library, it takes several minutes for the process to run to completion. In contrast, when I run the same legacy code compiled with the Compaq Visual Fortran 6 compiler, the same operation completes in under 30 seconds. I have traced the culprit to one call to the Fortran .Net class library, and that particular sub is identical to that used in Win32 exe created with the Compaq compiler that runs so well. Are there any optimization steps I can take to make my Fortran .Net code run more efficiently?
Thanks,
Kim
tzeis
08-28-2003, 06:53 PM
There are a couple of reasons why the .NET code might not run at the speed of native. The .NET code is "jitted" (just in time compiled) so a part of the time difference that you are seeing is because the IL code is being compiled before it is run. This will cause a slowdown the first time the code is loaded into memory. Another reason is that we haven't implemented any optimizations for the IL in the first release of Fortran for .NET.
That said, not all .NET code will run slower than native code. For example, we have a case where a program does a lot of database access, and have found that for large queries, the .NET code using the ADO.NET interface runs about twice as fast as native code using an ODBC interface.
Most Fortran code is written in two parts - a calculation part (aka the "kernel") and an interface part, which services the kernel by providing it with data I/O and allowing the user to provide information used by the kernel. If you find that the performance of the kernel is too slow with the .NET compiler, the best option might be to retain that part as a native DLL, and encapsulate calls to the DLL in an object oriented wrapper. This technique lets you take advantage of many of the features of .NET like powering Web servers or exposing your application through the COM interface, while retaining the speed of native Fortran.
kturok
08-28-2003, 07:36 PM
Wrapping the Native Fortran Win32 dll was the first thing we tried, but the legacy subroutine signatures are so convoluted that we couldn't get the declarations correct. I got close one time, but curiously, I kept getting a System.ExecutionEngineException even though in my watch window, I could see that the value I expected was being returned from the dll. I downloaded the trial version of Fortran .Net and I had the legacy code compiled into a .Net class library in a matter of hours. I build a proof of concept on top of it that accessed some of the simpler routines, and our organization decided to purchase the full version and drop the Win32 implementation all together because of its problematic nature. After several weeks of development, I have the complex operations working, but they are so slow that using this application isn't an option. The Fortran portions of the app are only complex calculations (business logic). The UI and data operations are done in VB.Net. I suppose I'll have to resurrect the Win32 stuff out of my recycle bin until optimizations are complete. Any idea when that will be?
tzeis
08-28-2003, 09:52 PM
We don't have a schedule yet for the addition of optimizations.
As a suggestion, you might try using a Fortran for .NET class library to interface to your VB.NET code, and go from the Fortran for .NET code to an LF95 generated DLL. rather than going from VB.NET to a CVF DLL. To go from a .NET APP to a native DLL, an interface is required, and trying to translate managed VB.NET variable types to unmanaged CVF types might be difficult, if there are not equivalent types on both sides of the interface. Going from a Fortran for .NET wrapper to a native LF95 DLL, all the variable declarations are the same on both sides of the DLL, as long as you are not sending derived types as arguments.
You would have to evaluate whether CVF or LF95 makes the faster DLL, it depends on what the code looks like. Sometimes LF95 generates the faster code, and sometimes not.
kturok
09-05-2003, 01:36 PM
I have followed your advice and recompiled my project in LF95, so now I have a Win32 dll. Initially, there were no exports, so I added a dll_export statement to one of the smaller, more simple subroutines for testing purposes. The simple addition of that one line causes the build to fail because of an "unresolved external symbol" error in each of the other subroutines that call the subroutine to which the dll_export statement was added. When I take the dll_export statement out, it compiles. Is it illegal to both export a subroutine and access it from other subroutines within the same dll?
tzeis
09-05-2003, 07:10 PM
It is not illegal to call an exported procedure from within the same dll. When you export the procedure, the name of the procedure is changed, because it gets "decorated" to conform to whatever calling convention is specified. A problem occurs because the calling procedure expects to see a non-decorated name.
There are at least two potential solutions to this dilemma:
1) Use wrapper routines to export procedures. The wrapper has a slightly different name, contains the export statement, and calls through to the procedure you want to access.
2) In the calling procedure in the DLL, import the procedure that you want to call. This will allow the calling procedure to recognise the decorated name. Doing this may cause a linker warning, which can be safely ignored.
vBulletin® v3.6.8, Copyright ©2000-2012, Jelsoft Enterprises Ltd.