{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}
module GHC.Prof.CostCentreTree
  ( -- * Cost center breakdown
  -- ** Aggregate cost centres
    aggregatedCostCentres
  , aggregatedCostCentresOrderBy

  -- ** Cost centre trees
  , costCentres
  , costCentresOrderBy

  -- * Call site breakdown
  -- ** Aggregate call sites
  , aggregateCallSites
  , aggregateCallSitesOrderBy

  -- ** Call sites
  , callSites
  , callSitesOrderBy

  -- * Module breakdown
  , aggregateModules
  , aggregateModulesOrderBy

  -- * Low level functions
  , buildAggregatedCostCentresOrderBy
  , buildCostCentresOrderBy
  , buildCallSitesOrderBy
  , buildAggregateCallSitesOrderBy
  ) where
import Control.Applicative
import Control.Arrow ((&&&))
import Control.Monad
import Data.Function (on)
import Data.List
import Data.Maybe (listToMaybe)
import Prelude hiding (mapM)
import qualified Data.Foldable as Fold

import Data.Text (Text)
import Data.Tree (Tree)
import qualified Data.Set as Set
import qualified Data.Tree as Tree

import Control.Monad.Extras (seqM)
import GHC.Prof.Types as Types

#if MIN_VERSION_containers(0, 5, 0)
import qualified Data.IntMap.Strict as IntMap
import qualified Data.Map.Strict as Map
#else
import qualified Data.IntMap as IntMap
import qualified Data.Map as Map
#endif

-- | Build a list of cost-centres from a profiling report ordered by the time
-- spent and the amount of allocation.
aggregatedCostCentres :: Profile -> [AggregatedCostCentre]
aggregatedCostCentres :: Profile -> [AggregatedCostCentre]
aggregatedCostCentres = (AggregatedCostCentre -> (Scientific, Scientific))
-> Profile -> [AggregatedCostCentre]
forall a.
Ord a =>
(AggregatedCostCentre -> a) -> Profile -> [AggregatedCostCentre]
aggregatedCostCentresOrderBy AggregatedCostCentre -> (Scientific, Scientific)
sortKey
  where
    sortKey :: AggregatedCostCentre -> (Scientific, Scientific)
sortKey = AggregatedCostCentre -> Scientific
aggregatedCostCentreTime (AggregatedCostCentre -> Scientific)
-> (AggregatedCostCentre -> Scientific)
-> AggregatedCostCentre
-> (Scientific, Scientific)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& AggregatedCostCentre -> Scientific
aggregatedCostCentreAlloc

-- | Build a list of cost-centres from a profling report ordered by the given
-- key.
aggregatedCostCentresOrderBy
  :: Ord a
  => (AggregatedCostCentre -> a)
  -- ^ Sorting key function
  -> Profile
  -> [AggregatedCostCentre]
aggregatedCostCentresOrderBy :: (AggregatedCostCentre -> a) -> Profile -> [AggregatedCostCentre]
aggregatedCostCentresOrderBy AggregatedCostCentre -> a
sortKey =
  (AggregatedCostCentre -> a)
-> CostCentreTree -> [AggregatedCostCentre]
forall a.
Ord a =>
(AggregatedCostCentre -> a)
-> CostCentreTree -> [AggregatedCostCentre]
buildAggregatedCostCentresOrderBy AggregatedCostCentre -> a
sortKey (CostCentreTree -> [AggregatedCostCentre])
-> (Profile -> CostCentreTree) -> Profile -> [AggregatedCostCentre]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Profile -> CostCentreTree
profileCostCentreTree

-- | Build a tree of cost-centres from a profiling report.
costCentres :: Profile -> Maybe (Tree CostCentre)
costCentres :: Profile -> Maybe (Tree CostCentre)
costCentres = (CostCentre
 -> (Scientific, (Scientific, (Scientific, Scientific))))
-> Profile -> Maybe (Tree CostCentre)
forall a.
Ord a =>
(CostCentre -> a) -> Profile -> Maybe (Tree CostCentre)
costCentresOrderBy CostCentre -> (Scientific, (Scientific, (Scientific, Scientific)))
sortKey
  where
    sortKey :: CostCentre -> (Scientific, (Scientific, (Scientific, Scientific)))
sortKey =
      CostCentre -> Scientific
costCentreInhTime (CostCentre -> Scientific)
-> (CostCentre -> (Scientific, (Scientific, Scientific)))
-> CostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CostCentre -> Scientific
costCentreIndTime (CostCentre -> Scientific)
-> (CostCentre -> (Scientific, Scientific))
-> CostCentre
-> (Scientific, (Scientific, Scientific))
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&&
      CostCentre -> Scientific
costCentreInhAlloc (CostCentre -> Scientific)
-> (CostCentre -> Scientific)
-> CostCentre
-> (Scientific, Scientific)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CostCentre -> Scientific
costCentreIndAlloc

-- | Build a tree of cost-centres from a profiling report.
-- Nodes are sorted by the given key function for each level
-- of the tree.
costCentresOrderBy
  :: Ord a
  => (CostCentre -> a)
  -- ^ Sorting key function
  -> Profile
  -> Maybe (Tree CostCentre)
costCentresOrderBy :: (CostCentre -> a) -> Profile -> Maybe (Tree CostCentre)
costCentresOrderBy CostCentre -> a
sortKey =
  (CostCentre -> a) -> CostCentreTree -> Maybe (Tree CostCentre)
