fix: performance: Speed up PostingsReport when called with a large number of intervals. (#1683)
It is still very slow for large journals, but at least it doesn't run any slower for interval reports.
This commit is contained in:
		
							parent
							
								
									724c84fe50
								
							
						
					
					
						commit
						3b5262e54a
					
				| @ -21,9 +21,10 @@ module Hledger.Reports.PostingsReport ( | |||||||
| ) | ) | ||||||
| where | where | ||||||
| 
 | 
 | ||||||
| import Data.List (nub, sortOn) | import Data.List (nub, sortBy, sortOn) | ||||||
| import Data.List.Extra (nubSort) | import Data.List.Extra (nubSort) | ||||||
| import Data.Maybe (fromMaybe, isJust, isNothing) | import Data.Maybe (fromMaybe, isJust, isNothing) | ||||||
|  | import Data.Ord (comparing) | ||||||
| import Data.Text (Text) | import Data.Text (Text) | ||||||
| import Data.Time.Calendar (Day) | import Data.Time.Calendar (Day) | ||||||
| import Safe (headMay) | import Safe (headMay) | ||||||
| @ -174,10 +175,26 @@ mkpostingsReportItem showdate showdesc wd mperiod p b = | |||||||
| -- aggregated to the specified depth if any. | -- aggregated to the specified depth if any. | ||||||
| -- Each summary posting will have a non-Nothing interval end date. | -- Each summary posting will have a non-Nothing interval end date. | ||||||
| summarisePostingsByInterval :: Interval -> WhichDate -> Maybe Int -> Bool -> DateSpan -> [Posting] -> [SummaryPosting] | summarisePostingsByInterval :: Interval -> WhichDate -> Maybe Int -> Bool -> DateSpan -> [Posting] -> [SummaryPosting] | ||||||
| summarisePostingsByInterval interval wd mdepth showempty reportspan ps = concatMap summarisespan $ splitSpan interval reportspan | summarisePostingsByInterval interval wd mdepth showempty reportspan = | ||||||
|  |     concatMap (\(s,ps) -> summarisePostingsInDateSpan s wd mdepth showempty $ map snd ps) | ||||||
|  |     -- Group postings into their columns. We try to be efficient, since | ||||||
|  |     -- there can possibly be a very large number of intervals (cf #1683) | ||||||
|  |     . groupByCols colspans | ||||||
|  |     . dropWhile (beforeStart . fst) | ||||||
|  |     . sortBy (comparing fst) | ||||||
|  |     . map (\p -> (getDate p, p)) | ||||||
|   where |   where | ||||||
|     summarisespan s = summarisePostingsInDateSpan s wd mdepth showempty (postingsinspan s) |     groupByCols []     _  = [] | ||||||
|     postingsinspan s = filter (isPostingInDateSpan' wd s) ps |     groupByCols (c:cs) [] = if showempty then (c,[]) : groupByCols cs [] else [] | ||||||
|  |     groupByCols (c:cs) ps = (c, matches) : groupByCols cs later | ||||||
|  |       where (matches, later) = span ((spanEnd c >) . Just . fst) ps | ||||||
|  | 
 | ||||||
|  |     -- The date spans to be included as report columns. | ||||||
|  |     colspans = splitSpan interval reportspan | ||||||
|  |     beforeStart = maybe (const True) (>) $ spanStart =<< headMay colspans | ||||||
|  |     getDate = case wd of | ||||||
|  |         PrimaryDate   -> postingDate | ||||||
|  |         SecondaryDate -> postingDate2 | ||||||
| 
 | 
 | ||||||
| -- | Given a date span (representing a report interval) and a list of | -- | Given a date span (representing a report interval) and a list of | ||||||
| -- postings within it, aggregate the postings into one summary posting per | -- postings within it, aggregate the postings into one summary posting per | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user