*
Quick Links|Home|Worldwide
Microsoft*
Search for


F# Performance - writing high performance code

F# uses the compilation facilities of the .NET CLR to generate high performance native code via the Common IL intermediary form. F# has the succinctness of a scripting language, and yet static type-checking and type-inference ensure that compact data representations are used and high performance efficient code is generated for all language constructs.

This page gives further tips on improving the performance of your F# code.

Optimizing your code

Faster code is produced by using the cross module optimizer (the "-O" options).  Not all optimizations are on by default.

Profiling your code

Good profiling tools are essential for achieving good performance in practice. F# works seamlessly with a range of memory and CPU profiling tools (see tool support). It is important to learn to use a profiler when developing code for high performance scenarios.

Reducing start-up times using NGEN

Applications will start-up faster if you produce .NET install-time compiled binary images using ngen.exe. This will work with both verifiable and non-verifiable code, and both debug and non-debug images. 

When using .NET 2.0 use a single invocation of ngen.exe for the final exe of the application:

    ngen install myprogram.exe

When using .NET 1.1 (or 1.0) use:

    ngen mylibrary.dll
    ngen myprogram.exe
Tips on how to optimize performance
  • Use profiling tools to identify the key time and space performance characteristics of your code.

  • Exception handling is implemented relatively inefficiently on many virtual machines. As a result, do not use exceptions for control within ML programs. This is the primary cause of poor performance in F# code. You can determine if your program is raising and catching exceptions by running under an interactive debugger such as cordbg.exe or Visual Studio. These will typically display exceptions as they are generated, even if subsequently caught.

  • The code generation works best with a .NET Common Language Runtime that supports generics. In order to run on non-generic CLRs, an erasure-to-Object model is used over the generated IL bytecode.  This results in some inefficient code sequences, especially when box/unbox operations need to be inserted on arguments in the middle of a complex call sequence. Another result is that some functions will generate many locals and intermediate unwrapping operations. This may also prevent tailcalls from being taken - this happens if the operation returns a polymorphic ('a) value that must be unwrapped/unboxed.

  • Top-level values are not GC'd by the .NET CLR. If you have large objects which you wish to be collected then make them local to a function.

  • Some corner constructs use implementation techniques that lead to slower execution than would be expected. These can be avoided by using the --fast-sublanguage-only compiler switch that prevents you from using these constructs.






©2008 Microsoft Corporation. All rights reserved. Terms of Use |Trademarks |Privacy Statement