forall a.
Ord a =>
(CostCentre -> a) -> CostCentreTree -> Maybe (Tree CostCentre)
buildCostCentresOrderBy CostCentre -> a
sortKey (CostCentreTree -> Maybe (Tree CostCentre))
-> (Profile -> CostCentreTree)
-> Profile
-> Maybe (Tree CostCentre)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Profile -> CostCentreTree
profileCostCentreTree

-- | Build a list of call sites (caller functions of a cost centre) aggregated
-- by their cost centre names and module names.
aggregateCallSites
  :: Text
  -- ^ Cost centre name
  -> Text
  -- ^ Module name
  -> Profile
  -> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
aggregateCallSites :: Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
aggregateCallSites = (CallSite AggregatedCostCentre
 -> (Scientific, (Scientific, (Scientific, Scientific))))
-> Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
forall a.
Ord a =>
(CallSite AggregatedCostCentre -> a)
-> Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
aggregateCallSitesOrderBy CallSite AggregatedCostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
sortKey
  where
    sortKey :: CallSite AggregatedCostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
sortKey = CallSite AggregatedCostCentre -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribTime (CallSite AggregatedCostCentre -> Scientific)
-> (CallSite AggregatedCostCentre
    -> (Scientific, (Scientific, Scientific)))
-> CallSite AggregatedCostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CallSite AggregatedCostCentre -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribAlloc
      (CallSite AggregatedCostCentre -> Scientific)
-> (CallSite AggregatedCostCentre -> (Scientific, Scientific))
-> CallSite AggregatedCostCentre
-> (Scientific, (Scientific, Scientific))
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& AggregatedCostCentre -> Scientific
aggregatedCostCentreTime (AggregatedCostCentre -> Scientific)
-> (CallSite AggregatedCostCentre -> AggregatedCostCentre)
-> CallSite AggregatedCostCentre
-> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallSite AggregatedCostCentre -> AggregatedCostCentre
forall cc. CallSite cc -> cc
callSiteCostCentre
      (CallSite AggregatedCostCentre -> Scientific)
-> (CallSite AggregatedCostCentre -> Scientific)
-> CallSite AggregatedCostCentre
-> (Scientific, Scientific)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& AggregatedCostCentre -> Scientific
aggregatedCostCentreAlloc (AggregatedCostCentre -> Scientific)
-> (CallSite AggregatedCostCentre -> AggregatedCostCentre)
-> CallSite AggregatedCostCentre
-> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallSite AggregatedCostCentre -> AggregatedCostCentre
forall cc. CallSite cc -> cc
callSiteCostCentre

-- | Build a list of call sites (caller functions of a cost centre) aggregated
-- by their cost centre names and module names. Call sites are sorted by the
-- given key function.
aggregateCallSitesOrderBy
  :: Ord a
  => (CallSite AggregatedCostCentre -> a)
  -- ^ Sorting key function
  -> Text
  -- ^ Cost centre name
  -> Text
  -- ^ Module name
  -> Profile
  -> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
aggregateCallSitesOrderBy :: (CallSite AggregatedCostCentre -> a)
-> Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
aggregateCallSitesOrderBy CallSite AggregatedCostCentre -> a
sortKey Text
name Text
modName =
  (CallSite AggregatedCostCentre -> a)
-> Text
-> Text
-> CostCentreTree
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
forall a.
Ord a =>
(CallSite AggregatedCostCentre -> a)
-> Text
-> Text
-> CostCentreTree
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
buildAggregateCallSitesOrderBy CallSite AggregatedCostCentre -> a
sortKey Text
name Text
modName (CostCentreTree
 -> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre]))
-> (Profile -> CostCentreTree)
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Profile -> CostCentreTree
profileCostCentreTree

-- | Build a list of call-sites (caller functions) for a specified
-- cost-centre name and module name.
callSites
  :: Text
  -- ^ Cost-centre name
  -> Text
  -- ^ Module name
  -> Profile
  -> Maybe (AggregatedCostCentre, [CallSite CostCentre])
callSites :: Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
callSites = (CallSite CostCentre
 -> (Scientific, (Scientific, (Scientific, Scientific))))
-> Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
forall a.
Ord a =>
(CallSite CostCentre -> a)
-> Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
callSitesOrderBy CallSite CostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
sortKey
  where
    sortKey :: CallSite CostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
sortKey = CallSite CostCentre -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribTime (CallSite CostCentre -> Scientific)
-> (CallSite CostCentre -> (Scientific, (Scientific, Scientific)))
-> CallSite CostCentre
-> (Scientific, (Scientific, (Scientific, Scientific)))
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CallSite CostCentre -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribAlloc
      (CallSite CostCentre -> Scientific)
-> (CallSite CostCentre -> (Scientific, Scientific))
-> CallSite CostCentre
-> (Scientific, (Scientific, Scientific))
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CostCentre -> Scientific
costCentreIndTime (CostCentre -> Scientific)
-> (CallSite CostCentre -> CostCentre)
-> CallSite CostCentre
-> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallSite CostCentre -> CostCentre
forall cc. CallSite cc -> cc
callSiteCostCentre
      (CallSite CostCentre -> Scientific)
