views:

119

answers:

3

F# Interactive (and in general REPL-style tools) is an ideal entrance to performance profiling. What could be easier than to select a code block and send it right to a profiler that would come back with performance analysis report. Unfortunately it looks like existing profilers don't have REPL support: you have to either attach a profiler to a process or specify and executable or Web application to profile.

What I end up doing then is wrapping a code block to profile in a unit test and then executing a profile against NUnit command-line session. But is this the best we can do right now with F#?

+6  A: 

What is the question?

Do you know about the #time command? E.g.

#time "on"
for i in 1..1000000 do
    let r = f(i)
    ignore r

which gives F# interactive output like

--> Timing now on
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0

In any case, I think simply putting the code in an application and running the profile against the app is better than an NUnit test. Either way, yes, it costs you maybe an extra 30 seconds of time to paste the code into a new app and compile it in Release mode. But that's a price I'm happy to pay to get the rich profiling info that Visual Studio provides. Ideally the experience could be better, but I doubt you'll find any REPL-friendly profiling tools today (or tomorrow).

Brian
Yes, but this is useful only in simple cases. It does not give you a picture of how the execution time is split between the operations in the call stack.
Vagif Abilov
And to answer your question "what is the question?": the question is not about timing execution of an outer call. The question is about performance profiling that is much more than that: it's an extensive performance analysis based on gathered performance data. Modern performance profilers like dotTrace and ANTS can do it by attaching to a process or running an application, but it would be very efficient if they could profile code that is sent to F# Interactive. So the question was whether this can be achieved.
Vagif Abilov
I did not know about the #time command!
Stephen Swensen
+2  A: 

You can try to use profiler programmatic API to achieve this. I have not tried this, but here are the instruction for ANTS profiler: http://help.red-gate.com/help/ANTSProfiler3/0/en/Topics/AP_UsingTheAPI.html

I think the following might succeed:

  1. Start ANTS profiler and attach to fsi.exe
  2. #r "RedGate.Profiler.Api.dll" in fsi
  3. Sprinkle the code you want to profile with RedGate.Profiler.Api.Reset()/RedGate.Profiler.Api.TakeSnapshot()

DotTrace has (had?) similiar API (CPUProfiler.Start()/.StopAndTakeSnapshot()), but I could not find the references for latest versions.

Mitya
That's an interesting option! Thanks for letting me know. I will try it out.
Vagif Abilov
+1  A: 

But is this the best we can do right now with F#?

AFAIK, yes. This is a great idea for a feature in the next version of F# or a third-party product though!

Jon Harrop