Executable not found when I pass `stack exec` the `--profile` option?

Viewed 311

Can anyone help me understand this?

$ stack exec -- mvm4x4_amf +RTS -sstderr
mvm4x4_amf: Most RTS options are disabled. Link with -rtsopts to enable them.

$ stack exec --profile -- mvm4x4_amf +RTS -sstderr                                                                                                         
Executable named mvm4x4_amf not found on path: [{snip}]

I found the suggestion for the second command tried above here, in the Debugging section. (10th of 13 matches for search term: "rts")

After rebuilding my Stack project with: stack build --profile, I get:

$ stack exec --profile -- mvm4x4_amf +RTS -sstderr                                                                                                         
mvm4x4_amf: Most RTS options are disabled. Link with -rtsopts to enable them.

If I use this instead:

$ stack exec --profile mvm4x4_amf +RTS -sstderr

them my program runs, but I don't get any profiling information output.

If I "reach in" to the .stack-work/ directory and "execute by hand" (as I've seen recommended in some other posts related to this issue):

$ .stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build/mvm4x4_amf/mvm4x4_amf +RTS -sstderr
mvm4x4_amf: Most RTS options are disabled. Link with -rtsopts to enable them.

then it appears my executable wasn't actually built for profiling. But, attempting to explicitly rebuild it for profiling yields no action:

$ stack build --profile :mvm4x4_amf

$

Oh, does this help at all?:

$ stack exec mvm4x4_amf --rts-options --info
 [("GHC RTS", "YES")
 ,("GHC version", "8.6.5")
 ,("RTS way", "rts_v")
 ,("Build platform", "x86_64-apple-darwin")
 ,("Build architecture", "x86_64")
 ,("Build OS", "darwin")
 ,("Build vendor", "apple")
 ,("Host platform", "x86_64-apple-darwin")
 ,("Host architecture", "x86_64")
 ,("Host OS", "darwin")
 ,("Host vendor", "apple")
 ,("Target platform", "x86_64-apple-darwin")
 ,("Target architecture", "x86_64")
 ,("Target OS", "darwin")
 ,("Target vendor", "apple")
 ,("Word size", "64")
 ,("Compiler unregisterised", "NO")
 ,("Tables next to code", "YES")
 ]

Hmmm, in changing a cabal file option and rebuilding, I noticed something strange:

$ stack build --profile :mvm4x4_amf
luminous-0.5.0.0: unregistering (local file changes: luminous.cabal)
luminous> configure (lib + exe)
Configuring luminous-0.5.0.0...
luminous> build (lib + exe)
Preprocessing library for luminous-0.5.0.0..
Building library for luminous-0.5.0.0..
Preprocessing executable 'mvm4x4_amf' for luminous-0.5.0.0..
Building executable 'mvm4x4_amf' for luminous-0.5.0.0..
luminous> copy/register
Installing library in .../.stack-work/install/x86_64-osx/2428dc603454d346facf6484280fa92531e4d7789d3
3c4dd56c39cf70d79bd7e/8.6.5/lib/x86_64-osx-ghc-8.6.5/luminous-0.5.0.0-9ABiH0AyDmV25JxAv1cFEI                                                              
{snip}
Installing executable mvm4x4_amf in .../.stack-work/install/x86_64-osx/2428dc603454d346facf6484280fa
92531e4d7789d33c4dd56c39cf70d79bd7e/8.6.5/bin                                                                                                             
{snip}
Registering library for luminous-0.5.0.0..

$ stack exec which mvm4x4_amf
.../.stack-work/install/x86_64-osx/9af8b70f7f84a02189b610f95c8d289ab7d743df5c23a5d5d43b30afe0c02b7c/
8.6.5/bin/mvm4x4_amf                                                                                                                                      

Stack seems to be finding my mvm4x4_amf executable in a different directory than where it's installing it! Am I reading this correctly? Should I be concerned?

Oh, for reference:

$ stack --version
Version 2.1.3, Git revision 0fa51b9925decd937e4a993ad90cb686f88fa282 (7739 commits) x86_64 hpack-0.31.2
2 Answers

Aha! You have to do this:

$ stack exec --profile mvm4x4_amf --rts-options -sstderr

With that command I get my expected profiling results:

 294,885,845,152 bytes allocated in the heap
   3,900,063,256 bytes copied during GC
     160,061,616 bytes maximum residency (57 sample(s))
       6,223,696 bytes maximum slop
             152 MB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0     282964 colls,     0 par    6.696s   6.863s     0.0000s    0.0013s
  Gen  1        57 colls,     0 par    0.928s   1.048s     0.0184s    0.1195s

  INIT    time    0.000s  (  0.003s elapsed)
  MUT     time  217.655s  (221.658s elapsed)
  GC      time    7.624s  (  7.911s elapsed)
  RP      time    0.000s  (  0.000s elapsed)
  PROF    time    0.000s  (  0.000s elapsed)
  EXIT    time    0.000s  (  0.000s elapsed)
  Total   time  225.279s  (229.571s elapsed)

  %GC     time       0.0%  (0.0% elapsed)

  Alloc rate    1,354,833,854 bytes per MUT second

  Productivity  96.6% of total user, 96.6% of total elapsed

after my normal program output.

And, also:

$ stack exec --profile which mvm4x4_amf                                                                                                                    
.../.stack-work/install/x86_64-osx/2428dc603454d346facf6484280fa92531e4d7789d33c4dd56c39cf70d79bd7e/
8.6.5/bin/mvm4x4_amf                                                                                                                                      

So, I guess, the --profile option "steers" the stack exec command to a different install/ subdirectory? I guess that makes sense.

$ stack exec -- mvm4x4_amf +RTS -sstderr
mvm4x4_amf: Most RTS options are disabled. Link with -rtsopts to enable them.

$ stack exec --profile -- mvm4x4_amf +RTS -sstderr
Executable named mvm4x4_amf not found on path: [{snip}]

This happens because executables built with and without profiling information are actually very different executables. This is because emitting profiling information is very costly and thus can noticeably slow down the execution, so when you are building without --profile, all this extra code is stripped for performance.

Your second invocation was failing, because you didn’t have the profiling executable for your program built. Simply put, there are multiple directories in .stack-work with multiple sets of binaries built with different options, so stack exec --profile looks in the “profiling binaries” directory, which was empty in your case.

After rebuilding my Stack project with: stack build --profile, I get:

$ stack exec --profile -- mvm4x4_amf +RTS -sstderr                    
mvm4x4_amf: Most RTS options are disabled. Link with -rtsopts to enable them.

This invocation is the right one. As the error suggests, you now need to build your executable with -rtsopts to make your executable accept the RTS options that you want to pass to it.

If I use this instead:

$ stack exec --profile mvm4x4_amf +RTS -sstderr

them my program runs, but I don't get any profiling information output.

Here the problem is that stack is a Haskell problem itself, so your +RTS -sstderr oprtions are getting consumed by stack rather than passed to your binary. You absolutely need those -- (or, alternatively, you can use --rts-options <options>, which tells stack to pass +RTS <options> to your binary.

Related