-> (CallSite CostCentre -> Scientific)
-> CallSite CostCentre
-> (Scientific, Scientific)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CostCentre -> Scientific
costCentreIndAlloc (CostCentre -> Scientific)
-> (CallSite CostCentre -> CostCentre)
-> CallSite CostCentre
-> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallSite CostCentre -> CostCentre
forall cc. CallSite cc -> cc
callSiteCostCentre

-- | Build a list of call-sites (caller function) for a specified
-- cost-centre name and module name. Nodes are sorted by the given
-- key function.
callSitesOrderBy
  :: Ord a
  => (CallSite CostCentre -> a)
  -- ^ Sorting key function
  -> Text
  -- ^ Cost-centre name
  -> Text
  -- ^ Module name
  -> Profile
  -> Maybe (AggregatedCostCentre, [CallSite CostCentre])
callSitesOrderBy :: (CallSite CostCentre -> a)
-> Text
-> Text
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
callSitesOrderBy CallSite CostCentre -> a
sortKey Text
name Text
modName =
  (CallSite CostCentre -> a)
-> Text
-> Text
-> CostCentreTree
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
forall a.
Ord a =>
(CallSite CostCentre -> a)
-> Text
-> Text
-> CostCentreTree
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
buildCallSitesOrderBy CallSite CostCentre -> a
sortKey Text
name Text
modName (CostCentreTree
 -> Maybe (AggregatedCostCentre, [CallSite CostCentre]))
-> (Profile -> CostCentreTree)
-> Profile
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Profile -> CostCentreTree
profileCostCentreTree

-- | Break down aggregate cost centres by module sorted by total time and
-- allocation.
aggregateModules
  :: Profile
  -> [AggregateModule]
aggregateModules :: Profile -> [AggregateModule]
aggregateModules = (AggregateModule -> (Scientific, Scientific))
-> Profile -> [AggregateModule]
forall a.
Ord a =>
(AggregateModule -> a) -> Profile -> [AggregateModule]
aggregateModulesOrderBy AggregateModule -> (Scientific, Scientific)
sortKey
  where
    sortKey :: AggregateModule -> (Scientific, Scientific)
sortKey = AggregateModule -> Scientific
aggregateModuleTime (AggregateModule -> Scientific)
-> (AggregateModule -> Scientific)
-> AggregateModule
-> (Scientific, Scientific)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& AggregateModule -> Scientific
aggregateModuleAlloc

-- | Break odwn aggregate cost centres by module.
aggregateModulesOrderBy
  :: Ord a
  => (AggregateModule -> a) -- ^ Sorting key function
  -> Profile
  -> [AggregateModule]
aggregateModulesOrderBy :: (AggregateModule -> a) -> Profile -> [AggregateModule]
aggregateModulesOrderBy AggregateModule -> a
sortKey =
    (AggregateModule -> a) -> CostCentreTree -> [AggregateModule]
forall a.
Ord a =>
(AggregateModule -> a) -> CostCentreTree -> [AggregateModule]
buildAggregateModulesOrderBy AggregateModule -> a
sortKey (CostCentreTree -> [AggregateModule])
-> (Profile -> CostCentreTree) -> Profile -> [AggregateModule]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Profile -> CostCentreTree
profileCostCentreTree

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

buildAggregatedCostCentresOrderBy
  :: Ord a
  => (AggregatedCostCentre -> a)
  -> CostCentreTree
  -> [AggregatedCostCentre]
buildAggregatedCostCentresOrderBy :: (AggregatedCostCentre -> a)
-> CostCentreTree -> [AggregatedCostCentre]
buildAggregatedCostCentresOrderBy AggregatedCostCentre -> a
sortKey CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
..} =
  (AggregatedCostCentre -> AggregatedCostCentre -> Ordering)
