lib: In sorting account names, perform lookups on HashSets and HashMaps,
rather than lists. This is probably not an enormous performance sink in real situations, but it takes a huge amount of time and memory in our benchmarks (specifically 10000x10000x10.journal). For bal -f examples/10000x10000x10.journal, this results in - A 23% reduction in heap allocation, from 27GiB to 21GiB - A 33% reduction in (profiled) time running, from 26.5s to 17.9s
This commit is contained in:
parent
13589aca2e
commit
522c8a6ad3
@ -1,4 +1,6 @@
|
|||||||
{-# LANGUAGE RecordWildCards, OverloadedStrings #-}
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-|
|
{-|
|
||||||
|
|
||||||
|
|
||||||
@ -9,12 +11,13 @@ account, and subaccounting-excluding and -including balances.
|
|||||||
|
|
||||||
module Hledger.Data.Account
|
module Hledger.Data.Account
|
||||||
where
|
where
|
||||||
|
import qualified Data.HashSet as HS
|
||||||
|
import qualified Data.HashMap.Strict as HM
|
||||||
import Data.List (find, sortOn)
|
import Data.List (find, sortOn)
|
||||||
import Data.List.Extra (groupSort, groupOn)
|
import Data.List.Extra (groupOn)
|
||||||
import Data.Maybe (fromMaybe)
|
|
||||||
import Data.Ord (Down(..))
|
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Safe (headMay, lookupJustDef)
|
import Data.Ord (Down(..))
|
||||||
|
import Safe (headMay)
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
|
||||||
import Hledger.Data.AccountName
|
import Hledger.Data.AccountName
|
||||||
@ -63,12 +66,12 @@ nullacct = Account
|
|||||||
accountsFromPostings :: [Posting] -> [Account]
|
accountsFromPostings :: [Posting] -> [Account]
|
||||||
accountsFromPostings ps =
|
accountsFromPostings ps =
|
||||||
let
|
let
|
||||||
grouped = groupSort [(paccount p,pamount p) | p <- ps]
|
summed = foldr (\p -> HM.insertWith addAndIncrement (paccount p) (1, pamount p)) mempty ps
|
||||||
counted = [(aname, length amts) | (aname, amts) <- grouped]
|
where addAndIncrement (n, a) (m, b) = (n + m, a `maPlus` b)
|
||||||
summed = [(aname, maSum amts) | (aname, amts) <- grouped] -- always non-empty
|
acctstree = accountTree "root" $ HM.keys summed
|
||||||
acctstree = accountTree "root" $ map fst summed
|
acctswithebals = mapAccounts setnumpsebalance acctstree
|
||||||
acctswithnumps = mapAccounts setnumps acctstree where setnumps a = a{anumpostings=fromMaybe 0 $ lookup (aname a) counted}
|
where setnumpsebalance a = a{anumpostings=numps, aebalance=total}
|
||||||
acctswithebals = mapAccounts setebalance acctswithnumps where setebalance a = a{aebalance=lookupJustDef nullmixedamt (aname a) summed}
|
where (numps, total) = HM.lookupDefault (0, nullmixedamt) (aname a) summed
|
||||||
acctswithibals = sumAccounts acctswithebals
|
acctswithibals = sumAccounts acctswithebals
|
||||||
acctswithparents = tieAccountParents acctswithibals
|
acctswithparents = tieAccountParents acctswithibals
|
||||||
acctsflattened = flattenAccounts acctswithparents
|
acctsflattened = flattenAccounts acctswithparents
|
||||||
@ -224,14 +227,14 @@ accountSetDeclarationInfo j a@Account{..} =
|
|||||||
--
|
--
|
||||||
sortAccountNamesByDeclaration :: Journal -> Bool -> [AccountName] -> [AccountName]
|
sortAccountNamesByDeclaration :: Journal -> Bool -> [AccountName] -> [AccountName]
|
||||||
sortAccountNamesByDeclaration j keepparents as =
|
sortAccountNamesByDeclaration j keepparents as =
|
||||||
(if keepparents then id else filter (`elem` as)) $ -- maybe discard missing parents that were added
|
(if keepparents then id else filter (`HS.member` HS.fromList as)) $ -- maybe discard missing parents that were added
|
||||||
map aname $ -- keep just the names
|
map aname $ -- keep just the names
|
||||||
drop 1 $ -- drop the root node that was added
|
drop 1 $ -- drop the root node that was added
|
||||||
flattenAccounts $ -- convert to an account list
|
flattenAccounts $ -- convert to an account list
|
||||||
sortAccountTreeByDeclaration $ -- sort by declaration order (and name)
|
sortAccountTreeByDeclaration $ -- sort by declaration order (and name)
|
||||||
mapAccounts (accountSetDeclarationInfo j) $ -- add declaration order info
|
mapAccounts (accountSetDeclarationInfo j) $ -- add declaration order info
|
||||||
accountTree "root" -- convert to an account tree
|
accountTree "root" -- convert to an account tree
|
||||||
as
|
as
|
||||||
|
|
||||||
-- | Sort each group of siblings in an account tree by declaration order, then account name.
|
-- | Sort each group of siblings in an account tree by declaration order, then account name.
|
||||||
-- So each group will contain first the declared accounts,
|
-- So each group will contain first the declared accounts,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user