From 7fe58f13460e7130e932bf74335f3e70231fab7e Mon Sep 17 00:00:00 2001 From: Stephen Morgan Date: Wed, 3 Mar 2021 15:57:22 +1100 Subject: [PATCH] lib: More efficiently check whether Amounts are or look zero. Comparing two Quantity (either with (==) or compare) does a lot of normalisation (calling roundMax) which is unnecessary if we're comparing to zero. Do things more directly to save work. For reg -f examples/10000x10000x10.journal, this results in - A 12% reduction in heap allocations, from 70GB to 62GB - A 14% reduction in (profiled) time, from 79s to 70s Results for bal -f examples/10000x10000x10.journal are of the same order of magnitude. --- hledger-lib/Hledger/Data/Amount.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hledger-lib/Hledger/Data/Amount.hs b/hledger-lib/Hledger/Data/Amount.hs index bd911db9b..f2bed321b 100644 --- a/hledger-lib/Hledger/Data/Amount.hs +++ b/hledger-lib/Hledger/Data/Amount.hs @@ -323,11 +323,15 @@ testAmountAndTotalPrice f amt = case aprice amt of -- | Do this Amount and (and its total price, if it has one) appear to be zero when rendered with its -- display precision ? amountLooksZero :: Amount -> Bool -amountLooksZero = testAmountAndTotalPrice ((0==) . amountRoundedQuantity) +amountLooksZero = testAmountAndTotalPrice looksZero + where + looksZero Amount{aquantity=Decimal e q, astyle=AmountStyle{asprecision=p}} = case p of + Precision d -> if e > d then abs q <= 5*10^(e-d-1) else q == 0 + NaturalPrecision -> q == 0 -- | Is this Amount (and its total price, if it has one) exactly zero, ignoring its display precision ? amountIsZero :: Amount -> Bool -amountIsZero = testAmountAndTotalPrice ((0==) . aquantity) +amountIsZero = testAmountAndTotalPrice (\Amount{aquantity=Decimal _ q} -> q == 0) -- | Set an amount's display precision, flipped. withPrecision :: Amount -> AmountPrecision -> Amount