Can anyone recommend a performance profiling tool with good F# support?
I’ve been using Visual Studio 2010 profiler but I’ve found a few issues when using F#. It feels more like I’m profiling the byte code after reflection than the original F#.
For example when profiling the following slightly contrived example:
let Add a b =
a + b
let Add1 = Add 1
let rec MultiAdd count =
match count with
| 1 -> 1
| _ -> (Add1 1) + (MultiAdd (count - 1))
MultiAdd 10000 |> ignore
I get the following call tree:
When I view Microsoft.FSharp.Core.FSharpFunc`2.Invoke(0) in the Function Details I see:
I understand that what I seeing is based on the underlying implementation of the compiled code and although I can follow it, it’s hard going.
Does anyone have experience of using other profiling tools with F# and do they do a better job of mapping to the original F# code?
American singer Selena Gomez has released three solo studio albums, two compilation albums, four extended plays (EPs), 34 singles (including 7 as a featured artist) and four promotional singles.
My answer may disappoint you, but it might be helpful.
A few months ago, I tried to find a good free .NET profiler for my F# project. My experience with nprof, slimtune, EQATEC and (recently commercial) Xte profiler was not decent at all. I found their support for F# was very limited, and had to fall back to Visual Studio 2010 profiler. I think your best bet here is some commercial profiler (which I have no experience with).
After some time, I get used to the profiler and see its presentation of results easy, clear and understandable. If you were optimizing parallel programs, using the Concurrent Visualizer would be unavoidable. That said the single thing you care is performance; getting on well with VS 2010 profiler is worth to try.
For profiling F# code, I also find CLR Profiler and ILSpy worth to mention. The former can visualize heaps in case you want to minimalize memory allocation or garbage collection. The latter can produce equivalent code in IL or C# (which I'm more familiar with than F#); it may help to understand how high-order constructs in F# work in order to use them appropriately.
UPDATE:
Dave Thomas has written an excellent blog post where he used several commercial profilers to detect memory leaks and tune an asynchronous application. Take a look at those profilers; they may suit your preference.
It sounds like your profiling in Debug mode. You need to enable "Optimize code" from project -> properties -> build menu. You could also profile in release mode which has this enabled by default. If you don't there will be lots of invoke calls and Tuple object creation among other things.
The MultiAdd function above is not tail recursive. If it were, you would also need to enable "Generate tail calls" in Debug mode for profiling.
This would also be a good case for tail call optimization.
let Add a b =
a + b
let Add1 = Add 1
let rec MultiAdd total count =
match count with
| 1 -> 1 + total
| _ -> MultiAdd (count - 1) (total + Add1 1)
MultiAdd 10000 0 |> ignore
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With