-> [AggregatedCostCentre] -> [AggregatedCostCentre]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> (AggregatedCostCentre -> a)
-> AggregatedCostCentre
-> AggregatedCostCentre
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` AggregatedCostCentre -> a
sortKey) ([AggregatedCostCentre] -> [AggregatedCostCentre])
-> [AggregatedCostCentre] -> [AggregatedCostCentre]
forall a b. (a -> b) -> a -> b
$
    (Map Text AggregatedCostCentre -> [AggregatedCostCentre])
-> [Map Text AggregatedCostCentre] -> [AggregatedCostCentre]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Map Text AggregatedCostCentre -> [AggregatedCostCentre]
forall k a. Map k a -> [a]
Map.elems ([Map Text AggregatedCostCentre] -> [AggregatedCostCentre])
-> [Map Text AggregatedCostCentre] -> [AggregatedCostCentre]
forall a b. (a -> b) -> a -> b
$ Map Text (Map Text AggregatedCostCentre)
-> [Map Text AggregatedCostCentre]
forall k a. Map k a -> [a]
Map.elems (Map Text (Map Text AggregatedCostCentre)
 -> [Map Text AggregatedCostCentre])
-> Map Text (Map Text AggregatedCostCentre)
-> [Map Text AggregatedCostCentre]
forall a b. (a -> b) -> a -> b
$ Map Text (Map Text AggregatedCostCentre)
costCentreAggregate

buildCostCentresOrderBy
  :: Ord a
  => (CostCentre -> a)
  -- ^ Sorting key function
  -> CostCentreTree
  -> Maybe (Tree CostCentre)
buildCostCentresOrderBy :: (CostCentre -> a) -> CostCentreTree -> Maybe (Tree CostCentre)
buildCostCentresOrderBy CostCentre -> a
sortKey CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
..} = do
  -- Invariant:
  --   The root node (MAIN.MAIN) should have the least cost centre ID
  CostCentreNo
rootKey <- [CostCentreNo] -> Maybe CostCentreNo
forall a. [a] -> Maybe a
listToMaybe ([CostCentreNo] -> Maybe CostCentreNo)
-> [CostCentreNo] -> Maybe CostCentreNo
forall a b. (a -> b) -> a -> b
$ IntMap CostCentre -> [CostCentreNo]
forall a. IntMap a -> [CostCentreNo]
IntMap.keys IntMap CostCentre
costCentreNodes
  (CostCentreNo -> Maybe (CostCentre, [CostCentreNo]))
-> CostCentreNo -> Maybe (Tree CostCentre)
forall (m :: * -> *) b a.
Monad m =>
(b -> m (a, [b])) -> b -> m (Tree a)
Tree.unfoldTreeM CostCentreNo -> Maybe (CostCentre, [CostCentreNo])
build CostCentreNo
rootKey
  where
    build :: CostCentreNo -> Maybe (CostCentre, [CostCentreNo])
build CostCentreNo
key = do
      CostCentre
node <- CostCentreNo -> IntMap CostCentre -> Maybe CostCentre
forall a. CostCentreNo -> IntMap a -> Maybe a
IntMap.lookup CostCentreNo
key IntMap CostCentre
costCentreNodes
      (CostCentre, [CostCentreNo]) -> Maybe (CostCentre, [CostCentreNo])
forall (m :: * -> *) a. Monad m => a -> m a
return (CostCentre
node, [CostCentreNo]
children)
      where
          !children :: [CostCentreNo]
children = [CostCentreNo]
-> ([CostCentreNo] -> [CostCentreNo])
-> Maybe [CostCentreNo]
-> [CostCentreNo]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] [CostCentreNo] -> [CostCentreNo]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Fold.toList (Maybe [CostCentreNo] -> [CostCentreNo])
-> Maybe [CostCentreNo] -> [CostCentreNo]
forall a b. (a -> b) -> a -> b
$ do
            Set CostCentre
nodes <- CostCentreNo -> IntMap (Set CostCentre) -> Maybe (Set CostCentre)
forall a. CostCentreNo -> IntMap a -> Maybe a
IntMap.lookup CostCentreNo
key IntMap (Set CostCentre)
costCentreChildren
            [CostCentreNo] -> Maybe [CostCentreNo]
forall (m :: * -> *) a. Monad m => a -> m a
return ([CostCentreNo] -> Maybe [CostCentreNo])
-> [CostCentreNo] -> Maybe [CostCentreNo]
forall a b. (a -> b) -> a -> b
$ CostCentre -> CostCentreNo
costCentreNo
              (CostCentre -> CostCentreNo) -> [CostCentre] -> [CostCentreNo]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (CostCentre -> CostCentre -> Ordering)
-> [CostCentre] -> [CostCentre]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> (CostCentre -> a) -> CostCentre -> CostCentre -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` CostCentre -> a
sortKey) (Set CostCentre -> [CostCentre]
forall a. Set a -> [a]
Set.toList Set CostCentre
nodes)

buildAggregateCallSitesOrderBy
  :: Ord a
  => (CallSite AggregatedCostCentre -> a)
  -- ^ Sorting key function
  -> Text
  -- ^ Cost centre name
  -> Text
  -- ^ Module name
  -> CostCentreTree
  -> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
buildAggregateCallSitesOrderBy :: (CallSite AggregatedCostCentre -> a)
-> Text
-> Text
-> CostCentreTree
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
buildAggregateCallSitesOrderBy CallSite AggregatedCostCentre -> a
sortKey Text
name Text
modName tree :: CostCentreTree
tree@CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
..} =
  (,) (AggregatedCostCentre
 -> [CallSite AggregatedCostCentre]
 -> (AggregatedCostCentre, [CallSite AggregatedCostCentre]))
-> Maybe AggregatedCostCentre
-> Maybe
     ([CallSite AggregatedCostCentre]
      -> (AggregatedCostCentre, [CallSite AggregatedCostCentre]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe AggregatedCostCentre
callee Maybe
  ([CallSite AggregatedCostCentre]
   -> (AggregatedCostCentre, [CallSite AggregatedCostCentre]))
-> Maybe [CallSite AggregatedCostCentre]
-> Maybe (AggregatedCostCentre, [CallSite AggregatedCostCentre])
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe [CallSite AggregatedCostCentre]
callers
  where
    callee :: Maybe AggregatedCostCentre
callee = Text
-> Text
-> Map Text (Map Text AggregatedCostCentre)
-> Maybe AggregatedCostCentre
lookupAggregate Text
name Text
modName Map Text (Map Text AggregatedCostCentre)
costCentreAggregate
    callers :: Maybe [CallSite AggregatedCostCentre]
callers = do
      Set CostCentre
callees <- (Text, Text)
-> Map (Text, Text) (Set CostCentre) -> Maybe (Set CostCentre)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Text
name, Text
modName) Map (Text, Text) (Set CostCentre)
costCentreCallSites
      (CallSite AggregatedCostCentre
 -> CallSite AggregatedCostCentre -> Ordering)
-> [CallSite AggregatedCostCentre]
-> [CallSite AggregatedCostCentre]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> (CallSite AggregatedCostCentre -> a)
-> CallSite AggregatedCostCentre
-> CallSite AggregatedCostCentre
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` CallSite AggregatedCostCentre -> a
sortKey) ([CallSite AggregatedCostCentre]
 -> [CallSite AggregatedCostCentre])
-> (Map (Text, Text) (CallSite AggregatedCostCentre)
    -> [CallSite AggregatedCostCentre])
-> Map (Text, Text) (CallSite AggregatedCostCentre)
-> [CallSite AggregatedCostCentre]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map (Text, Text) (CallSite AggregatedCostCentre)
-> [CallSite AggregatedCostCentre]
forall k a. Map k a -> [a]
Map.elems
        (Map (Text, Text) (CallSite AggregatedCostCentre)
 -> [CallSite AggregatedCostCentre])
-> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre))
-> Maybe [CallSite AggregatedCostCentre]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Map (Text, Text) (CallSite AggregatedCostCentre)
 -> CostCentre
 -> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre)))
-> Map (Text, Text) (CallSite AggregatedCostCentre)
-> [CostCentre]
-> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre))
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (CostCentreTree
-> Map (Text, Text) (CallSite AggregatedCostCentre)
-> CostCentre
-> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre))
buildAggregateCallSite CostCentreTree
tree) Map (Text, Text) (CallSite AggregatedCostCentre)
forall k a. Map k a
Map.empty (Set CostCentre -> [CostCentre]
forall a. Set a -> [a]
Set.toList Set CostCentre
callees)

buildAggregateCallSite
  :: CostCentreTree
  -> Map.Map (Text, Text) (CallSite AggregatedCostCentre)
  -> CostCentre
  -> Maybe (Map.Map (Text, Text) (CallSite AggregatedCostCentre))
buildAggregateCallSite :: CostCentreTree
-> Map (Text, Text) (CallSite AggregatedCostCentre)
-> CostCentre
-> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre))
buildAggregateCallSite CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
..} Map (Text, Text) (CallSite AggregatedCostCentre)
parents CostCentre {CostCentreNo
Integer
Maybe Integer
Maybe Text
Text
Scientific
costCentreBytes :: CostCentre -> Maybe Integer
costCentreTicks :: CostCentre -> Maybe Integer
costCentreEntries :: CostCentre -> Integer
costCentreSrc :: CostCentre -> Maybe Text
costCentreModule :: CostCentre -> Text
costCentreName :: CostCentre -> Text
costCentreBytes :: Maybe Integer
costCentreTicks :: Maybe Integer
costCentreInhAlloc :: Scientific
costCentreInhTime :: Scientific
costCentreIndAlloc :: Scientific
costCentreIndTime :: Scientific
costCentreEntries :: Integer
costCentreSrc :: Maybe Text
costCentreModule :: Text
costCentreName :: Text
costCentreNo :: CostCentreNo
costCentreNo :: CostCentre -> CostCentreNo
costCentreIndAlloc :: CostCentre -> Scientific
costCentreInhAlloc :: CostCentre -> Scientific
costCentreIndTime :: CostCentre -> Scientific
costCentreInhTime :: CostCentre -> Scientific
..} = do
  CostCentreNo
parentNo <- CostCentreNo -> IntMap CostCentreNo -> Maybe CostCentreNo
forall a. CostCentreNo -> IntMap a -> Maybe a
IntMap.lookup CostCentreNo
costCentreNo IntMap CostCentreNo
costCentreParents
  CostCentre
parent <- CostCentreNo -> IntMap CostCentre -> Maybe CostCentre
forall a. CostCentreNo -> IntMap a -> Maybe a
IntMap.lookup CostCentreNo
parentNo IntMap CostCentre
costCentreNodes
  let parentName :: Text
parentName = CostCentre -> Text
Types.costCentreName CostCentre
parent
      parentModule :: Text
parentModule = CostCentre -> Text
Types.costCentreModule CostCentre
parent
  AggregatedCostCentre
aggregate <- Text
-> Text
-> Map Text (Map Text AggregatedCostCentre)
-> Maybe AggregatedCostCentre
lookupAggregate Text
parentName Text
parentModule Map Text (Map Text AggregatedCostCentre)
costCentreAggregate
  Map (Text, Text) (CallSite AggregatedCostCentre)
-> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre))
forall (m :: * -> *) a. Monad m => a -> m a
return (Map (Text, Text) (CallSite AggregatedCostCentre)
 -> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre)))
-> Map (Text, Text) (CallSite AggregatedCostCentre)
-> Maybe (Map (Text, Text) (CallSite AggregatedCostCentre))
forall a b. (a -> b) -> a -> b
$! (CallSite AggregatedCostCentre
 -> CallSite AggregatedCostCentre -> CallSite AggregatedCostCentre)
-> (Text, Text)
-> CallSite AggregatedCostCentre
-> Map (Text, Text) (CallSite AggregatedCostCentre)
-> Map (Text, Text) (CallSite AggregatedCostCentre)
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith
    CallSite AggregatedCostCentre
-> CallSite AggregatedCostCentre -> CallSite AggregatedCostCentre
forall a. CallSite a -> CallSite a -> CallSite a
mergeCallSites
    (Text
parentName, Text
parentModule)
    CallSite :: forall cc.
cc
-> Integer
-> Scientific
-> Scientific
-> Maybe Integer
-> Maybe Integer
-> CallSite cc
CallSite
      { callSiteCostCentre :: AggregatedCostCentre
callSiteCostCentre = AggregatedCostCentre
aggregate
      , callSiteContribEntries :: Integer
callSiteContribEntries = Integer
costCentreEntries
      , callSiteContribTime :: Scientific
callSiteContribTime = Scientific
costCentreIndTime
      , callSiteContribAlloc :: Scientific
callSiteContribAlloc = Scientific
costCentreIndAlloc
      , callSiteContribTicks :: Maybe Integer
callSiteContribTicks = Maybe Integer
costCentreTicks
      , callSiteContribBytes :: Maybe Integer
callSiteContribBytes = Maybe Integer
costCentreBytes
      }
    Map (Text, Text) (CallSite AggregatedCostCentre)
parents

mergeCallSites :: CallSite a -> CallSite a -> CallSite a
mergeCallSites :: CallSite a -> CallSite a -> CallSite a
mergeCallSites CallSite a
a CallSite a
b = CallSite a
a
  { callSiteContribEntries :: Integer
callSiteContribEntries = CallSite a -> Integer
forall cc. CallSite cc -> Integer
callSiteContribEntries CallSite a
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ CallSite a -> Integer
forall cc. CallSite cc -> Integer
callSiteContribEntries CallSite a
b
  , callSiteContribTime :: Scientific
callSiteContribTime = CallSite a -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribTime CallSite a
a Scientific -> Scientific -> Scientific
forall a. Num a => a -> a -> a
+ CallSite a -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribTime CallSite a
b
  , callSiteContribAlloc :: Scientific
callSiteContribAlloc = CallSite a -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribAlloc CallSite a
a Scientific -> Scientific -> Scientific
forall a. Num a => a -> a -> a
+ CallSite a -> Scientific
forall cc. CallSite cc -> Scientific
callSiteContribAlloc CallSite a
b
  , callSiteContribTicks :: Maybe Integer
callSiteContribTicks = Maybe Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => m a -> m a
seqM (Maybe Integer -> Maybe Integer) -> Maybe Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
    (Integer -> Integer -> Integer)
-> Maybe Integer -> Maybe (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CallSite a -> Maybe Integer
forall cc. CallSite cc -> Maybe Integer
callSiteContribTicks CallSite a
a
    Maybe (Integer -> Integer) -> Maybe Integer -> Maybe Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> CallSite a -> Maybe Integer
forall cc. CallSite cc -> Maybe Integer
callSiteContribTicks CallSite a
b
  , callSiteContribBytes :: Maybe Integer
callSiteContribBytes = Maybe Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => m a -> m a
seqM (Maybe Integer -> Maybe Integer) -> Maybe Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
    (Integer -> Integer -> Integer)
-> Maybe Integer -> Maybe (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CallSite a -> Maybe Integer
forall cc. CallSite cc -> Maybe Integer
callSiteContribBytes CallSite a
a
    Maybe (Integer -> Integer) -> Maybe Integer -> Maybe Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> CallSite a -> Maybe Integer
forall cc. CallSite cc -> Maybe Integer
callSiteContribBytes CallSite a
b
  }

buildCallSitesOrderBy
  :: Ord a
  => (CallSite CostCentre -> a)
  -- ^ Sorting key function
  -> Text
  -- ^ Cost-centre name
  -> Text
  -- ^ Module name
  -> CostCentreTree
  -> Maybe (AggregatedCostCentre, [CallSite CostCentre])
buildCallSitesOrderBy :: (CallSite CostCentre -> a)
-> Text
-> Text
-> CostCentreTree
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
buildCallSitesOrderBy CallSite CostCentre -> a
sortKey Text
name Text
modName tree :: CostCentreTree
tree@CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
..} =
  (,) (AggregatedCostCentre
 -> [CallSite CostCentre]
 -> (AggregatedCostCentre, [CallSite CostCentre]))
-> Maybe AggregatedCostCentre
-> Maybe
     ([CallSite CostCentre]
      -> (AggregatedCostCentre, [CallSite CostCentre]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe AggregatedCostCentre
callee Maybe
  ([CallSite CostCentre]
   -> (AggregatedCostCentre, [CallSite CostCentre]))
-> Maybe [CallSite CostCentre]
-> Maybe (AggregatedCostCentre, [CallSite CostCentre])
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe [CallSite CostCentre]
callers
  where
    callee :: Maybe AggregatedCostCentre
callee = Text
-> Text
-> Map Text (Map Text AggregatedCostCentre)
-> Maybe AggregatedCostCentre
lookupAggregate Text
name Text
modName Map Text (Map Text AggregatedCostCentre)
costCentreAggregate
    callers :: Maybe [CallSite CostCentre]
callers = do
      Set CostCentre
callees <- (Text, Text)
-> Map (Text, Text) (Set CostCentre) -> Maybe (Set CostCentre)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Text
name, Text
modName) Map (Text, Text) (Set CostCentre)
costCentreCallSites
      (CallSite CostCentre -> CallSite CostCentre -> Ordering)
-> [CallSite CostCentre] -> [CallSite CostCentre]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> (CallSite CostCentre -> a)
-> CallSite CostCentre
-> CallSite CostCentre
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` CallSite CostCentre -> a
sortKey)
        ([CallSite CostCentre] -> [CallSite CostCentre])
-> Maybe [CallSite CostCentre] -> Maybe [CallSite CostCentre]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (CostCentre -> Maybe (CallSite CostCentre))
-> [CostCentre] -> Maybe [CallSite CostCentre]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (CostCentreTree -> CostCentre -> Maybe (CallSite CostCentre)
buildCallSite CostCentreTree
tree) (Set CostCentre -> [CostCentre]
forall a. Set a -> [a]
Set.toList Set CostCentre
callees)

buildCallSite
  :: CostCentreTree
  -> CostCentre
  -> Maybe (CallSite CostCentre)
buildCallSite :: CostCentreTree -> CostCentre -> Maybe (CallSite CostCentre)
buildCallSite CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
..} CostCentre {CostCentreNo
Integer
Maybe Integer
Maybe Text
Text
Scientific
costCentreBytes :: Maybe Integer
costCentreTicks :: Maybe Integer
costCentreInhAlloc :: Scientific
costCentreInhTime :: Scientific
costCentreIndAlloc :: Scientific
costCentreIndTime :: Scientific
costCentreEntries :: Integer
costCentreSrc :: Maybe Text
costCentreModule :: Text
costCentreName :: Text
costCentreNo :: CostCentreNo
costCentreBytes :: CostCentre -> Maybe Integer
costCentreTicks :: CostCentre -> Maybe Integer
costCentreEntries :: CostCentre -> Integer
costCentreSrc :: CostCentre -> Maybe Text
costCentreModule :: CostCentre -> Text
costCentreName :: CostCentre -> Text
costCentreNo :: CostCentre -> CostCentreNo
costCentreIndAlloc :: CostCentre -> Scientific
costCentreInhAlloc :: CostCentre -> Scientific
costCentreIndTime :: CostCentre -> Scientific
costCentreInhTime :: CostCentre -> Scientific
..} = do
  CostCentreNo
