@@ -13,7 +13,7 @@ import Control.Concurrent.Extra (Var, modifyVar_, newVar,
13
13
readVar , threadDelay )
14
14
import Control.Exception (evaluate )
15
15
import Control.Exception.Safe (catch , SomeException )
16
- import Control.Monad (unless , forM_ , forever , (>=>) )
16
+ import Control.Monad (void , when , unless , forM_ , forever , (>=>) )
17
17
import Control.Monad.Extra (whenJust )
18
18
import Control.Seq (r0 , seqList , seqTuple2 , using )
19
19
import Data.Dynamic (Dynamic )
@@ -28,12 +28,13 @@ import Development.IDE.Core.RuleTypes (GhcSession (GhcSession),
28
28
import Development.IDE.Types.Logger (logInfo , Logger , logDebug )
29
29
import Development.IDE.Types.Shake (Key (.. ), Value , Values )
30
30
import Development.Shake (Action , actionBracket , liftIO )
31
+ import Ide.PluginUtils (installSigUsr1Handler )
31
32
import Foreign.Storable (Storable (sizeOf ))
32
33
import HeapSize (recursiveSize , runHeapsize )
33
34
import Language.Haskell.LSP.Types (NormalizedFilePath ,
34
35
fromNormalizedFilePath )
35
36
import Numeric.Natural (Natural )
36
- import OpenTelemetry.Eventlog (addEvent , beginSpan , endSpan ,
37
+ import OpenTelemetry.Eventlog (Synchronicity ( Asynchronous ), Instrument , addEvent , beginSpan , endSpan ,
37
38
mkValueObserver , observe ,
38
39
setTag , withSpan , withSpan_ )
39
40
@@ -71,35 +72,45 @@ otTracedAction key file success act = actionBracket
71
72
unless (success res) $ setTag sp " error" " 1"
72
73
return res)
73
74
74
- startTelemetry :: Logger -> Var Values -> IO ()
75
- startTelemetry logger stateRef = do
75
+ startTelemetry :: Bool -> Logger -> Var Values -> IO ()
76
+ startTelemetry allTheTime logger stateRef = do
76
77
instrumentFor <- getInstrumentCached
77
78
mapCountInstrument <- mkValueObserver " values map count"
78
79
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
97
86
where
98
87
seconds = 1000000
99
88
100
89
regularly :: Int -> IO () -> IO (Async () )
101
90
regularly delay act = async $ forever (act >> threadDelay delay)
102
91
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
+
103
114
{-# ANN startTelemetry ("HLint: ignore Use nubOrd" :: String) #-}
104
115
105
116
type OurValueObserver = Int -> IO ()
0 commit comments