lib: Consume list immediately in commodityStylesFromAmounts.
This reduced the maximum heap size per thread from ~850K to ~430K in a real-world register test.
This commit is contained in:
parent
150cf3f862
commit
a65ef7cd19
@ -92,6 +92,7 @@ module Hledger.Data.Journal (
|
|||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Control.Applicative ((<|>))
|
||||||
import Control.Monad.Except (ExceptT(..), runExceptT, throwError)
|
import Control.Monad.Except (ExceptT(..), runExceptT, throwError)
|
||||||
import "extra" Control.Monad.Extra (whenM)
|
import "extra" Control.Monad.Extra (whenM)
|
||||||
import Control.Monad.Reader as R
|
import Control.Monad.Reader as R
|
||||||
@ -102,9 +103,9 @@ import Data.Default (Default(..))
|
|||||||
import Data.Function ((&))
|
import Data.Function ((&))
|
||||||
import qualified Data.HashTable.Class as H (toList)
|
import qualified Data.HashTable.Class as H (toList)
|
||||||
import qualified Data.HashTable.ST.Cuckoo as H
|
import qualified Data.HashTable.ST.Cuckoo as H
|
||||||
import Data.List (find, sortOn)
|
import Data.List (find, foldl', sortOn)
|
||||||
import Data.List.Extra (groupSort, nubSort)
|
import Data.List.Extra (nubSort)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map.Strict as M
|
||||||
import Data.Maybe (catMaybes, fromJust, fromMaybe, isJust, mapMaybe)
|
import Data.Maybe (catMaybes, fromJust, fromMaybe, isJust, mapMaybe)
|
||||||
#if !(MIN_VERSION_base(4,11,0))
|
#if !(MIN_VERSION_base(4,11,0))
|
||||||
import Data.Semigroup (Semigroup(..))
|
import Data.Semigroup (Semigroup(..))
|
||||||
@ -1109,42 +1110,40 @@ journalInferCommodityStyles j =
|
|||||||
-- and this function never reports an error.
|
-- and this function never reports an error.
|
||||||
--
|
--
|
||||||
commodityStylesFromAmounts :: [Amount] -> Either String (M.Map CommoditySymbol AmountStyle)
|
commodityStylesFromAmounts :: [Amount] -> Either String (M.Map CommoditySymbol AmountStyle)
|
||||||
commodityStylesFromAmounts amts =
|
commodityStylesFromAmounts =
|
||||||
Right $ M.fromList commstyles
|
Right . foldr (\a -> M.insertWith canonicalStyle (acommodity a) (astyle a)) mempty
|
||||||
where
|
|
||||||
commamts = groupSort [(acommodity as, as) | as <- amts]
|
-- | Given a list of amount styles (assumed to be from parsed amounts
|
||||||
commstyles = [(c, canonicalStyleFrom $ map astyle as) | (c,as) <- commamts]
|
-- in a single commodity), in parse order, choose a canonical style.
|
||||||
|
canonicalStyleFrom :: [AmountStyle] -> AmountStyle
|
||||||
|
-- canonicalStyleFrom [] = amountstyle
|
||||||
|
canonicalStyleFrom ss = foldl' canonicalStyle amountstyle ss
|
||||||
|
|
||||||
-- TODO: should probably detect and report inconsistencies here.
|
-- TODO: should probably detect and report inconsistencies here.
|
||||||
-- Though, we don't have the info for a good error message, so maybe elsewhere.
|
-- Though, we don't have the info for a good error message, so maybe elsewhere.
|
||||||
-- | Given a list of amount styles (assumed to be from parsed amounts
|
-- | Given a pair of AmountStyles, choose a canonical style.
|
||||||
-- in a single commodity), in parse order, choose a canonical style.
|
|
||||||
-- This is:
|
-- This is:
|
||||||
-- the general style of the first amount,
|
-- the general style of the first amount,
|
||||||
-- with the first digit group style seen,
|
-- with the first digit group style seen,
|
||||||
-- with the maximum precision of all.
|
-- with the maximum precision of all.
|
||||||
--
|
canonicalStyle :: AmountStyle -> AmountStyle -> AmountStyle
|
||||||
canonicalStyleFrom :: [AmountStyle] -> AmountStyle
|
canonicalStyle a b = a{asprecision=prec, asdecimalpoint=decmark, asdigitgroups=mgrps}
|
||||||
canonicalStyleFrom [] = amountstyle
|
|
||||||
canonicalStyleFrom ss@(s:_) =
|
|
||||||
s{asprecision=prec, asdecimalpoint=Just decmark, asdigitgroups=mgrps}
|
|
||||||
where
|
where
|
||||||
-- precision is maximum of all precisions
|
-- precision is maximum of all precisions
|
||||||
prec = maximumStrict $ map asprecision ss
|
prec = max (asprecision a) (asprecision b)
|
||||||
-- identify the digit group mark (& group sizes)
|
-- identify the digit group mark (& group sizes)
|
||||||
mgrps = headMay $ mapMaybe asdigitgroups ss
|
mgrps = asdigitgroups a <|> asdigitgroups b
|
||||||
-- if a digit group mark was identified above, we can rely on that;
|
-- if a digit group mark was identified above, we can rely on that;
|
||||||
-- make sure the decimal mark is different. If not, default to period.
|
-- make sure the decimal mark is different. If not, default to period.
|
||||||
defdecmark =
|
defdecmark = case mgrps of
|
||||||
case mgrps of
|
|
||||||
Just (DigitGroups '.' _) -> ','
|
Just (DigitGroups '.' _) -> ','
|
||||||
_ -> '.'
|
_ -> '.'
|
||||||
-- identify the decimal mark: the first one used, or the above default,
|
-- identify the decimal mark: the first one used, or the above default,
|
||||||
-- but never the same character as the digit group mark.
|
-- but never the same character as the digit group mark.
|
||||||
-- urgh.. refactor..
|
-- urgh.. refactor..
|
||||||
decmark = case mgrps of
|
decmark = case mgrps of
|
||||||
Just _ -> defdecmark
|
Just _ -> Just defdecmark
|
||||||
_ -> headDef defdecmark $ mapMaybe asdecimalpoint ss
|
Nothing -> asdecimalpoint a <|> asdecimalpoint b <|> Just defdecmark
|
||||||
|
|
||||||
-- -- | Apply this journal's historical price records to unpriced amounts where possible.
|
-- -- | Apply this journal's historical price records to unpriced amounts where possible.
|
||||||
-- journalApplyPriceDirectives :: Journal -> Journal
|
-- journalApplyPriceDirectives :: Journal -> Journal
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user