parentNo <- CostCentreNo -> IntMap CostCentreNo -> Maybe CostCentreNo
forall a. CostCentreNo -> IntMap a -> Maybe a
IntMap.lookup CostCentreNo
costCentreNo IntMap CostCentreNo
costCentreParents
  CostCentre
parent <- CostCentreNo -> IntMap CostCentre -> Maybe CostCentre
forall a. CostCentreNo -> IntMap a -> Maybe a
IntMap.lookup CostCentreNo
parentNo IntMap CostCentre
costCentreNodes
  CallSite CostCentre -> Maybe (CallSite CostCentre)
forall (m :: * -> *) a. Monad m => a -> m a
return CallSite :: forall cc.
cc
-> Integer
-> Scientific
-> Scientific
-> Maybe Integer
-> Maybe Integer
-> CallSite cc
CallSite
    { callSiteCostCentre :: CostCentre
callSiteCostCentre = CostCentre
parent
    , callSiteContribEntries :: Integer
callSiteContribEntries = Integer
costCentreEntries
    , callSiteContribTime :: Scientific
callSiteContribTime = Scientific
costCentreIndTime
    , callSiteContribAlloc :: Scientific
callSiteContribAlloc = Scientific
costCentreIndAlloc
    , callSiteContribTicks :: Maybe Integer
callSiteContribTicks = Maybe Integer
costCentreTicks
    , callSiteContribBytes :: Maybe Integer
callSiteContribBytes = Maybe Integer
costCentreBytes
    }

buildAggregateModulesOrderBy
  :: Ord a
  => (AggregateModule -> a)
  -- ^ Sorting key function
  -> CostCentreTree
  -> [AggregateModule]
buildAggregateModulesOrderBy :: (AggregateModule -> a) -> CostCentreTree -> [AggregateModule]
buildAggregateModulesOrderBy AggregateModule -> a
sortKey CostCentreTree {IntMap CostCentreNo
IntMap (Set CostCentre)
IntMap CostCentre
Map (Text, Text) (Set CostCentre)
Map Text (Map Text AggregatedCostCentre)
costCentreAggregate :: Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: Map (Text, Text) (Set CostCentre)
costCentreChildren :: IntMap (Set CostCentre)
costCentreParents :: IntMap CostCentreNo
costCentreNodes :: IntMap CostCentre
costCentreAggregate :: CostCentreTree -> Map Text (Map Text AggregatedCostCentre)
costCentreCallSites :: CostCentreTree -> Map (Text, Text) (Set CostCentre)
costCentreChildren :: CostCentreTree -> IntMap (Set CostCentre)
costCentreParents :: CostCentreTree -> IntMap CostCentreNo
costCentreNodes :: CostCentreTree -> IntMap CostCentre
..} =
  (AggregateModule -> AggregateModule -> Ordering)
