Skip to content

Commit 15c312d

Browse files
committed
Only integrate known target in the cache once
1 parent 5dd978e commit 15c312d

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

ghcide/session-loader/Development/IDE/Session.hs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ import Control.Applicative (Alternative ((<|>)))
9191
import Data.Void
9292

9393
import Control.Concurrent.STM.Stats (atomically, modifyTVar',
94-
readTVar, writeTVar)
94+
readTVar, writeTVar, readTVarIO)
9595
import Control.Concurrent.STM.TQueue
9696
import Control.DeepSeq
9797
import Control.Exception (evaluate)
@@ -124,6 +124,7 @@ import GHC.Driver.Errors.Types
124124
import GHC.Types.Error (errMsgDiagnostic,
125125
singleMessage)
126126
import GHC.Unit.State
127+
import Development.IDE (HscEnvEq(..))
127128

128129
#if MIN_VERSION_ghc(9,13,0)
129130
import GHC.Driver.Make (checkHomeUnitsClosed)
@@ -443,7 +444,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
443444

444445
return $ do
445446
clientConfig <- getClientConfigAction
446-
extras@ShakeExtras{restartShakeSession, ideNc, knownTargetsVar, lspEnv
447+
extras@ShakeExtras{restartShakeSession, ideNc, knownTargetsVar, lspEnv, moduleToPathCache
447448
} <- getShakeExtras
448449
let invalidateShakeCache = do
449450
void $ modifyVar' version succ
@@ -490,6 +491,22 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} rootDir que = do
490491
pure hasUpdate
491492
for_ hasUpdate $ \x ->
492493
logWith recorder Debug $ LogKnownFilesUpdated (targetMap x)
494+
495+
496+
-- Clean the module map cache
497+
-- TODO: the clean is total: it refresh the complete module to
498+
-- filename cache. We can imagine something smarter in the future,
499+
-- but anyway, the scan is actually really fast (It lists recursively
500+
-- the content of all your include path, but once. It could only be
501+
-- as slow as the number of files in your include paths, which is,
502+
-- most of the time, the same as the number of module in your
503+
-- project. If there are a lot of not required files inside your
504+
-- include path, this will be an issue) and right now
505+
-- what's expensive is the association of Known target to module,
506+
-- which is still fast considering that it does not do any IO.
507+
atomically $ do
508+
writeTVar moduleToPathCache mempty
509+
493510
return $ toNoFileKey GetKnownTargets
494511

495512
-- Create a new HscEnv from a hieYaml root and a set of options

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ getLocatedImportsRule recorder =
330330
let dflags = hsc_dflags env
331331
opt <- getIdeOptions
332332

333-
moduleMaps <- extendModuleMapWithKnownTargets file
333+
moduleMaps <- use_ GetModulesPaths file
334334

335335
(diags, imports') <- fmap unzip $ forM imports $ \(isSource, (mbPkgName, modName)) -> do
336336

@@ -661,23 +661,29 @@ getModulesPathsRule recorder = defineEarlyCutoff (cmapWithPrio LogShake recorder
661661
pure (fmap (u,) $ mconcat a, fmap (u, ) $ mconcat b)
662662

663663
let res = (mconcat a, mconcat b)
664-
liftIO $ atomically $ modifyTVar' moduleToPathCache (Map.insert (envUnique env_eq) res)
664+
-- Extend the current module map with all the known targets
665+
resExtended <- extendModuleMapWithKnownTargets file res
666+
667+
liftIO $ atomically $ modifyTVar' moduleToPathCache (Map.insert (envUnique env_eq) resExtended)
668+
669+
pure (mempty, ([], Just resExtended))
665670

666-
pure (mempty, ([], Just res))
667671

668672
-- | Extend the map from module name to filepath (exiting on the drive) with
669673
-- the list of known targets provided by HLS
670674
--
671675
-- These known targets are files which were recently created and not yet saved
672676
-- to the filesystem.
673677
--
674-
-- TODO: for now the implementation is O(number_of_known_files *
675-
-- number_of_include_path) which is inacceptable and should be addressed.
678+
-- This code is not really efficient (O(import_dirs * known_targets)), which
679+
-- can quickly represents millions of tests. It could be improved, but
680+
-- everything only happen once everytime known_targets is updated (which only
681+
-- happen when the project start or when a file is added) and the code is not
682+
-- doing any IO.
676683
extendModuleMapWithKnownTargets
677-
:: NormalizedFilePath
678-
-> Action (Map.Map ModuleName (UnitId, NormalizedFilePath), Map.Map ModuleName (UnitId, NormalizedFilePath))
679-
extendModuleMapWithKnownTargets file = do
680-
(notSourceModules, sourceModules) <- use_ GetModulesPaths file
684+
:: NormalizedFilePath -> (Map.Map ModuleName (UnitId, NormalizedFilePath), Map.Map ModuleName (UnitId, NormalizedFilePath)) ->
685+
Action (Map.Map ModuleName (UnitId, NormalizedFilePath), Map.Map ModuleName (UnitId, NormalizedFilePath))
686+
extendModuleMapWithKnownTargets file (notSourceModules, sourceModules) = do
681687
KnownTargets targetsMap <- useNoFile_ GetKnownTargets
682688

683689
env_eq <- use_ GhcSession file
@@ -717,7 +723,6 @@ extendModuleMapWithKnownTargets file = do
717723
else
718724
pure (Just (modName, (u, path)), Nothing)
719725

720-
721726
pure $ (Map.fromList a <> notSourceModules, Map.fromList b <> sourceModules)
722727

723728

0 commit comments

Comments
 (0)