summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2023-01-27 14:55:57 +0000
committersheaf <sam.derbyshire@gmail.com>2023-02-13 11:36:41 +0100
commitda208b9aa03eaeec34528a7815d4d3451c106e18 (patch)
treee6b1a0fb1bd8c09a05932b7c0cf4634b30467575
parent1e9eac1c01077c2cd3ce5bf0e4a77c0affaf88e9 (diff)
downloadhaskell-wip/profiling-docs-refresh.tar.gz
docs: Add section about profiling and foreign callswip/profiling-docs-refresh
Previously there was no documentation for how foreign calls interacted with the profiler. This can be quite confusing for users so getting it into the user guide is the first step to a potentially better solution. See the ticket for more insightful discussion. Fixes #21764
-rw-r--r--docs/users_guide/profiling.rst36
1 files changed, 36 insertions, 0 deletions
diff --git a/docs/users_guide/profiling.rst b/docs/users_guide/profiling.rst
index d8199adfd7..4acd13c48c 100644
--- a/docs/users_guide/profiling.rst
+++ b/docs/users_guide/profiling.rst
@@ -33,6 +33,9 @@ Time profiling a program is a three-step process:
3. Examine the generated profiling information, use the information to
optimise your program, and repeat as necessary.
+The time profiler measures the CPU time taken by the Haskell code in your application.
+In particular time taken by safe foreign calls is not tracked by the profiler (see :ref:`prof-foreign-calls`).
+
.. _cost-centres:
Cost centres and cost-centre stacks
@@ -310,6 +313,39 @@ and become CAFs. You will probably need to consult the Core
.. index::
single: -fprof-cafs
+.. _prof-foreign-calls:
+
+Profiling and foreign calls
+---------------------------
+
+Simply put, the profiler includes time spent in unsafe foreign
+calls but ignores time taken in safe foreign calls. For example, time spent blocked on IO
+operations (e.g. ``getLine``) is not accounted for in the profile as ``getLine`` is implemented
+using a safe foreign call.
+
+The profiler estimates CPU time, for Haskell threads within the program only.
+In particular, time "taken" by the program in blocking safe foreign calls
+is not accounted for in time profiles. The runtime has the notion of a virtual
+processor which is known as a "capability". Haskell threads are run on capabilities,
+and the profiler samples the capabilities in order to determine what is being
+executed at a certain time. When a safe foreign call is executed, it's run outside
+the context of a capability; hence the sampling does not account for the time
+taken. Whilst the safe call is executed, other
+Haskell threads are free to run on the capability, and their cost will be attributed
+to the profiler. When the safe call is finished, the blocked, descheduled thread can
+be resumed and rescheduled.
+
+However, the time taken by blocking on unsafe foreign calls is accounted for in the profile.
+This happens because unsafe foreign calls are executed by the same capability
+their calling Haskell thread is running on. Therefore, an unsafe foreign call will
+block the entire capability whilst it is running, and any time the capability is
+sampled the "cost" of the foreign call will be attributed to the calling cost-centre stack.
+
+However, do note that you are not supposed to use unsafe foreign calls for any
+operations which do block! Do not be tempted to replace your safe foreign calls
+with unsafe calls just so they appear in the profile. This prevents GC from
+happening until the foreign call returns, which can be catastrophic for performance.
+
.. _prof-compiler-options:
Compiler options for profiling