Hannes Siebenhandl pushed to branch wip/fendor/ghc-pkg-faster-closure at Glasgow Haskell Compiler / GHC

Commits:

2 changed files:

Changes:

  • changelog.d/ghc-pkg-faster-closure
    1
    +section: ghc-pkg
    
    2
    +synopsis: Improve performance of `ghc-pkg list` command
    
    3
    +issues: #27275
    
    4
    +mrs: !16062
    
    5
    +
    
    6
    +description: {
    
    7
    +`ghc-pkg list` was quadratic in the number of packages due to an inefficient `closure` computation.
    
    8
    +We cache the set of seen packages, allowing us to speed up the `closure` computation, improving run-time
    
    9
    +for the commands `list`, `check`, `distrust`, `expose`, `hide`, `trust` and `unregister`.
    
    10
    +}

  • utils/ghc-pkg/Main.hs
    ... ... @@ -1826,7 +1826,7 @@ checkConsistency verbosity my_flags = do
    1826 1826
                   all_ps = map mungedId pkgs1
    
    1827 1827
     
    
    1828 1828
       let not_broken_pkgs = filterOut broken_pkgs pkgs
    
    1829
    -      (_, trans_broken_pkgs) = closure [] not_broken_pkgs
    
    1829
    +      trans_broken_pkgs = brokenPackages not_broken_pkgs
    
    1830 1830
     
    
    1831 1831
           all_broken_pkgs :: [InstalledPackageInfo]
    
    1832 1832
           all_broken_pkgs = broken_pkgs ++ trans_broken_pkgs
    
    ... ... @@ -1845,26 +1845,26 @@ checkConsistency verbosity my_flags = do
    1845 1845
       when (not (null all_broken_pkgs)) $ exitWith (ExitFailure 1)
    
    1846 1846
     
    
    1847 1847
     
    
    1848
    -closure :: [InstalledPackageInfo] -> [InstalledPackageInfo]
    
    1849
    -        -> ([InstalledPackageInfo], [InstalledPackageInfo])
    
    1850
    -closure pkgs db_stack = go pkgs db_stack
    
    1851
    - where
    
    1852
    -   go avail not_avail =
    
    1853
    -     case partition (depsAvailable avail) not_avail of
    
    1854
    -        ([],        not_avail') -> (avail, not_avail')
    
    1855
    -        (new_avail, not_avail') -> go (new_avail ++ avail) not_avail'
    
    1848
    +-- | Compute the set of transitive broken packages.
    
    1849
    +--
    
    1850
    +-- A package is assumed to be broken if any of its dependencies is not
    
    1851
    +-- found in the 'db_stack' after a transitive reduction.
    
    1852
    +brokenPackages :: [InstalledPackageInfo] -> [InstalledPackageInfo]
    
    1853
    +brokenPackages db_stack = go Set.empty db_stack
    
    1854
    +  where
    
    1855
    +    go avail_ids not_avail =
    
    1856
    +      case partition (depsAvailable avail_ids) not_avail of
    
    1857
    +        ([],        not_avail') -> not_avail'
    
    1858
    +        (new_avail, not_avail') -> go (add new_avail avail_ids) not_avail'
    
    1856 1859
     
    
    1857
    -   depsAvailable :: [InstalledPackageInfo] -> InstalledPackageInfo
    
    1858
    -                 -> Bool
    
    1859
    -   depsAvailable pkgs_ok pkg = null dangling
    
    1860
    -        where dangling = filter (`notElem` pids) (depends pkg)
    
    1861
    -              pids = map installedUnitId pkgs_ok
    
    1860
    +    add new_avail avail_ids =
    
    1861
    +      foldl' (flip Set.insert) avail_ids (map installedUnitId new_avail)
    
    1862 1862
     
    
    1863
    -        -- we want mutually recursive groups of package to show up
    
    1864
    -        -- as broken. (#1750)
    
    1863
    +    depsAvailable :: Set.Set UnitId -> InstalledPackageInfo -> Bool
    
    1864
    +    depsAvailable pids pkg = all (`Set.member` pids) (depends pkg)
    
    1865 1865
     
    
    1866
    -brokenPackages :: [InstalledPackageInfo] -> [InstalledPackageInfo]
    
    1867
    -brokenPackages pkgs = snd (closure [] pkgs)
    
    1866
    +      -- we want mutually recursive groups of package to show up
    
    1867
    +      -- as broken. (#1750)
    
    1868 1868
     
    
    1869 1869
     -----------------------------------------------------------------------------
    
    1870 1870
     -- Sanity-check a new package config, and automatically build GHCi libs