Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
23d1e81
hls-graph: isolate runtime engine improvements
soulomoon May 6, 2026
b894af1
Isolate hls-graph runtime engine improvements
soulomoon May 6, 2026
bf753af
ghcide: integrate hls-graph runtime engine
soulomoon May 6, 2026
f72ca37
chore: remove accidental eventlog
soulomoon May 6, 2026
8693fde
Confirm reactor shutdown before cleanup
soulomoon May 6, 2026
71e697e
Run LSP shutdown after worker teardown
soulomoon May 6, 2026
49f9304
Fix shutdown warning helper masking
soulomoon May 6, 2026
8f80b9e
chore: update GHC version in benchmark matrix
soulomoon May 6, 2026
eecfa90
chore: remove GHC 9.8 from benchmark matrix
soulomoon May 6, 2026
ed2a709
fix bench 9.12
soulomoon Oct 25, 2025
a11fbe4
update bench config
soulomoon Oct 28, 2025
46d5609
update bench config
soulomoon Oct 29, 2025
0f4ea7b
update bench config
soulomoon Oct 29, 2025
5482d79
update bench CI to 9.12
soulomoon Nov 18, 2025
28a6ddd
refactor: update GHC version handling in benchmark workflow
soulomoon Nov 18, 2025
5a5a837
Enable benchmark CI for GHC 9.14
soulomoon May 6, 2026
8cb6663
Drop benchmark SVG generation
soulomoon May 6, 2026
cd6ee40
refactor: remove unused dependencies for GHC 9.14
soulomoon May 6, 2026
1de9bab
Use Cabal 3.16 for benchmark CI
soulomoon May 6, 2026
abb8a0e
fix: update Cabal version to 3.16 in benchmark workflow
soulomoon May 6, 2026
e9530c2
Update benchmark examples for GHC 9.14
soulomoon May 6, 2026
9786cd7
Fix benchmark target project setup
soulomoon May 7, 2026
399bba3
fix: restore benchmark configurations for MultiLayerModules and Dummy…
soulomoon May 7, 2026
cb69dd8
Merge branch 'master' into fixbench
soulomoon May 7, 2026
04da422
Merge remote-tracking branch 'origin/fixbench' into codex/hls-graph-r…
soulomoon May 7, 2026
2f8a559
fix: hide uninformative benchmark diffs
soulomoon May 7, 2026
1aec4e9
Merge branch 'fixbench' into codex/hls-graph-runtime-engine
soulomoon May 7, 2026
b7e950a
fix: remove threshold for insignificant percentage differences in sho…
soulomoon May 7, 2026
2a71e12
refactor: simplify spawnAsyncWithDbRegistration by removing registerH…
soulomoon May 7, 2026
1bcc1bd
fix: handle unmatched Key cases in fromKey and fromKeyType functions
soulomoon May 7, 2026
6095bcd
fix: correct newDirectKey implementation to avoid key collisions
soulomoon May 7, 2026
027d588
Clarify hls-graph runtime restart keys
soulomoon May 7, 2026
cf73b99
Add no-file rule for global kick action and refactor kick usage
soulomoon Sep 27, 2025
089a781
fix: adjust doKick behavior to always kick during testing
soulomoon Oct 1, 2025
06b68c0
Merge branch 'codex/extract-dokick-optimization' into codex/hls-graph…
soulomoon May 8, 2026
a9739b2
Merge branch 'master' into codex/hls-graph-runtime-engine
soulomoon May 12, 2026
f8a9250
Add typing burst benchmark coverage
soulomoon May 12, 2026
c977429
Merge branch 'master' into codex/hls-graph-runtime-engine
soulomoon May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ jobs:
steps:
- id: set_ghc_versions
run: |
# benching the two latest GHCs we support now
# since benchmark are expansive.
# choosing the two latest are easier to maintain and more forward looking
# see discussion https://github.com/haskell/haskell-language-server/pull/4118
# Benchmarking only the two latest GHCs we support now
# since benchmark are expensive.
# Choosing the two latest is easier to maintain and more forward looking.
Expand Down
1 change: 0 additions & 1 deletion cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ constraints:
allow-newer:
cabal-install-parsers:Cabal-syntax,


if impl(ghc >= 9.13)
allow-newer:
cabal-install-parsers:base,
Expand Down
23 changes: 22 additions & 1 deletion ghcide-bench/src/Experiments.hs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,28 @@ examplesPath :: FilePath
examplesPath = "bench/example"