-> [AggregateModule] -> [AggregateModule]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> (AggregateModule -> a)
-> AggregateModule
-> AggregateModule
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` AggregateModule -> a
sortKey) ([AggregateModule] -> [AggregateModule])
-> [AggregateModule] -> [AggregateModule]
forall a b. (a -> b) -> a -> b
$
    (Text
 -> Map Text AggregatedCostCentre
 -> [AggregateModule]
 -> [AggregateModule])
-> [AggregateModule]
-> Map Text (Map Text AggregatedCostCentre)
-> [AggregateModule]
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey
      (\Text
modName Map Text AggregatedCostCentre
ccs [AggregateModule]
as -> Text -> Map Text AggregatedCostCentre -> AggregateModule
forall k. Text -> Map k AggregatedCostCentre -> AggregateModule
aggregateModule Text
modName Map Text AggregatedCostCentre
ccs AggregateModule -> [AggregateModule] -> [AggregateModule]
forall a. a -> [a] -> [a]
: [AggregateModule]
as)
      []
      Map Text (Map Text AggregatedCostCentre)
costCentreAggregate
  where
    aggregateModule :: Text -> Map k AggregatedCostCentre -> AggregateModule
aggregateModule Text
modName = (AggregateModule -> AggregatedCostCentre -> AggregateModule)
-> AggregateModule -> Map k AggregatedCostCentre -> AggregateModule
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Map.foldl' AggregateModule -> AggregatedCostCentre -> AggregateModule
add (Text -> AggregateModule
emptyAggregateModule Text
modName)
    add :: AggregateModule -> AggregatedCostCentre -> AggregateModule
add AggregateModule
aggMod AggregatedCostCentre {Maybe Integer
Maybe Text
Text
Scientific
aggregatedCostCentreBytes :: AggregatedCostCentre -> Maybe Integer
aggregatedCostCentreTicks :: AggregatedCostCentre -> Maybe Integer
aggregatedCostCentreEntries :: AggregatedCostCentre -> Maybe Integer
aggregatedCostCentreSrc :: AggregatedCostCentre -> Maybe Text
aggregatedCostCentreModule :: AggregatedCostCentre -> Text
aggregatedCostCentreName :: AggregatedCostCentre -> Text
aggregatedCostCentreBytes :: Maybe Integer
aggregatedCostCentreTicks :: Maybe Integer
aggregatedCostCentreAlloc :: Scientific
aggregatedCostCentreTime :: Scientific
aggregatedCostCentreEntries :: Maybe Integer
aggregatedCostCentreSrc :: Maybe Text
aggregatedCostCentreModule :: Text
aggregatedCostCentreName :: Text
aggregatedCostCentreAlloc :: AggregatedCostCentre -> Scientific
aggregatedCostCentreTime :: AggregatedCostCentre -> Scientific
..} = AggregateModule
aggMod
      { aggregateModuleEntries :: Maybe Integer
aggregateModuleEntries = Maybe Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => m a -> m a
seqM (Maybe Integer -> Maybe Integer) -> Maybe Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
        (Integer -> Integer -> Integer)
-> Maybe Integer -> Maybe (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AggregateModule -> Maybe Integer
aggregateModuleEntries AggregateModule
aggMod
        Maybe (Integer -> Integer) -> Maybe Integer -> Maybe Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Integer
aggregatedCostCentreEntries
      , aggregateModuleTime :: Scientific
aggregateModuleTime =
        AggregateModule -> Scientific
aggregateModuleTime AggregateModule
aggMod Scientific -> Scientific -> Scientific
forall a. Num a => a -> a -> a
+ Scientific
aggregatedCostCentreTime
      , aggregateModuleAlloc :: Scientific
aggregateModuleAlloc =
        AggregateModule -> Scientific
aggregateModuleAlloc AggregateModule
aggMod Scientific -> Scientific -> Scientific
forall a. Num a => a -> a -> a
+ Scientific
aggregatedCostCentreAlloc
      , aggregateModuleTicks :: Maybe Integer
aggregateModuleTicks = Maybe Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => m a -> m a
seqM (Maybe Integer -> Maybe Integer) -> Maybe Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
        (Integer -> Integer -> Integer)
-> Maybe Integer -> Maybe (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AggregateModule -> Maybe Integer
aggregateModuleTicks AggregateModule
aggMod
        Maybe (Integer -> Integer) -> Maybe Integer -> Maybe Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Integer
aggregatedCostCentreTicks
      , aggregateModuleBytes :: Maybe Integer
aggregateModuleBytes = Maybe Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => m a -> m a
seqM (Maybe Integer -> Maybe Integer) -> Maybe Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
        (Integer -> Integer -> Integer)
-> Maybe Integer -> Maybe (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AggregateModule -> Maybe Integer
aggregateModuleBytes AggregateModule
aggMod
        Maybe (Integer -> Integer) -> Maybe Integer -> Maybe Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Integer
aggregatedCostCentreBytes
      }

lookupAggregate
  :: Text -- ^ Cost centre name
  -> Text -- ^ Module name
  -> Map.Map Text (Map.Map Text AggregatedCostCentre)
  -> Maybe AggregatedCostCentre
lookupAggregate :: Text
-> Text
-> Map Text (Map Text AggregatedCostCentre)
-> Maybe AggregatedCostCentre
lookupAggregate Text
name Text
modName Map Text (Map Text AggregatedCostCentre)
m = Text
-> Map Text (Map Text AggregatedCostCentre)
-> Maybe (Map Text AggregatedCostCentre)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
modName Map Text (Map Text AggregatedCostCentre)
m Maybe (Map Text AggregatedCostCentre)
-> (Map Text AggregatedCostCentre -> Maybe AggregatedCostCentre)
-> Maybe AggregatedCostCentre
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Map Text AggregatedCostCentre -> Maybe AggregatedCostCentre
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
name