-
Notifications
You must be signed in to change notification settings - Fork 702
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add top-level performance measuring guide page
- Loading branch information
1 parent
c1ddadb
commit d326c39
Showing
3 changed files
with
126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
How to analyze Haskell performance | ||
================================== | ||
|
||
When a Haskell application is slow or uses too much memory, | ||
Cabal and `GHC <https://downloads.haskell.org/ghc/latest/docs/users_guide/>`__ | ||
can help you understand why. | ||
|
||
The main steps are to | ||
|
||
1. let GHC insert performance measuring code into your application, | ||
2. run the application to collect a performance report and | ||
3. visualize that report. | ||
|
||
The process of inserting performance measuring code and collecting performance information | ||
is called "profiling". Cabal makes this easy to do. | ||
|
||
Profiling CPU performance | ||
------------------------- | ||
|
||
First, build your application, e.g. ``my-app``, with profiling enabled: | ||
|
||
.. code-block:: console | ||
$ cabal build --enable-profiling --profiling-detail=late my-app | ||
Under the hood, this will pass the corresponding | ||
`profiling compiler options <https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#compiler-options-for-profiling>`__ | ||
to GHC. The additional Cabal flag ``--profiling-detail=late`` instructs GHC to use | ||
so-called | ||
`late-cost-center profiling <https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#ghc-flag--fprof-late>`__ | ||
and insert performance measuring code only after important optimisations | ||
have been applied to your application code. | ||
This reduces the performance slow-down of profiling itself and gives you more realistic measurements. | ||
See the Cabal section on :ref:`profiling options <profiling-options>` for more details. | ||
|
||
.. note:: | ||
You can add further three recommended profiling options to your ``my-app.cabal`` file | ||
to control where measuring code is inserted into your application as follows: | ||
|
||
:: | ||
|
||
executable my-app | ||
... | ||
ghc-prof-options: | ||
-fprof-auto | ||
-fno-prof-count-entries | ||
-fprof-auto-calls | ||
... | ||
|
||
You can find more information on these options in the | ||
`GHC "cost-center" guide <https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#automatically-placing-cost-centres>`__. | ||
|
||
Second, run the application with the necessary | ||
`runtime system (RTS) options <https://downloads.haskell.org/ghc/latest/docs/users_guide/runtime_control.html>`__ | ||
to produce a profile report. | ||
|
||
.. code-block:: console | ||
$ $(cabal list-bin my-app) +RTS -pj -RTS | ||
<program runs and finishes> | ||
The report is written to a ``<app-name>.prof`` file, i.e. ``my-app.prof``, in the current directory. | ||
With the RTS option ``-pj`` the app produces a | ||
`"profile JSON" (pj) file report <https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--pj>`__. | ||
Other report format options can be found in the | ||
`GHC format documentation. <https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#time-and-allocation-profiling>`__. | ||
|
||
.. note:: | ||
|
||
You can combine both steps above into a single ``cabal run`` command: | ||
|
||
.. code-block:: console | ||
$ cabal run --enable-profiling --profiling-detail=late my-app -- +RTS -pj -RTS | ||
<program runs and finishes> | ||
Finally, load the profiling report file ``my-app.prof`` into a visualizer | ||
and look for performance bottlenecks. One popular open-source | ||
`flame graph <https://www.brendangregg.com/flamegraphs.html>`__ | ||
visualizer is | ||
`Speedscope <https://speedscope.app>`__, | ||
which runs in the browser and can open this report directly. | ||
|
||
Profiling your dependencies too | ||
------------------------------- | ||
|
||
The setup so far only profiles your main application, which is usually what you want. | ||
This happens by default, because Cabal command line options only apply to local packages | ||
and dependencies are usually not local. | ||
However, the bottlenecks may be in your dependencies, so you would want to profile those too. | ||
|
||
First, to enable ``late``-cost-center profiling of all packages/dependencies in your project, | ||
add the following to your project’s ``cabal.project`` file: | ||
|
||
.. code-block:: console | ||
package * | ||
profiling: true | ||
profiling-detail: late | ||
Second, rebuild your application with ``cabal build`` as before: | ||
|
||
.. code-block:: console | ||
$ cabal build my-app | ||
Resolving dependencies... | ||
Build profile: -w ghc-9.10.1 -O1 | ||
In order, the following will be built (use -v for more details): | ||
- base64-bytestring-1.2.1.0 (lib) --enable-profiling (requires build) | ||
- cryptohash-sha256-0.11.102.1 (lib) --enable-profiling (requires build) | ||
... | ||
There's no need to pass ``--enable-profiling`` to the build command manually, | ||
because it's already enabled in the project file (and seen in the build log). | ||
|
||
Finally, run the application with the ``-pj`` RTS option as before. | ||
You should now find more information in the profiling report ``my-app.prof``. | ||
|
||
Further information on how to apply Cabal options can be in the | ||
:ref:`Cabal options sections <package-configuration-options>`. | ||
Further in-depth information on profiling with GHC can be found in the | ||
`GHC profiling guide <https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html>`__. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters