diff options
author | Alexander Kjeldaas <alexander@schibsted.com> | 2020-07-03 11:38:41 +0200 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-09-29 09:41:27 -0400 |
commit | 162492ea0903e5b7c96f1f3934a70571f5daad23 (patch) | |
tree | 5c8aa3ce5016b3f929f165532fb443fdbf370728 | |
parent | cd6030623eabe9de80779ff0ba5081be01a6a3f4 (diff) | |
download | haskell-162492ea0903e5b7c96f1f3934a70571f5daad23.tar.gz |
Document interaction between unsafe FFI and GC
In the multi-threaded RTS this can lead to hard to debug
performance issues.
-rw-r--r-- | docs/users_guide/exts/ffi.rst | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/docs/users_guide/exts/ffi.rst b/docs/users_guide/exts/ffi.rst index 56f55352ef..3b681252e8 100644 --- a/docs/users_guide/exts/ffi.rst +++ b/docs/users_guide/exts/ffi.rst @@ -803,16 +803,34 @@ Foreign imports and multi-threading ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When you call a ``foreign import``\ ed function that is annotated as -``safe`` (the default), and the program was linked using :ghc-flag:`-threaded`, -then the call will run concurrently with other running Haskell threads. -If the program was linked without :ghc-flag:`-threaded`, then the other Haskell -threads will be blocked until the call returns. +``safe`` (the default) in a single-threaded runtime (the program was linked +without using :ghc-flag:`-threaded`), then other Haskell threads will be blocked +until the call returns. + +In the multi-threaded runtime (the program was linked using :ghc-flag:`-threaded`), +``foreign import``\ ed functions run concurrently (both ``safe`` and ``unsafe``), +but a similar effect can happen when you call an ``unsafe`` function, and a global +garbage collection is triggered in another thread. In this situation, the garbage +collector cannot proceed, and this can lead to performance issues that often +appear under high load, as other threads are more active and thus more prone +to trigger global garbage collection. This means that if you need to make a foreign call to a function that -takes a long time or blocks indefinitely, then you should mark it +takes a long time or potentially blocks, then you should mark it ``safe`` and use :ghc-flag:`-threaded`. Some library functions make such calls internally; their documentation should indicate when this is the case. +On the other hand, a foreign call to a function that is guaranteed to take a short +time, and does not call back into Haskell can be marked ``unsafe``. This works +both for the single-threaded and the multi-threaded runtime. When considering +what "a short time" is, a foreign function that does comparable work to what +Haskell code does between each heap allocation (not very much), is a good +candidate. + +Outside these two clear cases for ``safe`` and ``unsafe`` foreign functions, +there is a trade-off between whole-program throughput and efficiency of the +individual foreign function call. + If you are making foreign calls from multiple Haskell threads and using :ghc-flag:`-threaded`, make sure that the foreign code you are calling is thread-safe. In particularly, some GUI libraries are not thread-safe and |