FSX debugging

1,214 views
Skip to first unread message

czb

unread,
Mar 18, 2013, 3:29:42 AM3/18/13
to fsharp-o...@googlegroups.com
Are there any plans to add debugging support to fsx files?

Often, I have to do small tasks such as parse a file and do something with it etc. It is usually a matter of at max. 50 lines of code. I therefore start writing *.fsx file. I write it and run it and I get... an error :) Then I have two options. Flood the code with printfn mess or convert it into a single *.fs file solution. Based on my experience, I usually pick the latter => I convert the fsx into a single *.fs file solution as it is much more convenient way to find the error.

Doing that the *.fsx files looses their point. If I am to write more then 5 lines of code, I am afraid of using *.fsx files because at the end of the day, I can be almost certain, that I will have to convert them into a solution.

What is a point of having a *.fsx files without the debugging support?

Tim Robinson

unread,
Mar 18, 2013, 3:49:01 AM3/18/13
to fsharp-o...@googlegroups.com
I normally use printf debugging on .fsx scripts, or they're short enough to fix without needing to use a debugger. I switch to a full F# project at the point where the script code becomes to hard to understand.

However, it's possible to attach the Visual Studio debugger to the fsi.exe process, set breakpoints, step through code, etc. You can attach by hand, or you can add a call to System.Diagnostics.Debugger.Break.

The --debug+ flag on the fsi command line makes debugging possible; I believe Visual Studio adds this automatically, but if you run fsi by hand you'll need to add it.

(This applies to Visual Studio on Windows; I haven't tried the Monodevelop debugger with fsharpi.)

--
--
You received this message because you are subscribed to the Google
Groups "FSharp Open Source Community" group.
To post to this group, send email to fsharp-o...@googlegroups.com
To unsubscribe from this group, send email to
fsharp-opensou...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/fsharp-opensource?hl=en
 
---
You received this message because you are subscribed to the Google Groups "FSharp Open Source Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fsharp-opensou...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Nicolas

unread,
Mar 18, 2013, 6:24:03 AM3/18/13
to fsharp-o...@googlegroups.com
fseye comes in handy as well as a generalized printf

Oldrich Svec

unread,
Mar 18, 2013, 6:31:13 AM3/18/13
to fsharp-o...@googlegroups.com
Thank you for your replies. How difficult would be to do the following?:

In visual studio, I click on an icon or press a hot-key. The *.fsx file that I am currently in would get executed by the FSI. If there is any break-point in the *.fsx file, it would automatically break at that position. Is that doable, and if so, do you know how?

It is pain to look for bugs in nested loops (Array.map ...) etc. as printfn in the loop just prints and prints and prints... :) and there is no easy way how to send to FSI just part of the loop.


You received this message because you are subscribed to a topic in the Google Groups "FSharp Open Source Community" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/fsharp-opensource/JPoDL7iknd4/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to fsharp-opensou...@googlegroups.com.

Dave Thomas

unread,
Mar 18, 2013, 6:39:10 AM3/18/13
to fsharp-o...@googlegroups.com, fsharp-o...@googlegroups.com
If your going to be spending any substantial time debugging then just using the IDE would make the most sense to me.  

Integrating debugging with VS or monodevelop would take a little effort but would be doable( probably easier from monodevelop)

Tim Robinson

unread,
Mar 18, 2013, 6:49:16 AM3/18/13
to fsharp-o...@googlegroups.com
Agreed. I think there's enough functionality already there for somebody to make this work, but the open source community is unlikely to have any impact on Visual Studio itself.

Oldrich Svec

unread,
Mar 18, 2013, 6:57:28 AM3/18/13
to fsharp-opensource
*substantial time debugging* - I would not say that I spend any substantial time debugging but the rule of thumb is that whenever I use *.fsx no matter how large the file is, there is always a bug hidden in a loop that forces me to switch to a solution with a *.fs file. It happened to me so often that I wonder why such a basic feature as debugging is not supported for fsx files. It is like somebody is cutting my right hand saying that I do not need it anyway :)

