Skip to content

Commit 808cec8

Browse files
committed
Perform memory measurement on SIGUSR1
1 parent 1a34357 commit 808cec8

File tree

3 files changed

+43
-25
lines changed

3 files changed

+43
-25
lines changed

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,7 @@ shakeOpen getLspId eventer withProgress withIndefiniteProgress clientCapabilitie
406406
let ideState = IdeState{..}
407407

408408
IdeOptions{ optOTMemoryProfiling = IdeOTMemoryProfiling otProfilingEnabled } <- getIdeOptionsIO shakeExtras
409-
when otProfilingEnabled $
410-
startTelemetry logger $ state shakeExtras
409+
startTelemetry otProfilingEnabled logger $ state shakeExtras
411410

412411
return ideState
413412
where

ghcide/src/Development/IDE/Core/Tracing.hs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Control.Concurrent.Extra (Var, modifyVar_, newVar,
1313
readVar, threadDelay)
1414
import Control.Exception (evaluate)
1515
import Control.Exception.Safe (catch, SomeException)
16-
import Control.Monad (unless, forM_, forever, (>=>))
16+
import Control.Monad (void, when, unless, forM_, forever, (>=>))
1717
import Control.Monad.Extra (whenJust)
1818
import Control.Seq (r0, seqList, seqTuple2, using)
1919
import Data.Dynamic (Dynamic)
@@ -28,12 +28,13 @@ import Development.IDE.Core.RuleTypes (GhcSession (GhcSession),
2828
import Development.IDE.Types.Logger (logInfo, Logger, logDebug)
2929
import Development.IDE.Types.Shake (Key (..), Value, Values)
3030
import Development.Shake (Action, actionBracket, liftIO)
31+
import Ide.PluginUtils (installSigUsr1Handler)
3132
import Foreign.Storable (Storable (sizeOf))
3233
import HeapSize (recursiveSize, runHeapsize)
3334
import Language.Haskell.LSP.Types (NormalizedFilePath,
3435
fromNormalizedFilePath)
3536
import Numeric.Natural (Natural)
36-
import OpenTelemetry.Eventlog (addEvent, beginSpan, endSpan,
37+
import OpenTelemetry.Eventlog (Synchronicity(Asynchronous), Instrument, addEvent, beginSpan, endSpan,
3738
mkValueObserver, observe,
3839
setTag, withSpan, withSpan_)
3940

@@ -71,35 +72,45 @@ otTracedAction key file success act = actionBracket
7172
unless (success res) $ setTag sp "error" "1"
7273
return res)
7374

74-
startTelemetry :: Logger -> Var Values -> IO ()
75-
startTelemetry logger stateRef = do
75+
startTelemetry :: Bool -> Logger -> Var Values -> IO ()
76+
startTelemetry allTheTime logger stateRef = do
7677
instrumentFor <- getInstrumentCached
7778
mapCountInstrument <- mkValueObserver "values map count"
7879

79-
_ <- regularly (1 * seconds) $
80-
withSpan_ "Measure length" $
81-
readVar stateRef
82-
>>= observe mapCountInstrument . length
83-
84-
_ <- regularly (1 * seconds) $ do
85-
values <- readVar stateRef
86-
let keys = nub
87-
$ Key GhcSession : Key GhcSessionDeps
88-
: [ k | (_,k) <- HMap.keys values
89-
-- do GhcSessionIO last since it closes over stateRef itself
90-
, k /= Key GhcSessionIO]
91-
++ [Key GhcSessionIO]
92-
!groupedForSharing <- evaluate (keys `using` seqList r0)
93-
measureMemory logger [groupedForSharing] instrumentFor stateRef
94-
`catch` \(e::SomeException) ->
95-
logInfo logger ("MEMORY PROFILING ERROR: " <> fromString (show e))
96-
return ()
80+
installSigUsr1Handler $ do
81+
logInfo logger "SIGUSR1 received: performing memory measurement"
82+
performMeasurement logger stateRef instrumentFor mapCountInstrument
83+
84+
when allTheTime $ void $ regularly (1 * seconds) $
85+
performMeasurement logger stateRef instrumentFor mapCountInstrument
9786
where
9887
seconds = 1000000
9988

10089
regularly :: Int -> IO () -> IO (Async ())
10190
regularly delay act = async $ forever (act >> threadDelay delay)
10291

92+
93+
performMeasurement ::
94+
Logger ->
95+
Var (HMap.HashMap (NormalizedFilePath, Key) (Value Dynamic)) ->
96+
(Maybe Key -> IO OurValueObserver) ->
97+
Instrument 'Asynchronous a m' ->
98+
IO ()
99+
performMeasurement logger stateRef instrumentFor mapCountInstrument = do
100+
withSpan_ "Measure length" $ readVar stateRef >>= observe mapCountInstrument . length
101+
102+
values <- readVar stateRef
103+
let keys = nub
104+
$ Key GhcSession : Key GhcSessionDeps
105+
: [ k | (_,k) <- HMap.keys values
106+
-- do GhcSessionIO last since it closes over stateRef itself
107+
, k /= Key GhcSessionIO]
108+
++ [Key GhcSessionIO]
109+
!groupedForSharing <- evaluate (keys `using` seqList r0)
110+
measureMemory logger [groupedForSharing] instrumentFor stateRef
111+
`catch` \(e::SomeException) ->
112+
logInfo logger ("MEMORY PROFILING ERROR: " <> fromString (show e))
113+
103114
{-# ANN startTelemetry ("HLint: ignore Use nubOrd" :: String) #-}
104115

105116
type OurValueObserver = Int -> IO ()

hls-plugin-api/src/Ide/PluginUtils.hs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module Ide.PluginUtils
1818
fullRange,
1919
mkLspCommand,
2020
mkLspCmdId,
21-
allLspCmdIds,allLspCmdIds')
21+
allLspCmdIds,allLspCmdIds',installSigUsr1Handler)
2222
where
2323

2424

@@ -35,13 +35,15 @@ import Language.Haskell.LSP.Types.Capabilities
3535
#ifdef mingw32_HOST_OS
3636
import qualified System.Win32.Process as P (getCurrentProcessId)
3737
#else
38+
import System.Posix.Signals
3839
import qualified System.Posix.Process as P (getProcessID)
3940
#endif
4041
import qualified Data.Aeson as J
4142
import qualified Data.Default
4243
import qualified Data.Map.Strict as Map
4344
import Ide.Plugin.Config
4445
import qualified Language.Haskell.LSP.Core as LSP
46+
import Control.Monad (void)
4547

4648
-- ---------------------------------------------------------------------
4749

@@ -246,8 +248,14 @@ getPid :: IO T.Text
246248
getPid = T.pack . show <$> getProcessID
247249

248250
getProcessID :: IO Int
251+
installSigUsr1Handler :: IO () -> IO ()
252+
249253
#ifdef mingw32_HOST_OS
250254
getProcessID = fromIntegral <$> P.getCurrentProcessId
255+
installSigUsr1Handler _ = return ()
256+
251257
#else
252258
getProcessID = fromIntegral <$> P.getProcessID
259+
260+
installSigUsr1Handler h = void $ installHandler sigUSR1 (Catch h) Nothing
253261
#endif

0 commit comments

Comments
 (0)