Profile Haskell without installing profiling libraries for all dependencies - haskell

I wish to profile my program written in Haskell.
On compilation, I am told that I do not have profiling libraries for certain dependencies (e.g., criterion) installed and cabal aborts.
I have no interest in profiling parts of those dependencies; code called from main doesn't even use them.
How can I profile my application without installing profiling libraries I don't need and without removing all those dependencies?

A good way to circumvent having to compile everything with profiling is to use cabal sandbox. It allows you to set up a sandbox for one application only, and thereby you won't have to re-install your entire ~/.cabal prefix. You'll need a recent version of Cabal, so run cabal update && cabal install cabal-install first.
Once you initialise a sandbox, create a file cabal.config to include the necessary directives (in your case library-profiling: True; executable-profiling: True may also be handy.)
A side-effect of this is that you can test your code with dependencies that need not be installed globally, for example, experimental versions, or outdated versions.
EDIT: btw, I don't think you need to have profiling enabled for criterion to work. In any case, it works for me without profiling being enabled. Just write a Main module that contains main = defaultMain benchmarks where benchmarks has type [Benchmark], i.e. a list of benchmarks that you've written.
You then compile that file (say, we call it benchmarks.hs with ghc --make -o bench benchmarks.hs, and run the program, ./bench with the appropriate arguments (consult the criterion documentation for details. A good default argument is, say ./bench -o benchmarks.html which will generate a nifty report similar to this one)

I had the same problem this week, and although I had recompiled everything by hand, I was instructed in the IRC channel to do the following:
Go to your cabal config file (in case you don't know where)
Edit the line for enable library profiling (and while you are at it, enable documentation)
Run Cabal Install World

As mentioned in the question you refer to in your comment, a good way to solve this problem in the future is to enable profiling in the cabal configuration. This way all libraries are installed with profiling support. This might not be a satisfying solution but I guess many are opting for it.
If you are only interested in getting an impression of the memory usage of your program you can generate a heap profile of your program using -hT. More precisely, you have to compile the program with -rtsopts to enable RTS options then execute it using +RTS -hT. The compiler generates a file with the extension hp. You can convert the hp file into a postscript file with a heap profile using hp2ps. This should work without any profiling support, but note that I am too lazy to verify it as I have installed all libraries with profiling support ; )

Related

How does the workflow with Haskell Stack work?

I don't get the point about Stack.
I used to write my Haskell code in my favourite environment, ran or compiled using GHC(i), and if necessary, installed packages using Cabal. Now, that apparently is not the way to go any more, but I don't understand how to work with Stack. So far, I have only understood that I need to write stack exec ghci instead ghci to start a repl.
Apart from that, the docs always talk about 'projects' for which I have to write some yaml files. But I probably don't have any project -- I just want to launch a GHCi repl and experiment a bit with my ideas. At the moment, this fails with the unability to get the packages that I want to work with installed.
How is working with Stack meant? Is there any explanation of their use cases? Where do I find my use case in there?
Edit. My confusion comes from the fact that I want to work with some software (IHaskell) whose installation guide explains the installation via stack. Assuming I already have a GHCi installed whose package base I maintain e.g. using Cabal. How would I have to set up stack.yaml to make stack use my global GHCi for that project?
First, notice that stack will use its own package base independent from cabal. AFAIK they can't be shared... hence, if you run stack build it'll download packages (including the compiler) on its own package database.
Nevertheless stack allows to use a system compiler (but not other libraries). To do so, in the stack.yaml you must have the following two lines
resolver: lts-XX.XX -- keep reading below
system-ghc: True
The version of the stackage snapshot can be found in: https://www.stackage.org/. Each snapshot works with a different version of the compiler. Be sure to use a snapshot with the same compiler version you have in you system. If it happens your system ghc is greater than any lts, then you can set allow-newer: true in stack.yaml.
Now, if getting a different database from stack feels wrong to you, notice that you can build the project with cabal too, since stack at the end of the day spits out a cabal file. Probably, It wont work out of the box if you build with cabal. You can modify the cabal file to match exactly the version of the packages of the snapshot you are using
In summary:
You can use your system-wide ghc
you can not share libraries installed with cabal.
you can use cabal to build the project, probably modifying the ihaskell.cabal file to match versions of the stackage's snapshot.

Will ghc-options of an executable override ghc-options of linked libraries?

I have a main Haskell executable program with a cabal file. There, I specify the ghc-options.
This executable links against other libraries out in the wilderness. Will the ghc-options of the cabal files of these libraries be ignored?
I'm basically wondering whether the executable's ghc-options will be used for the entire enchilada (main executable + libraries).
Additional bounty notes: Please also expand on chi's comment below, namely, what exactly is the difference between ghc-options for compiling vs. linking. Which are which, and which are never needed in libraries? Maybe you can talk about some of the most important ones, such as the -threaded mentioned below.
Under the normal cabal-install workflow (and the stack workflow built atop it), flags specified in your Cabal file are local to your package, and should not trigger rebuilds. Similarly, options specified with --ghc-options on the command line are local to your package.
To your specific questions about -threaded, this flag has no effect on library code (as cabal-install will tell you), only on executables.
A brief listing of GHC flags is available here. In particular, note that -threaded is listed under Linking options, with a further link to Options affecting linking. From this information, we conclude that -threaded is only meaningful for executables because it signals to GHC that we wish to use the threaded runtime. If your package doesn't provide an executable, it has no need for any runtime, threaded or otherwise.
For a high-level explanation of compiling vs. linking: they are two of the steps between source code and executable. Compilation is the process of producing an object file from source code. Linking is the process of connecting the numerous object files which compose your executable. When you compile an executable, it has no idea that a function, say map exists unless you defined it, so it just compiles under the assumption that it does. The linking step is where we make all those names available and meaningful. In the case of -threaded, we are making the linking process aware of the threaded runtime, which all code calling on the runtime will use.
Since I don't know if you're using the standard cabal workflow, stack, or the new cabal.project workflow, here's a digression to discuss this behavior in the cabal.project case.
This is actually an open bug, right now.
The bug is tracked as issue 3883 on the Cabal GitHub (and somewhat in the related issue 4247).
Relevant to your question, according to current behavior, specifying flags in a ghc-options stanza in a cabal.project file causes those dependencies to be compiled (or recompiled, as the case may be) with those flags.

Differential Documentation with haddock

If I do a cabal build on my library, then change a file, the next time I run cabal build, I only have to recompile files affected by the changes. I'm not getting the same behavior with the cabal haddock command: when I run it after changing a file, cabal/haddock ends up throwing out all of the previous work and starting from scratch. This is rather time consuming; is there a way to get differential updates to documentation?
Here's a dump of the command cabal issues to generate the documentation.
processModules documentation says:
Create Interfaces and a link environment by typechecking the list of modules using the GHC API and processing the resulting syntax trees.
And that is the core function of haddock. So ATM the answer your question is No.
cabal build doesn't help cabal haddock at all, as haddock type-checks modules with different parameters (e.g. __HADDOCK__ CPP variable enabled)
Making reliable incremental haddock generation is hard, as the code later in the dependency graph can alter the modules documentation previous to that point: particularly the instances listings. Probably one could dump module interfaces.
Looking at the code of processModules the first step is something that could be possible to do incrementally, rest is using global information.
Try turn verbosity to the max i.e. --haddock-options=--verbosity=2 and check how much time is spent between Creating interfaces... and Attaching instances....

How to use two different compilers for different targets in a .cabal file?

When I run cabal build it uses some Haskell compiler to build the executables and/or test-suites in my .cabal file.
Can I control which compiler is used for the different targets? Ideally, I would like to have separate build targets that use ghc and ghcjs in the same .cabal file. It seems to me that someone might want to use ghc and hugs or two version of ghc in the same project. Is this currently possible?
Also, how does cabal decide what compiler to use when running cabal build? I saw there is a compiler option in my ~/.cabal/config file but changing it from ghc to ghcjs and uncommenting it, did not seem to change what cabal build does.
The compiler to use is determined during the configure step (or during an install step's implicit configure step, which does not share configuration options with a previous configure step). It is also determined by the entity building the package and cannot be influenced by the person writing the package. Probably what happened to you is that a previous cabal build implicitly invoked the configure step and chose a compiler; future builds will keep a previous choice of compiler over one stuck in your global configuration file. You can countermand that by simply manually running cabal configure again.
It is possible to cause a build to fail with the wrong implementation, e.g.
library
if impl(ghc)
buildable: False
will prevent cabal from trying to build the package using GHC. However, this isn't really useful for building separate parts of a package with separate compilers, as cabal will refuse to install a package unless it can build the whole thing with a single compiler.
Probably the best way forward is to make separate packages for things that should be built by separate compilers.

Is it possible to profile a Haskell program without prof libraries?

Is it possible to time profile a Haskell program without installing the profiling libraries?
When I pass the -prof option to ghc, I always get errors like this one:
src/MyPKG/FooBlah.lhs:7:7:
Could not find module `Data.Time.Calendar':
Perhaps you haven't installed the profiling libraries for package `time-1.1.4'?
Use -v to see a list of the files searched for.
I know that the solution is to install with cabal profile versions of the libraries, but sometimes this is a pain in the ass (sorry for the bad language).
I think it should be possible to profile my program and the calls that have no symbols should appear as ???? or something like that in the output.
No, it's not possible. Building for profiling changes the representation and function calls have extra parameters to keep track of the profiling data.
You have to install the profiling libraries to use GHC's profiler, even if it's a pain in the rear.

Resources