As for the IDE. I am open to switching to Xamarin (monodevelop), if that makes the integration of debugging fsx files easier :).

The last note is that I have just tried to open fsx. file, add the following code, attach fsi.exe and run the code. I am however not able to step into the Array.init function.

let a = Array.init 5 (fun i ->
  let b = 4
  i + b
)


Tim Robinson

unread,
Mar 18, 2013, 7:01:00 AM3/18/13
to fsharp-o...@googlegroups.com
Stepping through an F# closure is fundamentally complicated by the fact that the code detours through the F# runtime. Try setting a breakpoint on "let b = 4". If you have a complicated function (complicated enough to require a debugger), it can be helpful to put it in its own "let fn i = ..." block; the Visual Studio debugger can have problems matching compiled lambda functions with their source code.

Oldrich Svec

unread,
Mar 18, 2013, 7:07:21 AM3/18/13
to fsharp-o...@googlegroups.com
Maybe I am doing something wrong but the following does not work either. I hit ctrl+alt+p to open attach to process, find fsi.exe, attach it. I execute the code by alt+enter and try to step into "test" function. It is however not possible.

Just to be clear. I do not require that it must work together with "alt+enter" hotkey. For me it is enough if there was a hotkey that would execute the whole fsx file with enabled debugging for that file.
let test i =
  let b = 4
  i + b
 
let a = Array.init 5 test

Don Syme

unread,
Mar 18, 2013, 6:44:43 PM3/18/13
to fsharp-o...@googlegroups.com

Hi Oldrich,

 

In VS, you can also create an empty project, add the .fsx script to the project, change the CompileAction to “Compile” and compile/execute that way. That is, you don’t need to rename your script to “.fs”

 

Note you could package that up into an “F# Scripting Project” template which already contains the script and populates the project.

 

Also, if I have a command line hanging around, I tend to use

fsc -g --optimize- script.fsx

devenv /debugexe script.exe

 

or just

                devenv /debugexe fsi.exe script.fsx

 

 

Cheers

Don

--

Steven Taylor

unread,
Oct 1, 2013, 11:30:17 AM10/1/13
to fsharp-o...@googlegroups.com

(... reviving an old thread)


Also, if I have a command line hanging around, I tend to use

fsc -g --optimize- script.fsx

devenv /debugexe script.exe

 

or just

                devenv /debugexe fsi.exe script.fsx


When using either of these options, should I expect to be able to step into the source code?  I keep getting "Source Not Available".    The .dll and pdb files exist.  If inspect these files with a text editor, the correct source file paths are embedded in the .dll & .pdb versions.  Is there a step that I'm missing?

Otherwise, this right-click on fsi in the IDE projects lists looks good, although it'd be nice if I didn't have to use the mouse to kick off the test.  

thanks,
-Steven

Eric

unread,
Oct 1, 2013, 11:48:02 AM10/1/13
to fsharp-opensource
Maybe I'm missing something here.  This is what I do to debug fsx files.
 
  1. In Visual Studio F# Interactive window, right click, Reset Session
  2. If F# Interactive window run any necessary setup commands. e.g. #I, #r, open
  3. Set your break point(s) in Visual Studio.
  4. Using VS menu: Tools -> Attack to Process..
  5. Double click process: Fsi.exe
  6. With mouse, select example statement you want to debug, right click, Send To Interactive.

You should be at your first break point.

 

Regards, Eric

Steven Taylor

unread,
Oct 1, 2013, 12:51:42 PM10/1/13
to fsharp-o...@googlegroups.com, fsharp-opensource
The attach method works fine.  The motivation is to streamline a dev / test sequence that I'm in.  VS gets in the way sometimes, hence trying to drop down to the command line


Eric

unread,
Oct 1, 2013, 1:07:12 PM10/1/13
to fsharp-opensource
Ahh,
 
I find taking smaller steps and building up from the bottom with lots of test cases helps me to avoid having to do debug sessions. The more I work with F# the less and less I use the debugger.
 
Regards, Eric

Steven Taylor

unread,
Oct 1, 2013, 2:57:09 PM10/1/13
to fsharp-o...@googlegroups.com


