Skip to content

Commit

Permalink
Add separate cache for getPkgConfigDb
Browse files Browse the repository at this point in the history
Querying pkg-config for the version of every module can be a very
expensive operation on some systems. This change adds a separate,
per-project, cache for PkgConfigDB; reducing the cost from "every plan
change" to "every pkg-config-db change per project".

The cache key is composed by the pkg-config configured program and the
list of directories reported by pkg-config's pc_path variable.

A notice is presented to the user when refreshing the PkgConfigDB.
  • Loading branch information
andreabedini committed Nov 21, 2023
1 parent c97092f commit 03e8346
Show file tree
Hide file tree
Showing 148 changed files with 265 additions and 48 deletions.
22 changes: 22 additions & 0 deletions cabal-install/src/Distribution/Client/ProjectConfig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module Distribution.Client.ProjectConfig
, resolveSolverSettings
, BuildTimeSettings (..)
, resolveBuildTimeSettings
, resolveProgramDb

-- * Checking configuration
, checkBadPerPackageCompilerPaths
Expand Down Expand Up @@ -154,6 +155,14 @@ import Distribution.Simple.InstallDirs
)
import Distribution.Simple.Program
( ConfiguredProgram (..)
, ProgramSearchPathEntry (..)
)
import Distribution.Simple.Program.Db
( ProgramDb
, defaultProgramDb
, modifyProgramSearchPath
, userSpecifyArgss
, userSpecifyPaths
)
import Distribution.Simple.Setup
( Flag (Flag)
Expand Down Expand Up @@ -496,6 +505,19 @@ resolveBuildTimeSettings
| isParallelBuild buildSettingNumJobs = False
| otherwise = False

-- | ProgramDb with directly user specified paths
resolveProgramDb :: ProjectConfig -> ProgramDb
resolveProgramDb ProjectConfig{projectConfigLocalPackages = PackageConfig{..}} =
userSpecifyPaths (Map.toList (getMapLast packageConfigProgramPaths))
. userSpecifyArgss (Map.toList (getMapMappend packageConfigProgramArgs))
. modifyProgramSearchPath
( ++
[ ProgramSearchPathDir dir
| dir <- fromNubList packageConfigProgramPathExtra
]
)
$ defaultProgramDb

---------------------------------------------
-- Reading and writing project config files
--
Expand Down
76 changes: 31 additions & 45 deletions cabal-install/src/Distribution/Client/ProjectPlanning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ configureCompiler
DistDirLayout
{ distProjectCacheFile
}
ProjectConfig
projectConfig@ProjectConfig
{ projectConfigShared =
ProjectConfigShared
{ projectConfigHcFlavor
Expand Down Expand Up @@ -531,15 +531,7 @@ configureCompiler
hcFlavor = flagToMaybe projectConfigHcFlavor
hcPath = flagToMaybe projectConfigHcPath
hcPkg = flagToMaybe projectConfigHcPkg
progdb =
userSpecifyPaths (Map.toList (getMapLast packageConfigProgramPaths))
. modifyProgramSearchPath
( [ ProgramSearchPathDir dir
| dir <- fromNubList packageConfigProgramPathExtra
]
++
)
$ defaultProgramDb
progdb = resolveProgramDb projectConfig

------------------------------------------------------------------------------

Expand Down Expand Up @@ -588,6 +580,9 @@ rebuildInstallPlan
progsearchpath <- liftIO $ getSystemSearchPath
let projectConfigMonitored = projectConfig{projectConfigBuildOnly = mempty}

let progdb = resolveProgramDb projectConfig
pkgConfigDB <- getPkgConfigDb verbosity distDirLayout progdb

-- The overall improved plan is cached
rerunIfChanged
verbosity
Expand All @@ -607,11 +602,12 @@ rebuildInstallPlan
)
$ do
compilerEtc <- phaseConfigureCompiler projectConfig
_ <- phaseConfigurePrograms projectConfig compilerEtc
(solverPlan, pkgConfigDB, totalIndexState, activeRepos) <-

(solverPlan, totalIndexState, activeRepos) <-
phaseRunSolver
projectConfig
compilerEtc
pkgConfigDB
localPackages
(fromMaybe mempty mbInstalledPackages)
( elaboratedPlan
Expand Down Expand Up @@ -650,55 +646,37 @@ rebuildInstallPlan
phaseConfigureCompiler
:: ProjectConfig
-> Rebuild (Compiler, Platform, ProgramDb)
phaseConfigureCompiler = configureCompiler verbosity distDirLayout
phaseConfigureCompiler projectConfig = do
(compiler, platform, progdb) <- configureCompiler verbosity distDirLayout projectConfig

-- Configuring other programs.
--
-- Having configred the compiler, now we configure all the remaining
-- programs. This is to check we can find them, and to monitor them for
-- changes.
--
-- TODO: [required eventually] we don't actually do this yet.
--
-- We rely on the fact that the previous phase added the program config for
-- all local packages, but that all the programs configured so far are the
-- compiler program or related util programs.
--
phaseConfigurePrograms
:: ProjectConfig
-> (Compiler, Platform, ProgramDb)
-> Rebuild ()
phaseConfigurePrograms projectConfig (_, _, compilerprogdb) = do
-- Users are allowed to specify program locations independently for
-- each package (e.g. to use a particular version of a pre-processor
-- for some packages). However they cannot do this for the compiler
-- itself as that's just not going to work. So we check for this.
liftIO $
checkBadPerPackageCompilerPaths
(configuredPrograms compilerprogdb)
(configuredPrograms progdb)
(getMapMappend (projectConfigSpecificPackage projectConfig))

-- TODO: [required eventually] find/configure other programs that the
-- user specifies.

-- TODO: [required eventually] find/configure all build-tools
-- but note that some of them may be built as part of the plan.
return (compiler, platform, progdb)

-- Run the solver to get the initial install plan.
-- This is expensive so we cache it independently.
--
phaseRunSolver
:: ProjectConfig
-> (Compiler, Platform, ProgramDb)
-> PkgConfigDb
-> [PackageSpecifier UnresolvedSourcePackage]
-> InstalledPackageIndex
-> Rebuild (SolverInstallPlan, PkgConfigDb, IndexUtils.TotalIndexState, IndexUtils.ActiveRepos)
-> Rebuild (SolverInstallPlan, IndexUtils.TotalIndexState, IndexUtils.ActiveRepos)
phaseRunSolver
projectConfig@ProjectConfig
{ projectConfigShared
, projectConfigBuildOnly
}
(compiler, platform, progdb)
pkgConfigDB
localPackages
installedPackages =
rerunIfChanged
Expand All @@ -719,13 +697,13 @@ rebuildInstallPlan
progdb
platform
corePackageDbs

(sourcePkgDb, tis, ar) <-
getSourcePackages
verbosity
withRepoCtx
(solverSettingIndexState solverSettings)
(solverSettingActiveRepos solverSettings)
pkgConfigDB <- getPkgConfigDb verbosity progdb

-- TODO: [code cleanup] it'd be better if the Compiler contained the
-- ConfiguredPrograms that it needs, rather than relying on the progdb
Expand All @@ -750,7 +728,7 @@ rebuildInstallPlan
Left msg -> do
reportPlanningFailure projectConfig compiler platform localPackages
dieWithException verbosity $ PhaseRunSolverErr msg
Right plan -> return (plan, pkgConfigDB, tis, ar)
Right plan -> return (plan, tis, ar)
where
corePackageDbs :: [PackageDB]
corePackageDbs =
Expand Down Expand Up @@ -1036,13 +1014,21 @@ getSourcePackages verbosity withRepoCtx idxState activeRepos = do
$ repos
return sourcePkgDbWithTIS

getPkgConfigDb :: Verbosity -> ProgramDb -> Rebuild PkgConfigDb
getPkgConfigDb verbosity progdb = do
getPkgConfigDb :: Verbosity -> DistDirLayout -> ProgramDb -> Rebuild PkgConfigDb
getPkgConfigDb verbosity distDirLayout progdb = do
-- We find the pkg-config program and we ask it for the location of the pc files.
-- We then use these two values for the cache key
mpkgConfig <- liftIO $ needProgram verbosity pkgConfigProgram progdb
let mpkgConfigLoc = fst <$> mpkgConfig
dirs <- liftIO $ getPkgConfigDbDirs verbosity progdb
-- Just monitor the dirs so we'll notice new .pc files.
-- Alternatively we could monitor all the .pc files too.
traverse_ monitorDirectoryStatus dirs
liftIO $ readPkgConfigDb verbosity progdb
rerunIfChanged verbosity fileMonitorPkgConfigDb (mpkgConfigLoc, dirs) $ do
liftIO $ notice verbosity "Querying pkg-config database..."
-- Just monitor the dirs so we'll notice new .pc files.
-- Alternatively we could monitor all the .pc files too.
traverse_ monitorDirectoryStatus dirs
liftIO $ readPkgConfigDb verbosity progdb
where
fileMonitorPkgConfigDb = newFileMonitor $ distProjectCacheFile distDirLayout "pkg-config-db"

-- | Select the config values to monitor for changes package source hashes.
packageLocationsSignature
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand All @@ -18,8 +19,7 @@ Configuring library 'indef' instantiated with
Data.Map = containers-<VERSION>:Data.Map
for Includes3-0.1.0.0...
Preprocessing library 'indef' for Includes3-0.1.0.0...
Building library 'indef' instantiated with
Data.Map = containers-<VERSION>:Data.Map
Building library 'indef' instantiated with Data.Map = containers-<VERSION>:Data.Map
for Includes3-0.1.0.0...
Configuring executable 'exe' for Includes3-0.1.0.0...
Preprocessing executable 'exe' for Includes3-0.1.0.0...
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/Backpack/Reexport2/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Error:
Problem with module re-exports:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/Backpack/T6385/cabal.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/Backpack/bkpcabal01/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/BuildDeps/DepCycle/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Error:
Dependency cycle between the following components:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Error: [Cabal-7107]
Could not resolve dependencies:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/BuildToolDepends/setup.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/BuildTools/External/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/BuildTools/Internal/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/CmmSources/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-run
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/CmmSourcesDyn/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-run
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/CmmSourcesExe/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-run
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-run
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/ConfigFile/T8487/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O2
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/Configure/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/CopyHie/cabal.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/CustomSegfault/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/CustomWithoutCabal/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
1 change: 1 addition & 0 deletions cabal-testsuite/PackageTests/Exec/cabal.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# cabal v2-build
Querying pkg-config database...
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
Expand Down
Loading

0 comments on commit 03e8346

Please sign in to comment.