defConfig :: Config
Success defConfig = execParserPure defaultPrefs (info configP fullDesc) []
defConfig = Config
{ verbosity = Normal
, shakeProfiling = Nothing
, otMemoryProfiling = Nothing
, outputCSV = "results.csv"
, buildTool = Cabal
, ghcideOptions = []
, matches = []
, repetitions = Nothing
, ghcide = "ghcide"
, timeoutLsp = 60
, example = Example
{ exampleName = "Cabal"
, exampleDetails = ExampleHackage ExamplePackage
{ packageName = "Cabal"
, packageVersion = makeVersion [3,16,1,0]
}
, exampleModules = ["src/Distribution/Simple.hs"]
, exampleExtraArgs = []
}
, lspConfig = False
}

quiet, verbose :: Config -> Bool
verbose = (== All) . verbosity
Expand Down
3 changes: 2 additions & 1 deletion ghcide/session-loader/Development/IDE/Session.hs
Original file line number Diff line number Diff line change
Expand Up @@ -905,14 +905,15 @@ session recorder sessionShake sessionState knownTargetsVar(hieYaml, cfp, opts, l
-- Typecheck all files in the project on startup
unless (null new_components_info || not checkProject) $ do
cfps' <- liftIO $ filterM (IO.doesFileExist . fromNormalizedFilePath) (concatMap targetLocations all_targets)
void $ enqueueActions sessionShake $ mkDelayedAction "InitialLoad" Debug $ void $ do
initialLoad <- mkDelayedAction "InitialLoad" Debug $ void $ do
mmt <- uses GetModificationTime cfps'
let cs_exist = catMaybes (zipWith (<$) cfps' mmt)
modIfaces <- uses GetModIface cs_exist
-- update exports map
shakeExtras <- getShakeExtras
let !exportsMap' = createExportsMap $ mapMaybe (fmap hirModIface) modIfaces
liftIO $ atomically $ modifyTVar' (exportsMap shakeExtras) (exportsMap' <>)
void $ enqueueActions sessionShake initialLoad
return [keys1, keys2]

-- | Create a new HscEnv from a hieYaml root and a set of options
Expand Down
5 changes: 3 additions & 2 deletions ghcide/src/Development/IDE/Core/FileStore.hs
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,9 @@ setFileModified recorder vfs state saved nfp actionBefore = do
typecheckParents recorder state nfp

typecheckParents :: Recorder (WithPriority Log) -> IdeState -> NormalizedFilePath -> IO ()
typecheckParents recorder state nfp = void $ shakeEnqueue (shakeExtras state) parents
where parents = mkDelayedAction "ParentTC" L.Debug (typecheckParentsAction recorder nfp)
typecheckParents recorder state nfp = do
parents <- mkDelayedAction "ParentTC" L.Debug (typecheckParentsAction recorder nfp)
void $ shakeEnqueue (shakeExtras state) parents

typecheckParentsAction :: Recorder (WithPriority Log) -> NormalizedFilePath -> Action ()
typecheckParentsAction recorder nfp = do
Expand Down
21 changes: 17 additions & 4 deletions ghcide/src/Development/IDE/Core/OfInterest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Development.IDE.Core.OfInterest(
kick, FileOfInterestStatus(..),
OfInterestVar(..),
scheduleGarbageCollection,
Log(..)
Log(..), doKick
) where

import Control.Concurrent.Strict
Expand All @@ -39,7 +39,7 @@ import Development.IDE.Plugin.Completions.Types
import Development.IDE.Types.Exports
import Development.IDE.Types.Location
import Development.IDE.Types.Options (IdeTesting (..))
import Development.IDE.Types.Shake (toKey)
import Development.IDE.Types.Shake (toKey, toNoFileKey)
import GHC.TypeLits (KnownSymbol)
import Ide.Logger (Pretty (pretty),
Priority (..),
Expand All @@ -66,6 +66,10 @@ ofInterestRules :: Recorder (WithPriority Log) -> Rules ()
ofInterestRules recorder = do
addIdeGlobal . OfInterestVar =<< liftIO (newVar HashMap.empty)
addIdeGlobal . GarbageCollectVar =<< liftIO (newVar False)
-- A no-file rule to perform the global kick action
defineEarlyCutOffNoFile (cmapWithPrio LogShake recorder) $ \Kick -> do
kick
pure ("", ())
defineEarlyCutoff (cmapWithPrio LogShake recorder) $ RuleNoDiagnostics $ \IsFileOfInterest f -> do
alwaysRerun
filesOfInterest <- getFilesOfInterestUntracked
Expand Down Expand Up @@ -113,7 +117,7 @@ addFileOfInterest state f v = do
then do
logWith (ideLogger state) Debug $
LogSetFilesOfInterest (HashMap.toList files)
return [toKey IsFileOfInterest f]
return [toKey IsFileOfInterest f, toNoFileKey Kick]
else return []

deleteFileOfInterest :: IdeState -> NormalizedFilePath -> IO [Key]
Expand All @@ -122,12 +126,21 @@ deleteFileOfInterest state f = do
files <- modifyVar' var $ HashMap.delete f
logWith (ideLogger state) Debug $
LogSetFilesOfInterest (HashMap.toList files)
return [toKey IsFileOfInterest f]
return [toKey IsFileOfInterest f, toNoFileKey Kick]
scheduleGarbageCollection :: IdeState -> IO ()
scheduleGarbageCollection state = do
GarbageCollectVar var <- getIdeGlobalState state
writeVar var True

doKick :: Action ()
doKick = do
ShakeExtras{ideTesting = IdeTesting testing} <- getShakeExtras
-- only kick always if testing, otherwise we rely on the kick rule
if testing
then kick
else void $ useNoFile Kick


-- | Typecheck all the files of interest.
-- Could be improved
kick :: Action ()
Expand Down
10 changes: 6 additions & 4 deletions ghcide/src/Development/IDE/Core/PluginUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ import qualified StmContainers.Map as STM
-- |ExceptT version of `runAction`, takes a ExceptT Action
runActionE :: MonadIO m => String -> IdeState -> ExceptT e Action a -> ExceptT e m a
runActionE herald ide act =
mapExceptT liftIO . ExceptT $
join $ shakeEnqueue (shakeExtras ide) (mkDelayedAction herald Logger.Debug $ runExceptT act)
mapExceptT liftIO . ExceptT $ do
delayed <- mkDelayedAction herald Logger.Debug $ runExceptT act
join $ shakeEnqueue (shakeExtras ide) delayed

-- |MaybeT version of `runAction`, takes a MaybeT Action
runActionMT :: MonadIO m => String -> IdeState -> MaybeT Action a -> MaybeT m a
runActionMT herald ide act =
mapMaybeT liftIO . MaybeT $
join $ shakeEnqueue (shakeExtras ide) (mkDelayedAction herald Logger.Debug $ runMaybeT act)
mapMaybeT liftIO . MaybeT $ do
delayed <- mkDelayedAction herald Logger.Debug $ runMaybeT act
join $ shakeEnqueue (shakeExtras ide) delayed

-- |ExceptT version of `use` that throws a PluginRuleFailed upon failure
useE :: IdeRule k v => k -> NormalizedFilePath -> ExceptT PluginError Action v
Expand Down
8 changes: 8 additions & 0 deletions ghcide/src/Development/IDE/Core/RuleTypes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,14 @@ data IsFileOfInterest = IsFileOfInterest
instance Hashable IsFileOfInterest
instance NFData IsFileOfInterest

-- | A no-file rule that triggers the IDE "kick" action
data Kick = Kick
deriving (Eq, Show, Generic)
instance Hashable Kick
instance NFData Kick

type instance RuleResult Kick = ()

data GetModSummaryWithoutTimestamps = GetModSummaryWithoutTimestamps
deriving (Eq, Show, Generic)
instance Hashable GetModSummaryWithoutTimestamps
Expand Down
5 changes: 3 additions & 2 deletions ghcide/src/Development/IDE/Core/Service.hs
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,6 @@ shutdown = shakeShut
-- available. There might still be other rules running at this point,
-- e.g., the ofInterestRule.
runAction :: String -> IdeState -> Action a -> IO a
runAction herald ide act =
join $ shakeEnqueue (shakeExtras ide) (mkDelayedAction herald Logger.Debug act)
runAction herald ide act = do
delayed <- mkDelayedAction herald Logger.Debug act
join $ shakeEnqueue (shakeExtras ide) delayed
Loading
Loading