On 1 Oct 2013, at 18:07, Eric <researc...@gmail.com> wrote:

Ahh,
 
I find taking smaller steps and building up from the bottom with lots of test cases helps me to avoid having to do debug sessions.

Agree mostly... However there are times when a faster response / less in the way / closer to the metal approach can be more productive.  It's similar to working with a fsx from fsi prior to everything getting well defined plus formalising further with a .fs.  We all like that right?

btw: it is a test based approach, but just that it's being driven more from the command line in the initial stages.  

Joseph Ellsworth

unread,
Dec 6, 2013, 10:48:08 PM12/6/13
to fsharp-o...@googlegroups.com
Hi Don, 

Your answer was a great help.  I Googled for a solution a 1/2 dozen times and finally found your answer. 

I also prefer to build using FSC.   I use the standalone and static link options which allow me to copy the .exe file to any windows server and have it run correctly without worrying about what version of .net is locally installed.  It also allows me to run exe files that were built at different times against different versions of underlying libraries without worrying about DLL conflicts.   I have found this to be a huge time saver and it facilitates incremental releases for different analyzers without planning a huge release cycle which is also a time saver.  When combined this has largely eliminated the DLL reference hell I have observed across many .net projects.      It has naturally enabled an incremental RAD release approach that every .net team talks about but none ever seem to deliver.  

Perhaps I am unduly influenced the old Unix make files but I find this approach infinitely easier to manage than the file and directory proliferation caused by visual studio solutions.   I still use the visual studio editor for intellisense, syntax checking  and colorization but my source management is a lot closer to how you could use the paths in Python and C.   We have a lot of shared libraries that evolve over time and it is simply easier to release single EXE files than risk DLL conflicts.    Since you can specify the code dependencies at the source level having to specify them again at the tool level is simply wasted effort.   It is more explicit in the code and makes module sharing easier.     I think we invest less than 10% of the time in that portion of the compared to what I have seen consumed by this in .net projects at major companies.       I know Microsoft had not intended FSC to be used with source files  referencing dozens to hundreds source members but it works and I think this approach provides a higher net ROI than using the visual studio projects which are a maintenance hassle.   If Microsoft ever makes it impossible I may have to consider porting to a different language. 

I have not spent a single hour in trying to fix a corrupted solution.   Our modify, build, execute cycle is super fast.  I have never had to move a source member simply to get the project dependencies fit.   I have never had an out of date DLL waste hours of debugging at the worst possible time.   Our release cycles are minutes and easily reversed rather than a catastrophic event.   Net, net this approach has saved hundreds of hours of wasted time compared to normal visual studio IDE development using their solutions and projects.   

I did the first 6 months of debugging with logging and good test harnesses but as your other contributors pointed out it is occasionally useful to be able to step through with a debugger.      Your link on how to do source level debugging that works against compiled FSX files has been an immense help.   

With visual studio 2012 I found that the following worked for me. 

  The SellOnDropBuyOnRise.exe is the executable built by the fsc.exe
 fsc --debug:full SellOnDropBuyOnRise.fsx

  "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" /debugexe SellOnDropBuyOnRise.exe
  I obtained the devenv path from properties under the start menu. Will add it to my PATH environment variable next.
The same think did not work for Visual Studio express.


After starting the development environment I chose the debug option <step into new instance>

I want to compliment Microsoft.   F# is so expressive and the FSC compiler so fast that it produces executable files from dozens of .FSX source members from dozens of directories  faster than either GCC or GO for a similar sized project.     I know this is not Microsoft's  intended use but they got this part right.      You must use the  #I directive and you really need to use namespaces and modules to get the name resolution correct across multiple source directories to work.   The only real irritation is that Microsoft  messed up their own file write logic so about 1/3 the time FSC fails with an error message  claiming the EXE file is locked.   This is easily fixed with a bat file which runs the cygwin rm -f on the EXE file before calling FSC.  When the EXE is removed first FSC  always produces the EXE file even when it complains about the error.   

