%---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %---------------------------------------------------------------------------% % Copyright (C) 2001, 2005-2008, 2010 The University of Melbourne. % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %---------------------------------------------------------------------------% % % File: top_procs.m. % Author: zs. % % This module contains code to find the top procedures by several criteria. % % For comparisons on costs, we sort highest first. For comparisons on names and % contexts, we sort lowest first. This is consistently what users want. % %---------------------------------------------------------------------------% :- module top_procs. :- interface. :- import_module measurements. :- import_module profile. :- import_module query. :- import_module list. :- import_module maybe. %---------------------------------------------------------------------------% :- func find_top_procs(cost_kind, include_descendants, measurement_scope, display_limit, deep) = maybe_error(list(int)). % A line group consists of a first line, and optionally a group of later % lines. The first line is structured as a sequence of fields, which may % have one or two id fields but must have all the measurement fields % demanded by the current preferences. The later lines must all be full % rows. % :- type line_group(FL, LL) ---> line_group( group_filename :: string, group_linenumber :: int, group_name :: string, group_own :: own_prof_info, group_desc :: inherit_prof_info, group_first_line_id :: string, group_later_lines :: LL ). :- func sort_line_groups(order_criteria, list(line_group(FL, LL))) = list(line_group(FL, LL)). :- pred sum_line_group_measurements(list(line_group(FL, LL))::in, own_prof_info::out, inherit_prof_info::out) is det. %---------------------------------------------------------------------------% %---------------------------------------------------------------------------% :- implementation. :- import_module array. :- import_module bool. :- import_module float. :- import_module int. %---------------------------------------------------------------------------% find_top_procs(Sort, InclDesc, Scope, Limit, Deep) = MaybeTopPSIs :- find_top_sort_predicate(Sort, InclDesc, Scope, SortCompatible, RawSortFunc, FilterPred), ( SortCompatible = no, MaybeTopPSIs = error("bad sort specification") ; SortCompatible = yes, ProcStatics = Deep ^ proc_statics, array.max(ProcStatics, MaxProcStatic), PSIs0 = 1 .. MaxProcStatic, deep_lookup_proc_dynamics(Deep, Deep ^ root, RootPD), RootPD ^ pd_proc_static = proc_static_ptr(RootPSI), list.filter(filter_top_procs(Deep, RootPSI, FilterPred), PSIs0, PSIs), SortPred = (pred(PSI1::in, PSI2::in, ComparisonResult::out) is det :- ComparisonResult = compare_procs_fallback(RawSortFunc, Deep, PSI1, PSI2) ), list.sort(SortPred, PSIs, DescendingPSIs), ( Limit = rank_range(First, Last), ( if list.drop(First - 1, DescendingPSIs, RemainingPSIs) then list.take_upto(Last - First + 1, RemainingPSIs, TopPSIs), MaybeTopPSIs = ok(TopPSIs) else MaybeTopPSIs = ok([]) ) ; Limit = threshold_percent(Threshold), find_threshold_percent_predicate(Sort, InclDesc, ThresholdCompatible, RawThresholdPred), ( ThresholdCompatible = no, MaybeTopPSIs = error("bad threshold specification") ; ThresholdCompatible = yes, ThresholdPred = (pred(PSI::in) is semidet :- RawThresholdPred(Deep, Threshold, PSI) ), list.take_while(ThresholdPred, DescendingPSIs, TopPSIs), MaybeTopPSIs = ok(TopPSIs) ) ; Limit = threshold_value(Threshold), find_threshold_value_predicate(Sort, InclDesc, ThresholdCompatible, RawThresholdPred), ( ThresholdCompatible = no, MaybeTopPSIs = error("bad threshold specification") ; ThresholdCompatible = yes, ThresholdPred = (pred(PSI::in) is semidet :- RawThresholdPred(Deep, Threshold, PSI) ), list.take_while(ThresholdPred, DescendingPSIs, TopPSIs), MaybeTopPSIs = ok(TopPSIs) ) ) ). %---------------------------------------------------------------------------% :- type compare_proc_statics == (func(deep, int, int) = comparison_result). :- func compare_procs_fallback(compare_proc_statics, deep, int, int) = comparison_result. compare_procs_fallback(MainFunc, Deep, PSI1, PSI2) = Result :- Result0 = MainFunc(Deep, PSI1, PSI2), ( Result0 = (=), Result1 = compare_ps_time_both_overall(Deep, PSI1, PSI2), ( Result1 = (=), Result = compare_ps_words_both_overall(Deep, PSI1, PSI2) ; ( Result1 = (<) ; Result1 = (>) ), Result = Result1 ) ; ( Result0 = (<) ; Result0 = (>) ), Result = Result0 ). %---------------------------------------------------------------------------% :- pred filter_top_procs(deep::in, int::in, pred(deep, int)::in(pred(in, in) is semidet), int::in) is semidet. filter_top_procs(Deep, RootPSI, FilterPred, PSI) :- PSI \= RootPSI, FilterPred(Deep, PSI). :- pred find_top_sort_predicate(cost_kind::in, include_descendants::in, measurement_scope::in, bool::out, compare_proc_statics::out(func(in, in, in) = out is det), pred(deep, int)::out(pred(in, in) is semidet)) is det. find_top_sort_predicate(cost_calls, self, overall, yes, compare_ps_calls_self_overall, filter_ps_calls_self). find_top_sort_predicate(cost_calls, self, per_call, no, compare_ps_calls_self_overall, filter_ps_calls_self). find_top_sort_predicate(cost_calls, self_and_desc, overall, no, compare_ps_calls_self_overall, filter_ps_calls_self). find_top_sort_predicate(cost_calls, self_and_desc, per_call, no, compare_ps_calls_self_overall, filter_ps_calls_self). find_top_sort_predicate(cost_redos, self, overall, yes, compare_ps_redos_self_overall, filter_ps_redos_self). find_top_sort_predicate(cost_redos, self, per_call, no, compare_ps_redos_self_overall, filter_ps_redos_self). find_top_sort_predicate(cost_redos, self_and_desc, overall, no, compare_ps_redos_self_overall, filter_ps_redos_self). find_top_sort_predicate(cost_redos, self_and_desc, per_call, no, compare_ps_redos_self_overall, filter_ps_redos_self). find_top_sort_predicate(cost_time, self, overall, yes, compare_ps_time_self_overall, filter_ps_time_self). find_top_sort_predicate(cost_time, self, per_call, yes, compare_ps_time_self_percall, filter_ps_time_self). find_top_sort_predicate(cost_time, self_and_desc, overall, yes, compare_ps_time_both_overall, filter_ps_time_both). find_top_sort_predicate(cost_time, self_and_desc, per_call, yes, compare_ps_time_both_percall, filter_ps_time_both). find_top_sort_predicate(cost_callseqs, self, overall, yes, compare_ps_callseqs_self_overall, filter_ps_callseqs_self). find_top_sort_predicate(cost_callseqs, self, per_call, yes, compare_ps_callseqs_self_percall, filter_ps_callseqs_self). find_top_sort_predicate(cost_callseqs, self_and_desc, overall, yes, compare_ps_callseqs_both_overall, filter_ps_callseqs_both). find_top_sort_predicate(cost_callseqs, self_and_desc, per_call, yes, compare_ps_callseqs_both_percall, filter_ps_callseqs_both). find_top_sort_predicate(cost_allocs, self, overall, yes, compare_ps_allocs_self_overall, filter_ps_allocs_self). find_top_sort_predicate(cost_allocs, self, per_call, yes, compare_ps_allocs_self_percall, filter_ps_allocs_self). find_top_sort_predicate(cost_allocs, self_and_desc, overall, yes, compare_ps_allocs_both_overall, filter_ps_allocs_both). find_top_sort_predicate(cost_allocs, self_and_desc, per_call, yes, compare_ps_allocs_both_percall, filter_ps_allocs_both). find_top_sort_predicate(cost_words, self, overall, yes, compare_ps_words_self_overall, filter_ps_words_self). find_top_sort_predicate(cost_words, self, per_call, yes, compare_ps_words_self_percall, filter_ps_words_self). find_top_sort_predicate(cost_words, self_and_desc, overall, yes, compare_ps_words_both_overall, filter_ps_words_both). find_top_sort_predicate(cost_words, self_and_desc, per_call, yes, compare_ps_words_both_percall, filter_ps_words_both). :- pred find_threshold_percent_predicate(cost_kind::in, include_descendants::in, bool::out, pred(deep, float, int)::out(pred(in, in, in) is semidet)) is det. find_threshold_percent_predicate(cost_calls, self, no, threshold_percent_ps_time_self). find_threshold_percent_predicate(cost_calls, self_and_desc, no, threshold_percent_ps_time_self). find_threshold_percent_predicate(cost_redos, self, no, threshold_percent_ps_time_self). find_threshold_percent_predicate(cost_redos, self_and_desc, no, threshold_percent_ps_time_self). find_threshold_percent_predicate(cost_time, self, yes, threshold_percent_ps_time_self). find_threshold_percent_predicate(cost_time, self_and_desc, yes, threshold_percent_ps_time_both). find_threshold_percent_predicate(cost_callseqs, self, yes, threshold_percent_ps_callseqs_self). find_threshold_percent_predicate(cost_callseqs, self_and_desc, yes, threshold_percent_ps_callseqs_both). find_threshold_percent_predicate(cost_allocs, self, yes, threshold_percent_ps_allocs_self). find_threshold_percent_predicate(cost_allocs, self_and_desc, yes, threshold_percent_ps_allocs_both). find_threshold_percent_predicate(cost_words, self, yes, threshold_percent_ps_words_self). find_threshold_percent_predicate(cost_words, self_and_desc, yes, threshold_percent_ps_words_both). :- pred find_threshold_value_predicate(cost_kind::in, include_descendants::in, bool::out, pred(deep, float, int)::out(pred(in, in, in) is semidet)) is det. find_threshold_value_predicate(cost_calls, self, no, threshold_value_ps_time_self). find_threshold_value_predicate(cost_calls, self_and_desc, no, threshold_value_ps_time_self). find_threshold_value_predicate(cost_redos, self, no, threshold_value_ps_time_self). find_threshold_value_predicate(cost_redos, self_and_desc, no, threshold_value_ps_time_self). find_threshold_value_predicate(cost_time, self, yes, threshold_value_ps_time_self). find_threshold_value_predicate(cost_time, self_and_desc, yes, threshold_value_ps_time_both). find_threshold_value_predicate(cost_callseqs, self, yes, threshold_value_ps_callseqs_self). find_threshold_value_predicate(cost_callseqs, self_and_desc, yes, threshold_value_ps_callseqs_both). find_threshold_value_predicate(cost_allocs, self, yes, threshold_value_ps_allocs_self). find_threshold_value_predicate(cost_allocs, self_and_desc, yes, threshold_value_ps_allocs_both). find_threshold_value_predicate(cost_words, self, yes, threshold_value_ps_words_self). find_threshold_value_predicate(cost_words, self_and_desc, yes, threshold_value_ps_words_both). %---------------------------------------------------------------------------% :- func compare_ps_calls_self_overall(deep, int, int) = comparison_result. compare_ps_calls_self_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), OwnCalls1 = calls(Own1), OwnCalls2 = calls(Own2), compare(Result, OwnCalls2, OwnCalls1). :- func compare_ps_redos_self_overall(deep, int, int) = comparison_result. compare_ps_redos_self_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), OwnRedos1 = redos(Own1), OwnRedos2 = redos(Own2), compare(Result, OwnRedos2, OwnRedos1). :- func compare_ps_time_self_overall(deep, int, int) = comparison_result. compare_ps_time_self_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), OwnQuanta1 = quanta(Own1), OwnQuanta2 = quanta(Own2), compare(Result, OwnQuanta2, OwnQuanta1). :- func compare_ps_time_self_percall(deep, int, int) = comparison_result. compare_ps_time_self_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnQuanta1 = quanta(Own1), OwnQuanta2 = quanta(Own2), OwnQuantaPerCall1 = float(OwnQuanta1) / float(Calls1), OwnQuantaPerCall2 = float(OwnQuanta2) / float(Calls2), compare(Result, OwnQuantaPerCall2, OwnQuantaPerCall1). :- func compare_ps_time_both_overall(deep, int, int) = comparison_result. compare_ps_time_both_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), OwnQuanta1 = quanta(Own1), OwnQuanta2 = quanta(Own2), DescQuanta1 = inherit_quanta(Desc1), DescQuanta2 = inherit_quanta(Desc2), TotalQuanta1 = OwnQuanta1 + DescQuanta1, TotalQuanta2 = OwnQuanta2 + DescQuanta2, compare(Result, TotalQuanta2, TotalQuanta1). :- func compare_ps_time_both_percall(deep, int, int) = comparison_result. compare_ps_time_both_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnQuanta1 = quanta(Own1), OwnQuanta2 = quanta(Own2), DescQuanta1 = inherit_quanta(Desc1), DescQuanta2 = inherit_quanta(Desc2), TotalQuanta1 = OwnQuanta1 + DescQuanta1, TotalQuanta2 = OwnQuanta2 + DescQuanta2, TotalQuantaPerCall1 = float(TotalQuanta1) / float(Calls1), TotalQuantaPerCall2 = float(TotalQuanta2) / float(Calls2), compare(Result, TotalQuantaPerCall2, TotalQuantaPerCall1). :- func compare_ps_callseqs_self_overall(deep, int, int) = comparison_result. compare_ps_callseqs_self_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), OwnCallSeqs1 = callseqs(Own1), OwnCallSeqs2 = callseqs(Own2), compare(Result, OwnCallSeqs2, OwnCallSeqs1). :- func compare_ps_callseqs_self_percall(deep, int, int) = comparison_result. compare_ps_callseqs_self_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnCallSeqs1 = callseqs(Own1), OwnCallSeqs2 = callseqs(Own2), OwnCallSeqsPerCall1 = float(OwnCallSeqs1) / float(Calls1), OwnCallSeqsPerCall2 = float(OwnCallSeqs2) / float(Calls2), compare(Result, OwnCallSeqsPerCall2, OwnCallSeqsPerCall1). :- func compare_ps_callseqs_both_overall(deep, int, int) = comparison_result. compare_ps_callseqs_both_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), OwnCallSeqs1 = callseqs(Own1), OwnCallSeqs2 = callseqs(Own2), DescCallSeqs1 = inherit_callseqs(Desc1), DescCallSeqs2 = inherit_callseqs(Desc2), TotalCallSeqs1 = OwnCallSeqs1 + DescCallSeqs1, TotalCallSeqs2 = OwnCallSeqs2 + DescCallSeqs2, compare(Result, TotalCallSeqs2, TotalCallSeqs1). :- func compare_ps_callseqs_both_percall(deep, int, int) = comparison_result. compare_ps_callseqs_both_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnCallSeqs1 = callseqs(Own1), OwnCallSeqs2 = callseqs(Own2), DescCallSeqs1 = inherit_callseqs(Desc1), DescCallSeqs2 = inherit_callseqs(Desc2), TotalCallSeqs1 = OwnCallSeqs1 + DescCallSeqs1, TotalCallSeqs2 = OwnCallSeqs2 + DescCallSeqs2, TotalCallSeqsPerCall1 = float(TotalCallSeqs1) / float(Calls1), TotalCallSeqsPerCall2 = float(TotalCallSeqs2) / float(Calls2), compare(Result, TotalCallSeqsPerCall2, TotalCallSeqsPerCall1). :- func compare_ps_allocs_self_overall(deep, int, int) = comparison_result. compare_ps_allocs_self_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), OwnAlloc1 = allocs(Own1), OwnAlloc2 = allocs(Own2), compare(Result, OwnAlloc2, OwnAlloc1). :- func compare_ps_allocs_self_percall(deep, int, int) = comparison_result. compare_ps_allocs_self_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnAlloc1 = allocs(Own1), OwnAlloc2 = allocs(Own2), OwnAllocPerCall1 = float(OwnAlloc1) / float(Calls1), OwnAllocPerCall2 = float(OwnAlloc2) / float(Calls2), compare(Result, OwnAllocPerCall2, OwnAllocPerCall1). :- func compare_ps_allocs_both_overall(deep, int, int) = comparison_result. compare_ps_allocs_both_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), OwnAlloc1 = allocs(Own1), OwnAlloc2 = allocs(Own2), DescAlloc1 = inherit_allocs(Desc1), DescAlloc2 = inherit_allocs(Desc2), TotalAlloc1 = OwnAlloc1 + DescAlloc1, TotalAlloc2 = OwnAlloc2 + DescAlloc2, compare(Result, TotalAlloc2, TotalAlloc1). :- func compare_ps_allocs_both_percall(deep, int, int) = comparison_result. compare_ps_allocs_both_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnAlloc1 = allocs(Own1), OwnAlloc2 = allocs(Own2), DescAlloc1 = inherit_allocs(Desc1), DescAlloc2 = inherit_allocs(Desc2), TotalAlloc1 = OwnAlloc1 + DescAlloc1, TotalAlloc2 = OwnAlloc2 + DescAlloc2, TotalAllocPerCall1 = float(TotalAlloc1) / float(Calls1), TotalAllocPerCall2 = float(TotalAlloc2) / float(Calls2), compare(Result, TotalAllocPerCall2, TotalAllocPerCall1). :- func compare_ps_words_self_overall(deep, int, int) = comparison_result. compare_ps_words_self_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), OwnWords1 = words(Own1), OwnWords2 = words(Own2), compare(Result, OwnWords2, OwnWords1). :- func compare_ps_words_self_percall(deep, int, int) = comparison_result. compare_ps_words_self_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnWords1 = words(Own1), OwnWords2 = words(Own2), OwnWordsPerCall1 = float(OwnWords1) / float(Calls1), OwnWordsPerCall2 = float(OwnWords2) / float(Calls2), compare(Result, OwnWordsPerCall2, OwnWordsPerCall1). :- func compare_ps_words_both_overall(deep, int, int) = comparison_result. compare_ps_words_both_overall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), OwnWords1 = words(Own1), OwnWords2 = words(Own2), DescWords1 = inherit_words(Desc1), DescWords2 = inherit_words(Desc2), TotalWords1 = OwnWords1 + DescWords1, TotalWords2 = OwnWords2 + DescWords2, compare(Result, TotalWords2, TotalWords1). :- func compare_ps_words_both_percall(deep, int, int) = comparison_result. compare_ps_words_both_percall(Deep, PSI1, PSI2) = Result :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSOwn, PSI2, Own2), array.lookup(PSDesc, PSI1, Desc1), array.lookup(PSDesc, PSI2, Desc2), Calls1 = calls(Own1), Calls2 = calls(Own2), OwnWords1 = words(Own1), OwnWords2 = words(Own2), DescWords1 = inherit_words(Desc1), DescWords2 = inherit_words(Desc2), TotalWords1 = OwnWords1 + DescWords1, TotalWords2 = OwnWords2 + DescWords2, TotalWordsPerCall1 = float(TotalWords1) / float(Calls1), TotalWordsPerCall2 = float(TotalWords2) / float(Calls2), compare(Result, TotalWordsPerCall2, TotalWordsPerCall1). %---------------------------------------------------------------------------% :- pred filter_ps_calls_self(deep::in, int::in) is semidet. filter_ps_calls_self(Deep, PSI1) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), OwnCalls1 = calls(Own1), OwnCalls1 > 0. :- pred filter_ps_redos_self(deep::in, int::in) is semidet. filter_ps_redos_self(Deep, PSI1) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), OwnCalls1 = redos(Own1), OwnCalls1 > 0. :- pred filter_ps_time_self(deep::in, int::in) is semidet. filter_ps_time_self(Deep, PSI1) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), OwnQuanta1 = quanta(Own1), OwnQuanta1 > 0. :- pred filter_ps_time_both(deep::in, int::in) is semidet. filter_ps_time_both(Deep, PSI1) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSDesc, PSI1, Desc1), OwnQuanta1 = quanta(Own1), DescQuanta1 = inherit_quanta(Desc1), TotalQuanta1 = OwnQuanta1 + DescQuanta1, TotalQuanta1 > 0. :- pred filter_ps_callseqs_self(deep::in, int::in) is semidet. filter_ps_callseqs_self(Deep, PSI1) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), OwnCallSeqs1 = callseqs(Own1), OwnCallSeqs1 > 0. :- pred filter_ps_callseqs_both(deep::in, int::in) is semidet. filter_ps_callseqs_both(Deep, PSI1) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSDesc, PSI1, Desc1), OwnCallSeqs1 = callseqs(Own1), DescCallSeqs1 = inherit_callseqs(Desc1), TotalCallSeqs1 = OwnCallSeqs1 + DescCallSeqs1, TotalCallSeqs1 > 0. :- pred filter_ps_allocs_self(deep::in, int::in) is semidet. filter_ps_allocs_self(Deep, PSI1) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), OwnAlloc1 = allocs(Own1), OwnAlloc1 > 0. :- pred filter_ps_allocs_both(deep::in, int::in) is semidet. filter_ps_allocs_both(Deep, PSI1) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSDesc, PSI1, Desc1), OwnAlloc1 = allocs(Own1), DescAlloc1 = inherit_allocs(Desc1), TotalAlloc1 = OwnAlloc1 + DescAlloc1, TotalAlloc1 > 0. :- pred filter_ps_words_self(deep::in, int::in) is semidet. filter_ps_words_self(Deep, PSI1) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI1, Own1), OwnWords1 = words(Own1), OwnWords1 > 0. :- pred filter_ps_words_both(deep::in, int::in) is semidet. filter_ps_words_both(Deep, PSI1) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI1, Own1), array.lookup(PSDesc, PSI1, Desc1), OwnWords1 = words(Own1), DescWords1 = inherit_words(Desc1), TotalWords1 = OwnWords1 + DescWords1, TotalWords1 > 0. %---------------------------------------------------------------------------% :- pred threshold_value_ps_time_self(deep::in, float::in, int::in) is semidet. threshold_value_ps_time_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), OwnQuanta = quanta(Own), float(OwnQuanta) > Threshold. :- pred threshold_value_ps_time_both(deep::in, float::in, int::in) is semidet. threshold_value_ps_time_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), OwnQuanta = quanta(Own), DescQuanta = inherit_quanta(Desc), TotalQuanta = OwnQuanta + DescQuanta, float(TotalQuanta) > Threshold. :- pred threshold_value_ps_callseqs_self(deep::in, float::in, int::in) is semidet. threshold_value_ps_callseqs_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), OwnCallSeqs = callseqs(Own), float(OwnCallSeqs) > Threshold. :- pred threshold_value_ps_callseqs_both(deep::in, float::in, int::in) is semidet. threshold_value_ps_callseqs_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), OwnCallSeqs = callseqs(Own), DescCallSeqs = inherit_callseqs(Desc), TotalCallSeqs = OwnCallSeqs + DescCallSeqs, float(TotalCallSeqs) > Threshold. :- pred threshold_value_ps_allocs_self(deep::in, float::in, int::in) is semidet. threshold_value_ps_allocs_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), OwnAlloc = allocs(Own), float(OwnAlloc) > Threshold. :- pred threshold_value_ps_allocs_both(deep::in, float::in, int::in) is semidet. threshold_value_ps_allocs_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), OwnAlloc = allocs(Own), DescAlloc = inherit_allocs(Desc), TotalAlloc = OwnAlloc + DescAlloc, float(TotalAlloc) > Threshold. :- pred threshold_value_ps_words_self(deep::in, float::in, int::in) is semidet. threshold_value_ps_words_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), OwnWords = words(Own), float(OwnWords) > Threshold. :- pred threshold_value_ps_words_both(deep::in, float::in, int::in) is semidet. threshold_value_ps_words_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), OwnWords = words(Own), DescWords = inherit_words(Desc), TotalWords = OwnWords + DescWords, float(TotalWords) > Threshold. %---------------------------------------------------------------------------% :- pred threshold_percent_ps_time_self(deep::in, float::in, int::in) is semidet. threshold_percent_ps_time_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnQuanta = quanta(Own), RootOwnQuanta = quanta(RootOwn), RootDescQuanta = inherit_quanta(RootDesc), RootTotalQuanta = RootOwnQuanta + RootDescQuanta, 100.0 * float(OwnQuanta) > Threshold * float(RootTotalQuanta). :- pred threshold_percent_ps_time_both(deep::in, float::in, int::in) is semidet. threshold_percent_ps_time_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnQuanta = quanta(Own), RootOwnQuanta = quanta(RootOwn), DescQuanta = inherit_quanta(Desc), RootDescQuanta = inherit_quanta(RootDesc), TotalQuanta = OwnQuanta + DescQuanta, RootTotalQuanta = RootOwnQuanta + RootDescQuanta, 100.0 * float(TotalQuanta) > Threshold * float(RootTotalQuanta). :- pred threshold_percent_ps_callseqs_self(deep::in, float::in, int::in) is semidet. threshold_percent_ps_callseqs_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnCallSeqs = callseqs(Own), RootOwnCallSeqs = callseqs(RootOwn), RootDescCallSeqs = inherit_callseqs(RootDesc), RootTotalCallSeqs = RootOwnCallSeqs + RootDescCallSeqs, 100.0 * float(OwnCallSeqs) > Threshold * float(RootTotalCallSeqs). :- pred threshold_percent_ps_callseqs_both(deep::in, float::in, int::in) is semidet. threshold_percent_ps_callseqs_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnCallSeqs = callseqs(Own), RootOwnCallSeqs = callseqs(RootOwn), DescCallSeqs = inherit_callseqs(Desc), RootDescCallSeqs = inherit_callseqs(RootDesc), TotalCallSeqs = OwnCallSeqs + DescCallSeqs, RootTotalCallSeqs = RootOwnCallSeqs + RootDescCallSeqs, 100.0 * float(TotalCallSeqs) > Threshold * float(RootTotalCallSeqs). :- pred threshold_percent_ps_allocs_self(deep::in, float::in, int::in) is semidet. threshold_percent_ps_allocs_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnAlloc = allocs(Own), RootOwnAlloc = allocs(RootOwn), RootDescAlloc = inherit_allocs(RootDesc), RootTotalAlloc = RootOwnAlloc + RootDescAlloc, 100.0 * float(OwnAlloc) > Threshold * float(RootTotalAlloc). :- pred threshold_percent_ps_allocs_both(deep::in, float::in, int::in) is semidet. threshold_percent_ps_allocs_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnAlloc = allocs(Own), RootOwnAlloc = allocs(RootOwn), DescAlloc = inherit_allocs(Desc), RootDescAlloc = inherit_allocs(RootDesc), TotalAlloc = OwnAlloc + DescAlloc, RootTotalAlloc = RootOwnAlloc + RootDescAlloc, 100.0 * float(TotalAlloc) > Threshold * float(RootTotalAlloc). :- pred threshold_percent_ps_words_self(deep::in, float::in, int::in) is semidet. threshold_percent_ps_words_self(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, array.lookup(PSOwn, PSI, Own), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnWords = words(Own), RootOwnWords = words(RootOwn), RootDescWords = inherit_words(RootDesc), RootTotalWords = RootOwnWords + RootDescWords, 100.0 * float(OwnWords) > Threshold * float(RootTotalWords). :- pred threshold_percent_ps_words_both(deep::in, float::in, int::in) is semidet. threshold_percent_ps_words_both(Deep, Threshold, PSI) :- PSOwn = Deep ^ ps_own, PSDesc = Deep ^ ps_desc, array.lookup(PSOwn, PSI, Own), array.lookup(PSDesc, PSI, Desc), RootOwn = root_own_info(Deep), RootDesc = root_desc_info(Deep), OwnWords = words(Own), RootOwnWords = words(RootOwn), DescWords = inherit_words(Desc), RootDescWords = inherit_words(RootDesc), TotalWords = OwnWords + DescWords, RootTotalWords = RootOwnWords + RootDescWords, 100.0 * float(TotalWords) > Threshold * float(RootTotalWords). %---------------------------------------------------------------------------% sort_line_groups(Criteria, Groups) = SortedGroups :- ( Criteria = by_context, CompFunc = compare_line_groups_by_context ; Criteria = by_name, CompFunc = compare_line_groups_by_name ; Criteria = by_cost(Measurement, InclDesc, Scope), ( Measurement = cost_calls, % We ignore the setting of InclDesc because calls are not % inherited from descendants, and we ignore the setting of Scope % because sorting on "calls per call" is not useful. CompFunc = compare_line_groups_by_calls ; Measurement = cost_redos, CompFunc = compare_line_groups_by_redos ; Measurement = cost_time, InclDesc = self, Scope = overall, CompFunc = compare_line_groups_by_time_self_overall ; Measurement = cost_time, InclDesc = self, Scope = per_call, CompFunc = compare_line_groups_by_time_self_percall ; Measurement = cost_time, InclDesc = self_and_desc, Scope = overall, CompFunc = compare_line_groups_by_time_total_overall ; Measurement = cost_time, InclDesc = self_and_desc, Scope = per_call, CompFunc = compare_line_groups_by_time_total_percall ; Measurement = cost_callseqs, InclDesc = self, Scope = overall, CompFunc = compare_line_groups_by_callseqs_self_overall ; Measurement = cost_callseqs, InclDesc = self, Scope = per_call, CompFunc = compare_line_groups_by_callseqs_self_percall ; Measurement = cost_callseqs, InclDesc = self_and_desc, Scope = overall, CompFunc = compare_line_groups_by_callseqs_total_overall ; Measurement = cost_callseqs, InclDesc = self_and_desc, Scope = per_call, CompFunc = compare_line_groups_by_callseqs_total_percall ; Measurement = cost_allocs, InclDesc = self, Scope = overall, CompFunc = compare_line_groups_by_allocs_self_overall ; Measurement = cost_allocs, InclDesc = self, Scope = per_call, CompFunc = compare_line_groups_by_allocs_self_percall ; Measurement = cost_allocs, InclDesc = self_and_desc, Scope = overall, CompFunc = compare_line_groups_by_allocs_total_overall ; Measurement = cost_allocs, InclDesc = self_and_desc, Scope = per_call, CompFunc = compare_line_groups_by_allocs_total_percall ; Measurement = cost_words, InclDesc = self, Scope = overall, CompFunc = compare_line_groups_by_words_self_overall ; Measurement = cost_words, InclDesc = self, Scope = per_call, CompFunc = compare_line_groups_by_words_self_percall ; Measurement = cost_words, InclDesc = self_and_desc, Scope = overall, CompFunc = compare_line_groups_by_words_total_overall ; Measurement = cost_words, InclDesc = self_and_desc, Scope = per_call, CompFunc = compare_line_groups_by_words_total_percall ) ), SortedGroups = list.sort(compare_groups_fallback(CompFunc), Groups). :- type compare_line_groups_func(FL, LL) == (func(line_group(FL, LL), line_group(FL, LL)) = comparison_result). :- func compare_groups_fallback(compare_line_groups_func(FL, LL), line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_groups_fallback(MainFunc, Group1, Group2) = Result :- Result0 = MainFunc(Group1, Group2), ( Result0 = (=), Result1 = compare_line_groups_by_context(Group1, Group2), ( Result1 = (=), Result = compare_line_groups_by_name(Group1, Group2) ; ( Result1 = (<) ; Result1 = (>) ), Result = Result1 ) ; ( Result0 = (<) ; Result0 = (>) ), Result = Result0 ). %---------------------------------------------------------------------------% :- func compare_line_groups_by_context(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_context(Group1, Group2) = Result :- compare(ResultFilenames, Group1 ^ group_filename, Group2 ^ group_filename), ( ResultFilenames = (=), compare(Result, Group1 ^ group_linenumber, Group2 ^ group_linenumber) ; ( ResultFilenames = (<) ; ResultFilenames = (>) ), Result = ResultFilenames ). :- func compare_line_groups_by_name(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_name(Group1, Group2) = Result :- compare(Result, Group1 ^ group_name, Group2 ^ group_name). :- func compare_line_groups_by_calls(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_calls(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), compare(Result, Calls2, Calls1). :- func compare_line_groups_by_redos(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_redos(Group1, Group2) = Result :- Redos1 = redos(Group1 ^ group_own), Redos2 = redos(Group2 ^ group_own), compare(Result, Redos2, Redos1). :- func compare_line_groups_by_time_self_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_time_self_overall(Group1, Group2) = Result :- Quanta1 = quanta(Group1 ^ group_own), Quanta2 = quanta(Group2 ^ group_own), compare(Result, Quanta2, Quanta1). :- func compare_line_groups_by_time_self_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_time_self_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), Quanta1 = quanta(Group1 ^ group_own), Quanta2 = quanta(Group2 ^ group_own), ( if Calls1 = 0 then QuantaPerCall1 = 0.0 else QuantaPerCall1 = float(Quanta1) / float(Calls1) ), ( if Calls2 = 0 then QuantaPerCall2 = 0.0 else QuantaPerCall2 = float(Quanta2) / float(Calls2) ), compare(Result, QuantaPerCall2, QuantaPerCall1). :- func compare_line_groups_by_time_total_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_time_total_overall(Group1, Group2) = Result :- Quanta1 = quanta(Group1 ^ group_own) + inherit_quanta(Group1 ^ group_desc), Quanta2 = quanta(Group2 ^ group_own) + inherit_quanta(Group2 ^ group_desc), compare(Result, Quanta2, Quanta1). :- func compare_line_groups_by_time_total_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_time_total_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), Quanta1 = quanta(Group1 ^ group_own) + inherit_quanta(Group1 ^ group_desc), Quanta2 = quanta(Group2 ^ group_own) + inherit_quanta(Group2 ^ group_desc), ( if Calls1 = 0 then QuantaPerCall1 = 0.0 else QuantaPerCall1 = float(Quanta1) / float(Calls1) ), ( if Calls2 = 0 then QuantaPerCall2 = 0.0 else QuantaPerCall2 = float(Quanta2) / float(Calls2) ), compare(Result, QuantaPerCall2, QuantaPerCall1). :- func compare_line_groups_by_callseqs_self_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_callseqs_self_overall(Group1, Group2) = Result :- CallSeqs1 = callseqs(Group1 ^ group_own), CallSeqs2 = callseqs(Group2 ^ group_own), compare(Result, CallSeqs2, CallSeqs1). :- func compare_line_groups_by_callseqs_self_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_callseqs_self_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), CallSeqs1 = callseqs(Group1 ^ group_own), CallSeqs2 = callseqs(Group2 ^ group_own), ( if Calls1 = 0 then CallSeqsPerCall1 = 0.0 else CallSeqsPerCall1 = float(CallSeqs1) / float(Calls1) ), ( if Calls2 = 0 then CallSeqsPerCall2 = 0.0 else CallSeqsPerCall2 = float(CallSeqs2) / float(Calls2) ), compare(Result, CallSeqsPerCall2, CallSeqsPerCall1). :- func compare_line_groups_by_callseqs_total_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_callseqs_total_overall(Group1, Group2) = Result :- CallSeqs1 = callseqs(Group1 ^ group_own) + inherit_callseqs(Group1 ^ group_desc), CallSeqs2 = callseqs(Group2 ^ group_own) + inherit_callseqs(Group2 ^ group_desc), compare(Result, CallSeqs2, CallSeqs1). :- func compare_line_groups_by_callseqs_total_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_callseqs_total_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), CallSeqs1 = callseqs(Group1 ^ group_own) + inherit_callseqs(Group1 ^ group_desc), CallSeqs2 = callseqs(Group2 ^ group_own) + inherit_callseqs(Group2 ^ group_desc), ( if Calls1 = 0 then CallSeqsPerCall1 = 0.0 else CallSeqsPerCall1 = float(CallSeqs1) / float(Calls1) ), ( if Calls2 = 0 then CallSeqsPerCall2 = 0.0 else CallSeqsPerCall2 = float(CallSeqs2) / float(Calls2) ), compare(Result, CallSeqsPerCall2, CallSeqsPerCall1). :- func compare_line_groups_by_allocs_self_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_allocs_self_overall(Group1, Group2) = Result :- Alloc1 = allocs(Group1 ^ group_own), Alloc2 = allocs(Group2 ^ group_own), compare(Result, Alloc2, Alloc1). :- func compare_line_groups_by_allocs_self_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_allocs_self_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), Alloc1 = allocs(Group1 ^ group_own), Alloc2 = allocs(Group2 ^ group_own), ( if Calls1 = 0 then AllocPerCall1 = 0.0 else AllocPerCall1 = float(Alloc1) / float(Calls1) ), ( if Calls2 = 0 then AllocPerCall2 = 0.0 else AllocPerCall2 = float(Alloc2) / float(Calls2) ), compare(Result, AllocPerCall2, AllocPerCall1). :- func compare_line_groups_by_allocs_total_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_allocs_total_overall(Group1, Group2) = Result :- Alloc1 = allocs(Group1 ^ group_own) + inherit_allocs(Group1 ^ group_desc), Alloc2 = allocs(Group2 ^ group_own) + inherit_allocs(Group2 ^ group_desc), compare(Result, Alloc2, Alloc1). :- func compare_line_groups_by_allocs_total_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_allocs_total_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), Alloc1 = allocs(Group1 ^ group_own) + inherit_allocs(Group1 ^ group_desc), Alloc2 = allocs(Group2 ^ group_own) + inherit_allocs(Group2 ^ group_desc), ( if Calls1 = 0 then AllocPerCall1 = 0.0 else AllocPerCall1 = float(Alloc1) / float(Calls1) ), ( if Calls2 = 0 then AllocPerCall2 = 0.0 else AllocPerCall2 = float(Alloc2) / float(Calls2) ), compare(Result, AllocPerCall2, AllocPerCall1). :- func compare_line_groups_by_words_self_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_words_self_overall(Group1, Group2) = Result :- Words1 = words(Group1 ^ group_own), Words2 = words(Group2 ^ group_own), compare(Result, Words2, Words1). :- func compare_line_groups_by_words_self_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_words_self_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), Words1 = words(Group1 ^ group_own), Words2 = words(Group2 ^ group_own), ( if Calls1 = 0 then WordsPerCall1 = 0.0 else WordsPerCall1 = float(Words1) / float(Calls1) ), ( if Calls2 = 0 then WordsPerCall2 = 0.0 else WordsPerCall2 = float(Words2) / float(Calls2) ), compare(Result, WordsPerCall2, WordsPerCall1). :- func compare_line_groups_by_words_total_overall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_words_total_overall(Group1, Group2) = Result :- Words1 = words(Group1 ^ group_own) + inherit_words(Group1 ^ group_desc), Words2 = words(Group2 ^ group_own) + inherit_words(Group2 ^ group_desc), compare(Result, Words2, Words1). :- func compare_line_groups_by_words_total_percall(line_group(FL, LL), line_group(FL, LL)) = comparison_result. compare_line_groups_by_words_total_percall(Group1, Group2) = Result :- Calls1 = calls(Group1 ^ group_own), Calls2 = calls(Group2 ^ group_own), Words1 = words(Group1 ^ group_own) + inherit_words(Group1 ^ group_desc), Words2 = words(Group2 ^ group_own) + inherit_words(Group2 ^ group_desc), ( if Calls1 = 0 then WordsPerCall1 = 0.0 else WordsPerCall1 = float(Words1) / float(Calls1) ), ( if Calls2 = 0 then WordsPerCall2 = 0.0 else WordsPerCall2 = float(Words2) / float(Calls2) ), compare(Result, WordsPerCall2, WordsPerCall1). %---------------------------------------------------------------------------% sum_line_group_measurements(LineGroups, Own, Desc) :- list.foldl2(accumulate_line_group_measurements, LineGroups, zero_own_prof_info, Own, zero_inherit_prof_info, Desc). :- pred accumulate_line_group_measurements(line_group(FL, LL)::in, own_prof_info::in, own_prof_info::out, inherit_prof_info::in, inherit_prof_info::out) is det. accumulate_line_group_measurements(LineGroup, Own0, Own, Desc0, Desc) :- Own = add_own_to_own(Own0, LineGroup ^ group_own), Desc = add_inherit_to_inherit(Desc0, LineGroup ^ group_desc). %---------------------------------------------------------------------------% :- end_module top_procs. %---------------------------------------------------------------------------%