Skip to content

Commit f9e1023

Browse files
committed
prefer restart than other actions in shakeControlQueu
1 parent 1fd46bf commit f9e1023

File tree

7 files changed

+384
-34
lines changed

7 files changed

+384
-34
lines changed

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

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module Development.IDE.Core.Shake(
2727
KnownTargets(..), Target(..), toKnownFiles, unionKnownTargets, mkKnownTargets,
2828
ShakeRestartArgs(..),
2929
shakeRestart,
30-
IdeRule, IdeResult, RestartQueue,
30+
IdeRule, IdeResult, ShakeControlQueue,
3131
GetModificationTime(GetModificationTime, GetModificationTime_, missingFileDiagnostics),
3232
shakeOpen, shakeShut,
3333
shakeEnqueue,
@@ -78,7 +78,7 @@ module Development.IDE.Core.Shake(
7878
Log(..),
7979
VFSModified(..), getClientConfigAction,
8080
ThreadQueue(..),
81-
runWithSignal, runRestartTask, runRestartTaskDync, dynShakeRestart
81+
runWithSignal, runRestartTask, runRestartTaskDyn, dynShakeRestart
8282
) where
8383

8484
import Control.Concurrent.Async
@@ -289,16 +289,16 @@ data HieDbWriter
289289
-- The inner `(HieDb -> IO ()) -> IO ()` wraps `HieDb -> IO ()`
290290
-- with (currently) retry functionality
291291
type IndexQueue = TaskQueue (((HieDb -> IO ()) -> IO ()) -> IO ())
292-
-- type RestartQueue = TaskQueue ShakeRestartArgs
292+
-- type ShakeControlQueue = TaskQueue ShakeRestartArgs
293293
type ShakeQueue = DBQue
294-
type RestartQueue = ShakeQueue
294+
type ShakeControlQueue = ShakeQueue
295295
type LoaderQueue = TaskQueue (IO ())
296296

297297

298298
data ThreadQueue = ThreadQueue {
299-
tIndexQueue :: IndexQueue
300-
, tRestartQueue :: RestartQueue
301-
, tLoaderQueue :: LoaderQueue
299+
tIndexQueue :: IndexQueue
300+
, tShakeControlQueue :: ShakeControlQueue
301+
, tLoaderQueue :: LoaderQueue
302302
}
303303

304304
-- Note [Semantic Tokens Cache Location]
@@ -369,7 +369,7 @@ data ShakeExtras = ShakeExtras
369369
-- ^ Default HLS config, only relevant if the client does not provide any Config
370370
, dirtyKeys :: TVar KeySet
371371
-- ^ Set of dirty rule keys since the last Shake run
372-
, restartQueue :: RestartQueue
372+
, shakeControlQueue :: ShakeControlQueue
373373
-- ^ Queue of restart actions to be run.
374374
, loaderQueue :: LoaderQueue
375375
-- ^ Queue of loader actions to be run.
@@ -707,7 +707,7 @@ shakeOpen recorder lspEnv defaultConfig idePlugins debouncer
707707
withHieDb threadQueue opts argMonitoring rules rootDir = mdo
708708
-- see Note [Serializing runs in separate thread]
709709
let indexQueue = tIndexQueue threadQueue
710-
restartQueue = tRestartQueue threadQueue
710+
shakeControlQueue = tShakeControlQueue threadQueue
711711
loaderQueue = tLoaderQueue threadQueue
712712

713713
ideNc <- initNameCache 'r' knownKeyNames
@@ -720,7 +720,7 @@ shakeOpen recorder lspEnv defaultConfig idePlugins debouncer
720720
semanticTokensCache <- STM.newIO
721721
positionMapping <- STM.newIO
722722
knownTargetsVar <- newTVarIO $ hashed emptyKnownTargets
723-
let restartShakeSession = shakeRestart restartQueue
723+
let restartShakeSession = shakeRestart shakeControlQueue
724724
persistentKeys <- newTVarIO mempty
725725
indexPending <- newTVarIO HMap.empty
726726
indexCompleted <- newTVarIO 0
@@ -751,7 +751,7 @@ shakeOpen recorder lspEnv defaultConfig idePlugins debouncer
751751
pure ShakeExtras{shakeRecorder = recorder, ..}
752752
shakeDb <-
753753
shakeNewDatabase
754-
restartQueue
754+
shakeControlQueue
755755
opts { shakeExtra = newShakeExtra shakeExtras }
756756
rules
757757
shakeSession <- newEmptyMVar
@@ -855,13 +855,13 @@ delayedAction a = do
855855

856856

857857
data ShakeRestartArgs = ShakeRestartArgs
858-
{ sraVfs :: !VFSModified
859-
, sraReason :: !String
860-
, sraActions :: ![DelayedAction ()]
861-
, sraBetweenSessions :: IO [Key]
862-
, sraReStartQueue :: !RestartQueue
863-
, sraCount :: !Int
864-
, sraWaitMVars :: ![MVar ()]
858+
{ sraVfs :: !VFSModified
859+
, sraReason :: !String
860+
, sraActions :: ![DelayedAction ()]
861+
, sraBetweenSessions :: IO [Key]
862+
, sraShakeControlQueue :: !ShakeControlQueue
863+
, sraCount :: !Int
864+
, sraWaitMVars :: ![MVar ()]
865865
-- ^ Just for debugging, how many restarts have been requested so far
866866
}
867867

@@ -878,18 +878,20 @@ instance Semigroup ShakeRestartArgs where
878878
, sraReason = sraReason a ++ "; " ++ sraReason b
879879
, sraActions = sraActions a ++ sraActions b
880880
, sraBetweenSessions = (++) <$> sraBetweenSessions a <*> sraBetweenSessions b
881-
, sraReStartQueue = sraReStartQueue a
881+
, sraShakeControlQueue = sraShakeControlQueue a
882882
, sraCount = sraCount a + sraCount b
883883
, sraWaitMVars = sraWaitMVars a ++ sraWaitMVars b
884884
}
885885

886886
-- | Restart the current 'ShakeSession' with the given system actions.
887887
-- Any actions running in the current session will be aborted,
888888
-- but actions added via 'shakeEnqueue' will be requeued.
889-
shakeRestart :: RestartQueue -> VFSModified -> String -> [DelayedAction ()] -> IO [Key] -> IO ()
889+
shakeRestart :: ShakeControlQueue -> VFSModified -> String -> [DelayedAction ()] -> IO [Key] -> IO ()
890890
shakeRestart rts vfs reason acts ioActionBetweenShakeSession = do
891891
waitMVar <- newEmptyMVar
892-
void $ submitWork rts $ Left $
892+
-- submit at the head of the queue,
893+
-- prefer restart request over any pending actions
894+
void $ submitWorkAtHead rts $ Left $
893895
toDyn $ ShakeRestartArgs vfs reason acts ioActionBetweenShakeSession rts 1 [waitMVar]
894896
-- Wait until the restart is done
895897
takeMVar waitMVar
@@ -901,8 +903,8 @@ dynShakeRestart dy = case fromDynamic dy of
901903

902904
-- runRestartTask :: Recorder (WithPriority Log) -> IdeState -> VFSModified -> String -> [DelayedAction ()] -> IO [Key] -> IO ()
903905
-- runRestartTask recorder IdeState{..} vfs reason acts ioActionBetweenShakeSession =
904-
runRestartTaskDync :: Recorder (WithPriority Log) -> MVar IdeState -> Dynamic -> IO ()
905-
runRestartTaskDync recorder ideStateVar dy = runRestartTask recorder ideStateVar (dynShakeRestart dy)
906+
runRestartTaskDyn :: Recorder (WithPriority Log) -> MVar IdeState -> Dynamic -> IO ()
907+
runRestartTaskDyn recorder ideStateVar dy = runRestartTask recorder ideStateVar (dynShakeRestart dy)
906908

907909
runRestartTask :: Recorder (WithPriority Log) -> MVar IdeState -> ShakeRestartArgs -> IO ()
908910
runRestartTask recorder ideStateVar shakeRestartArgs = do
@@ -913,15 +915,15 @@ runRestartTask recorder ideStateVar shakeRestartArgs = do
913915
-- see Note [Housekeeping rule cache and dirty key outside of hls-graph]
914916
atomically $ modifyTVar' (dirtyKeys shakeExtras) $ \x -> foldl' (flip insertKeySet) x keys
915917
-- Check if there is another restart request pending, if so, we run that one too
916-
readAndGo sra sraReStartQueue
917-
readAndGo sra sraReStartQueue = do
918-
nextRestartArg <- atomically $ tryReadTaskQueue sraReStartQueue
918+
readAndGo sra sraShakeControlQueue
919+
readAndGo sra sraShakeControlQueue = do
920+
nextRestartArg <- atomically $ tryReadTaskQueue sraShakeControlQueue
919921
case nextRestartArg of
920922
Nothing -> return sra
921923
Just (Left dy) -> do
922924
res <- prepareRestart $ dynShakeRestart dy
923925
return $ sra <> res
924-
Just (Right _) -> readAndGo sra sraReStartQueue
926+
Just (Right _) -> readAndGo sra sraShakeControlQueue
925927
withMVar'
926928
shakeSession
927929
( \runner -> do

ghcide/src/Development/IDE/LSP/LanguageServer.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ runShakeThread :: Recorder (WithPriority Log) -> MVar IdeState -> ContT () IO DB
357357
runShakeThread recorder mide =
358358
withWorkerQueue
359359
(logWith (cmapWithPrio (LogSession . Session.LogSessionWorkerThread) recorder) Debug)
360-
"ShakeRestartQueue"
361-
(eitherWorker (runRestartTaskDync (cmapWithPrio LogShake recorder) mide) id)
360+
"ShakeShakeControlQueue"
361+
(eitherWorker (runRestartTaskDyn (cmapWithPrio LogShake recorder) mide) id)
362362
-- | runWithWorkerThreads
363363
-- create several threads to run the session, db and session loader
364364
-- see Note [Serializing runs in separate thread]

hlint.eventlog

109 KB
Binary file not shown.

hls-graph/src/Development/IDE/WorkerThread.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ module Development.IDE.WorkerThread
2626
Worker,
2727
tryReadTaskQueue,
2828
awaitRunInThreadAtHead,
29-
withWorkerQueueSimpleRight
29+
withWorkerQueueSimpleRight,
30+
submitWorkAtHead
3031
) where
3132

3233
import Control.Concurrent.Async (Async, async, withAsync)
@@ -157,10 +158,12 @@ eitherWorker w1 w2 = \case
157158

158159
-- submitWork without waiting for the result
159160
submitWork :: TaskQueue arg -> arg -> IO ()
160-
submitWork (TaskQueue q) arg = do
161-
-- Take an action from TQueue, run it and
162-
-- use barrier to wait for the result
163-
atomically $ writeTQueue q arg
161+
submitWork (TaskQueue q) arg = do atomically $ writeTQueue q arg
162+
163+
-- submit work at the head of the queue, so it will be executed next
164+
submitWorkAtHead :: TaskQueue arg -> arg -> IO ()
165+
submitWorkAtHead (TaskQueue q) arg = do
166+
atomically $ unGetTQueue q arg
164167

165168
awaitRunInThread :: TaskQueue (IO ()) -> IO result -> IO result
166169
awaitRunInThread (TaskQueue q) act = do

scripts/eventlog-dump.fish

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env fish
2+
3+
# Dump a GHC RTS .eventlog to a plain-text file using the ghc-events CLI.
4+
# Usage:
5+
# scripts/eventlog-dump.fish <file.eventlog> [output.txt] [contains_substring]
6+
#
7+
# Notes:
8+
# - Attempts to find ghc-events in PATH, ~/.cabal/bin, or ~/.local/bin.
9+
# - If not found, will try: cabal install ghc-events
10+
# - Output defaults to <basename>.events.txt in the current directory.
11+
12+
function usage
13+
echo "Usage: (basename (status filename)) <file.eventlog> [output.txt] [contains_substring]"
14+
exit 2
15+
end
16+
17+
if test (count $argv) -lt 1
18+
usage
19+
end
20+
21+
set evlog $argv[1]
22+
if not test -f $evlog
23+
echo "error: file not found: $evlog" >&2
24+
exit 1
25+
end
26+
27+
if test (count $argv) -ge 2
28+
set out $argv[2]
29+
else
30+
set base (basename $evlog)
31+
if string match -q '*\.eventlog' $base
32+
set out (string replace -r '\\.eventlog$' '.events.txt' -- $base)
33+
else
34+
set out "$base.events.txt"
35+
end
36+
end
37+
38+
# Optional contains filter: only keep lines that contain any of the substrings (pipe-separated)
39+
set filter_contains ""
40+
set filter_contains_list
41+
if test (count $argv) -ge 3
42+
set filter_contains $argv[3]
43+
set filter_contains_list (string split '|' -- $filter_contains)
44+
end
45+
46+
function find_ghc_events --description "echo absolute path to ghc-events or empty"
47+
if command -sq ghc-events
48+
command -s ghc-events
49+
return 0
50+
end
51+
if test -x ~/.cabal/bin/ghc-events
52+
echo ~/.cabal/bin/ghc-events
53+
return 0
54+
end
55+
if test -x ~/.local/bin/ghc-events
56+
echo ~/.local/bin/ghc-events
57+
return 0
58+
end
59+
return 1
60+
end
61+
62+
set ghc_events_bin (find_ghc_events)
63+
64+
if test -z "$ghc_events_bin"
65+
echo "ghc-events not found; attempting to install via 'cabal install ghc-events'..." >&2
66+
if not command -sq cabal
67+
echo "error: cabal not found; please install ghc-events manually (e.g., via cabal)." >&2
68+
exit 1
69+
end
70+
cabal install ghc-events
71+
set ghc_events_bin (find_ghc_events)
72+
if test -z "$ghc_events_bin"
73+
echo "error: ghc-events still not found after installation." >&2
74+
exit 1
75+
end
76+
end
77+
78+
echo "Dumping events from $evlog to $out..."
79+
if test -n "$filter_contains"
80+
$ghc_events_bin show $evlog | while read -l line
81+
set keep 1
82+
if (count $filter_contains_list) -gt 0
83+
set found 0
84+
for substr in $filter_contains_list
85+
if string match -q -- "*$substr*" -- $line
86+
set found 1
87+
break
88+
end
89+
end
90+
if test $found -eq 0
91+
set keep 0
92+
end
93+
end
94+
if test $keep -eq 1
95+
echo $line
96+
end
97+
end > $out
98+
else
99+
$ghc_events_bin show $evlog > $out
100+
end
101+
set exit_code $status
102+
103+
if test $exit_code -ne 0
104+
echo "error: dump failed with exit code $exit_code" >&2
105+
exit $exit_code
106+
end
107+
108+
set -l size ""
109+
if command -sq stat
110+
# macOS stat prints size with -f%z; suppress errors if not supported
111+
set size (stat -f%z $out 2>/dev/null)
112+
end
113+
if test -z "$size"
114+
set size (wc -c < $out)
115+
end
116+
117+
echo "Wrote $out ($size bytes)."

0 commit comments

Comments
 (0)