One recommendation for FSC is to adopt a FSC_PATH similar to the PYTHON_PATH.    Python, C, Java, LUA and Perl all support this for good reason.     In Python you can specify a include such as #Load "HTPPServer.fsx" and they will search directories in the order specified for the first source member that matches the name specified in by the Load.   The do this transparently and the directory location does not change the names space for the source member.      F#  makes this more difficult where you have to use the #I directive to change in to the directory before including the source member.    In F# it will not find the module at all unless you specify the full path such as "./HTTP/HTTPServer.fsx"  and if it is included from source members in different directories the namespace ends up conflicting.  The only way I found to work around it is to use the #I to the directory containing  source and then load the source member.       The Python approach is superior because it allows a engineer who is working on a new version of a library to include that in the environment variable path while testing temporarily and then the next time he opens a new shell it is reset to the default so it is back to using the standard version.  It allows changes to occur in micro that become a major hassle without that feature.  

Here a fully expanded FSC command line from my production make BAT

  fsc --debug:full --standalone  --optimize+ --crossoptimize+ --tailcalls+ --pdb:NONE --lib:c:\Windows\Microsoft.NET\Framework\v4.0.30319;.;..;.\lib;..\lib; DBarsMaint.fsx   

Most of this expansion is from environment variables and most of the time you can can skip the framework portion of the library. 
The --pdb:NONE is actually important because otherwise the PDB file ends up locked and messes up task manager so it doesn't show the proper EXE name.    

Our run-time BAT files always create a local copy of the EXE and run it for their local goal set.  For example  DBarsMaint.EXE may be copied to DBarsMaint019.exe representing the executable for the 1.9% goal set.    This allows us to easily differentiate different goal sets running the same code in TaskMgr so we can easily see what to kill if resources get scarce.       It also allows our  internal logging system to store it's log files according to that active EXE.    Perhaps most important it allows us to  update DBarsMaint.EXE on the server at any time and the next time the task scheduler runs the job it will replace DBarsMain019.exe with the new version.  This may seem unimportant but some of these jobs finish at 2 in the morning and I do not want to be awake to switch executables and I  do not want to interrupt a long running server executable to upgrade that may be a minor feature change. 

I have only tried distributing these EXE files to a closely held group  of servers so I have no idea if they would work on a broader set of servers with different .net installed.   What I do know is that they will run correctly on a generic  windows-8 box and 2008 server where no .net or visual studio has ever been installed. 

We host our HTTP server using the HTTP lib using F# async code.   So far it has performed flawlessly.  It allows us to run as a separate service which we can see independently and where we can restart individual executable without affecting the other services.   Perhaps most important is each executable is responsible for it's own memory management and unless it crashes the OS they are unlikely to affect other listeners on the same server.  I can not tell you how often in past projects they had to bounce IIS to resolve a problem.   In our approach the only time we needed to restart multiple listeners has been after a major windows update when we needed to reboot.    

Our DQServer is analogous to a cross between RSS Server and a ActiveMQ server but with a pure HTTP interface, super high performance and replay from the beginning of time built in.   DQServer has been measured at over 200K durable record inserts per second and over 700K records reads per second from a durable store across the HTTP interface.  It has ran without a hitch for months where we where pulling over 30 million records (about 3 gigabytes) per run 5 to 7 runs per hour concurrently from several client machines.     We had to be ultra careful about memory usage and minimizing garbage collection overhead but I have to admit Microsoft did a bang-up job with the HTTP server to F# Async interface. 

We use the legacy windows service hosting not the service host disaster common for .net.   It takes just a little more work to set up but is trivial after that.   It provides a key advantage that the same executable can run as a console app with a simple command line switch.  This single benefit allows us to switch the exact same compiled code for debugging and execution in a console where we can have it listen on a different port has saved more time than I can possibly explain.    I find being able to manage and see the executable by name in standard tools such as Service Manager gives us the ability to properly use the windows process based task control which is nearly impossible under IIS or under service host.       We keep our server CPU at 90% but since most of that is deferral analysis work scheduled under the windows idle level scheduling the high priority processes still get instance service and the server is always instant response.

Reply all
Reply to author
Forward
0 new messages