# GHC Profiling a Cabal Project with an Interactive Application

**URL:** <https://discourse.haskell.org/t/ghc-profiling-a-cabal-project-with-an-interactive-application/10465>\
**Category:** Learn\
**Created:** [October 4, 2024, 9:40pm UTC](https://discourse.haskell.org/t/ghc-profiling-a-cabal-project-with-an-interactive-application/10465 "2024-10-04T21:40:46Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [October 4, 2024, 11:33pm UTC](https://discourse.haskell.org/t/ghc-profiling-a-cabal-project-with-an-interactive-application/10465/2 "2024-10-04T23:33:58Z")

</div>

Hi @morphismz.

I feel like profiling Haskell programs is both easy and really cool!  
It would be great if this feeling were more widespread. If you come up with a good place to write down the following information more prominently, we should try to put it there.

To profile a Haskell executable from a large Cabal project, you need to, first and foremost, compile your executable with profiling. To do so, pass `--enable-profiling` to Cabal, and use late-cost-center profiling for profiling to not interfere with optimisation (`--profiling-detail=late`).

```txt
cabal build --enable-profiling --profiling-detail=late exe:my-executable-name

```

Second, you must run the program with the RTS flags to produce a profile. I suggest using `-pj` to produce a flame graph profile in JSON that can be loaded into [https://speedscope.app](https://speedscope.app). `-pj` must be passed after `+RTS`, or in between `+RTS` and `-RTS`, because it is a runtime system option.

```haskell
cabal list-bin exe:my-executable-name
> /path/to/exe
/path/to/exe +RTS -pj -RTS
> <program is now running>

```

At this point, you can simply load the `my-executable-name.prof` file into [https://speedscope.app](https://speedscope.app) to get something like:

 ![Screenshot 2024-10-05 at 00.32.31](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/8/83824ddf13c7c1ee1258f637837f783cd37f0a06.jpeg)

* * *

## Profiling your dependencies too

Even though this is plenty good, it’s often useful or needed to profile _your dependencies too_. The reason why this doesn’t happen by default is because cabal command line flags apply to _local packages_ only. However, all dependencies fetched from hackage count as non-local.

To apply profiling and profiling-detail: late to all packages/dependencies in your project, add to the project’s `cabal.project`:

```haskell
package *
    profiling: true
    profiling-detail: late

```

Now, recompile your executable and re-run with `+RTS -pj` and reload speedscope to get a more detailed profile with all relevant packages. You should see all packages being built with profiling, for example:

```haskell
$ cabal build exe:cabal
Resolving dependencies...
Build profile: -w ghc-9.10.1 -O1
In order, the following will be built (use -v for more details):
 - base16-bytestring-1.0.2.0 (lib) --enable-profiling (requires build)
 - base64-bytestring-1.2.1.0 (lib) --enable-profiling (requires build)
 - echo-0.1.4 (lib) --enable-profiling (requires build)
 - cryptohash-sha256-0.11.102.1 (lib) --enable-profiling (requires build)
 - ed25519-0.0.5.0 (lib) --enable-profiling (requires build)
 - hsc2hs-0.68.10 (exe:hsc2hs) --enable-profiling (requires build)
 - hashable-1.4.7.0 (lib) --enable-profiling (requires build)
 - alex-3.5.1.0 (exe:alex) --enable-profiling (requires build)
 - open-browser-0.2.1.0 (lib) --enable-profiling (requires build)
 - regex-base-0.94.0.2 (lib) --enable-profiling (requires build)
 - safe-exceptions-0.1.7.4 (lib) --enable-profiling (requires build)
 - splitmix-0.1.0.5 (lib) --enable-profiling (requires build)
 - th-compat-0.1.5 (lib) --enable-profiling (requires build)
 - tar-0.6.3.0 (lib:tar-internal) --enable-profiling (requires build)
 - resolv-0.2.0.2 (lib:resolv) --enable-profiling (requires build)
 - zlib-0.7.1.0 (lib) --enable-profiling (requires build)
 - network-3.2.3.0 (lib:network) --enable-profiling (requires build)
 - lukko-0.1.2 (lib) --enable-profiling (requires build)
 - async-2.2.5 (lib) --enable-profiling (requires build)
 - Cabal-syntax-3.13.0.0 (lib) --enable-profiling (cannot read state cache)
 - regex-posix-0.96.0.1 (lib) --enable-profiling (requires build)
 - random-1.2.1.2 (lib) --enable-profiling (requires build)
 - network-uri-2.6.4.2 (lib) --enable-profiling (requires build)
 - tar-0.6.3.0 (lib) --enable-profiling (requires build)
 - Cabal-3.13.0.0 (lib) --enable-profiling (cannot read state cache)
 - edit-distance-0.2.2.1 (lib) --enable-profiling (requires build)
 - HTTP-4000.4.1 (lib) --enable-profiling (requires build)
 - hackage-security-0.6.2.6 (lib) --enable-profiling (configuration changed)
 - cabal-install-solver-3.13.0.0 (lib) --enable-profiling (configuration changed)
 - cabal-install-3.13.0.0 (lib) --enable-profiling (configuration changed)
 - cabal-install-3.13.0.0 (exe:cabal) --enable-profiling (configuration changed)

```

---

_[View the full topic](https://discourse.haskell.org/t/ghc-profiling-a-cabal-project-with-an-interactive-application/10465)._
