From 9839ef1ccce1beab2c1a5d34429d320c8a23da32 Mon Sep 17 00:00:00 2001 From: Malte Neuss Date: Sat, 9 Nov 2024 15:23:40 +0100 Subject: [PATCH] Add top-level performance measuring guide page --- ...ow-to-analyze-haskell-code-performance.rst | 61 +++++++++++++------ 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/doc/how-to-analyze-haskell-code-performance.rst b/doc/how-to-analyze-haskell-code-performance.rst index b8cbf5a1cb3..21cfcda5abd 100644 --- a/doc/how-to-analyze-haskell-code-performance.rst +++ b/doc/how-to-analyze-haskell-code-performance.rst @@ -7,6 +7,7 @@ Cabal and the 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. @@ -21,25 +22,42 @@ First, build your application, e.g. ``my-app``, with profiling enabled: .. code-block:: console - $ cabal build --enable-profiling --profiling-detail=late exe:my-app + $ cabal build --enable-profiling --profiling-detail=late my-app Under the hood, this will pass the corresponding `profiling compiler options `__ to GHC. The additional Cabal flag ``--profiling-detail=late`` instructs GHC to use -`"late-cost-center" profiling `__ +so-called +`late-cost-center profiling `__ and insert performance measuring code only after important optimisations -have been applied, to minimize the impact of profiling on performance. +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 ` 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-options: + -fprof-auto + -fno-prof-count-entries + -fprof-auto-calls + ... + +You can find more information on these options in the +`GHC "cost-center" guide `__. + Second, run the application with the necessary `runtime system (RTS) options `__ to produce a profile report. .. code-block:: console - $ cabal list-bin exe:my-app - /path/to/my-app - $ /path/to/my-app +RTS -pj -RTS + $ $(cabal list-bin my-app) +RTS -pj -RTS The report is written to a ``.prof`` file, i.e. ``my-app.prof``, in the current directory. @@ -48,11 +66,22 @@ With the RTS option ``-pj`` the app produces a Other report format options can be found in the `GHC format documentation. `__. -Finally, load the profiling report file into a visualizer to look for performance bottlenecks. -One popular open-source +.. 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 + + + +Finally, load the profiling report file ``my-app.prof`` into a visualizer +and look for performance bottlenecks. One popular open-source `flame graph `__ -visualizer is `Speedscope `, which runs in the browser and comes with -an example. +visualizer is +`Speedscope `__, +which runs in the browser and can open this report directly. Profiling your dependencies too ------------------------------- @@ -62,7 +91,7 @@ This happens by default, because Cabal command line options only apply to local and dependencies are usually not local. However, the bottlenecks may be in your dependencies, so you would want to profile those too. -To enable ``late``-cost-center profiling`` of all packages/dependencies in your project, +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 @@ -71,27 +100,25 @@ add the following to your project’s ``cabal.project``` file: profiling: true profiling-detail: late -Then rebuild your application with ``cabal build``: +Second, rebuild your application with ``cabal build`` as before: .. code-block:: console - $ cabal build exe:my-app + $ 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). -Then run the application with the ``-pj`` RTS option as before. - +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 `. - Further in-depth information on profiling with GHC can be found in the `GHC profiling guide `__.