mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-18 02:43:40 +00:00
In the Mercury standard library, every exported predicate or function
has (or at least *should* have) a comment that documents it, including
the meanings of its arguments. About 35-40% of these modules put `'s
(left and right quotes) around the names of the variable representing
those arguments. Some tried to do it consistently (though there were spots
with unquoted or half quoted names), while some did it only a few places.
This is inconsistent: we should either do it everywhere, or nowhere.
This diff makes it nowhere, because
- this is what the majority of the standard library modules do;
- this is what virtually all of the modules in the compiler, profiler,
deep_profiler etc directories do;
- typing all those quotes when adding new predicates in modules that
follow this convention is a pain in the ass; and because
- on many modern terminals, `' looks non-symmetrical and weird.
Likewise, the comment explaining a predicate often started with
% `predname(arguments)' returns ...
This diff deletes these quotes as well, since they add nothing useful.
This diff does leave in place quotes around code fragments, both terms
and goals, where this helps delineate the boundaries of that fragment.
973 lines
40 KiB
Mathematica
973 lines
40 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2007 The University of Melbourne.
|
|
% Copyright (C) 2014-2018 The Mercury team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: table_statistics.m.
|
|
% Author: zs.
|
|
% Stability: low.
|
|
%
|
|
% This file is automatically imported, as if via ":- use_module", into every
|
|
% module that contains a `pragma memo' that asks the compiler to create
|
|
% a predicate for returning statistics about the memo table. It defines
|
|
% the data structure that this predicate will return, and some operations
|
|
% on this data structure.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module table_statistics.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
:- type proc_table_statistics
|
|
---> proc_table_statistics(
|
|
call_table_stats :: table_stats_curr_prev,
|
|
maybe_answer_table_stats :: maybe(table_stats_curr_prev)
|
|
).
|
|
|
|
:- type table_stats_curr_prev
|
|
---> table_stats_curr_prev(
|
|
current_stats :: table_stats,
|
|
stats_at_last_call :: table_stats
|
|
).
|
|
|
|
:- type table_stats
|
|
---> table_stats(
|
|
num_lookups :: int,
|
|
num_lookups_is_dupl :: int,
|
|
step_statistics :: list(table_step_stats)
|
|
).
|
|
|
|
% The definition of this type be an enum whose implementation matches
|
|
% the type MR_TableTrieStep in runtime/mercury_tabling.h. It should also
|
|
% be kept in sync with the type table_trie_step in hlds_pred.m.
|
|
%
|
|
:- type table_step_kind
|
|
---> table_step_dummy
|
|
; table_step_int
|
|
; table_step_char
|
|
; table_step_string
|
|
; table_step_float
|
|
; table_step_enum
|
|
; table_step_foreign_enum
|
|
; table_step_general
|
|
; table_step_general_addr
|
|
; table_step_general_poly
|
|
; table_step_general_poly_addr
|
|
; table_step_typeinfo
|
|
; table_step_typeclassinfo
|
|
; table_step_promise_implied
|
|
; table_step_int8
|
|
; table_step_uint8
|
|
; table_step_int16
|
|
; table_step_uint16
|
|
; table_step_int32
|
|
; table_step_uint32
|
|
; table_step_int64
|
|
; table_step_uint64.
|
|
|
|
:- type table_step_stats
|
|
---> table_step_stats(
|
|
table_step_var_name :: string,
|
|
table_step_num_lookups :: int,
|
|
table_step_num_lookups_is_dupl :: int,
|
|
table_step_detail :: table_step_stat_details
|
|
).
|
|
|
|
:- type table_step_stat_details
|
|
---> step_stats_none
|
|
; step_stats_start(
|
|
start_num_node_allocs :: int,
|
|
start_num_node_bytes :: int
|
|
)
|
|
; step_stats_enum(
|
|
enum_num_node_allocs :: int,
|
|
enum_num_node_bytes :: int
|
|
)
|
|
; step_stats_hash(
|
|
hash_num_table_allocs :: int,
|
|
hash_num_table_bytes :: int,
|
|
hash_num_link_chunk_allocs :: int,
|
|
hash_num_link_chunk_bytes :: int,
|
|
hash_num_num_key_compares_not_dupl :: int,
|
|
hash_num_num_key_compares_dupl :: int,
|
|
hash_num_resizes :: int,
|
|
hash_resizes_num_old_entries :: int,
|
|
hash_resizes_num_new_entries :: int
|
|
)
|
|
; step_stats_du(
|
|
du_num_node_allocs :: int,
|
|
du_num_node_bytes :: int,
|
|
du_num_arg_lookups :: int,
|
|
du_num_exist_lookups :: int,
|
|
|
|
du_enum_num_node_allocs :: int,
|
|
du_enum_num_node_bytes :: int,
|
|
|
|
du_hash_num_table_allocs :: int,
|
|
du_hash_num_table_bytes :: int,
|
|
du_hash_num_link_chunk_allocs :: int,
|
|
du_hash_num_link_chunk_bytes :: int,
|
|
du_hash_num_num_key_compares_not_dupl :: int,
|
|
du_hash_num_num_key_compares_dupl :: int,
|
|
du_hash_num_resizes :: int,
|
|
du_hash_resizes_num_old_entries :: int,
|
|
du_hash_resizes_num_new_entries :: int
|
|
)
|
|
; step_stats_poly(
|
|
poly_du_num_node_allocs :: int,
|
|
poly_du_num_node_bytes :: int,
|
|
poly_du_num_arg_lookups :: int,
|
|
poly_du_num_exist_lookups :: int,
|
|
|
|
poly_enum_num_node_allocs :: int,
|
|
poly_enum_num_node_bytes :: int,
|
|
|
|
poly_hash_num_table_allocs :: int,
|
|
poly_hash_num_table_bytes :: int,
|
|
poly_hash_num_link_chunk_allocs :: int,
|
|
poly_hash_num_link_chunk_bytes :: int,
|
|
poly_hash_num_num_key_compares_not_dupl :: int,
|
|
poly_hash_num_num_key_compares_dupl :: int,
|
|
poly_hash_num_resizes :: int,
|
|
poly_hash_resizes_num_old_entries :: int,
|
|
poly_hash_resizes_num_new_entries :: int
|
|
).
|
|
|
|
:- func table_stats_difference(table_stats, table_stats) = table_stats.
|
|
|
|
:- pred write_table_stats(table_stats::in, io::di, io::uo) is det.
|
|
:- pred write_table_stats(io.text_output_stream::in, table_stats::in,
|
|
io::di, io::uo) is det.
|
|
|
|
% In grades that don't support tabling, all calls to get tabling stats
|
|
% will return these dummy statistics.
|
|
%
|
|
:- func dummy_proc_table_statistics = proc_table_statistics.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
:- interface.
|
|
|
|
% The compiler, when implementing the "statistics" attribute of a
|
|
% tabling pragma, can introduce calls to MR_get_tabling_stats.
|
|
% This means that this C function is effectively part of the interface
|
|
% of this module. However, this fact is an implementation detail
|
|
% that is of concern only to implementors, which is why we do not
|
|
% want it included in the automatically generated documentation
|
|
% of this module.
|
|
:- pragma foreign_import_module("C", table_statistics).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module bool.
|
|
:- import_module float.
|
|
:- import_module int.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
:- import_module table_builtin.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred get_tabling_stats(ml_proc_table_info::in, proc_table_statistics::out,
|
|
io::di, io::uo) is det.
|
|
:- pragma foreign_export("C", get_tabling_stats(in, out, di, uo),
|
|
"MR_get_tabling_stats").
|
|
|
|
get_tabling_stats(Info, Statistics, !IO) :-
|
|
get_proc_info_direct_fields(Info, HasAnswerTable, NumInputs, NumOutputs,
|
|
InputStepDescsPtr, OutputStepDescsPtr,
|
|
CurCallStatsPtr, PrevCallStatsPtr,
|
|
CurAnswerStatsPtr, PrevAnswerStatsPtr, !IO),
|
|
get_one_table_stats(InputStepDescsPtr, CurCallStatsPtr, NumInputs,
|
|
CurCallStats, !IO),
|
|
get_one_table_stats(InputStepDescsPtr, PrevCallStatsPtr, NumInputs,
|
|
PrevCallStats, !IO),
|
|
CallStats = table_stats_curr_prev(CurCallStats, PrevCallStats),
|
|
copy_current_stats_to_prev(CurCallStatsPtr, PrevCallStatsPtr,
|
|
NumInputs, !IO),
|
|
( if HasAnswerTable > 0 then
|
|
get_one_table_stats(OutputStepDescsPtr, CurAnswerStatsPtr, NumOutputs,
|
|
CurAnswerStats, !IO),
|
|
get_one_table_stats(OutputStepDescsPtr, PrevAnswerStatsPtr, NumOutputs,
|
|
PrevAnswerStats, !IO),
|
|
AnswerStats = table_stats_curr_prev(CurAnswerStats, PrevAnswerStats),
|
|
copy_current_stats_to_prev(CurAnswerStatsPtr, PrevAnswerStatsPtr,
|
|
NumOutputs, !IO),
|
|
MaybeAnswerStats = yes(AnswerStats)
|
|
else
|
|
MaybeAnswerStats = no
|
|
),
|
|
Statistics = proc_table_statistics(CallStats, MaybeAnswerStats).
|
|
|
|
:- type ml_table_step_desc_ptr ---> ml_table_step_desc_ptr(c_pointer).
|
|
:- pragma foreign_type("C", ml_table_step_desc_ptr, "const MR_TableStepDesc *",
|
|
[can_pass_as_mercury_type]).
|
|
|
|
:- type ml_table_stats_ptr ---> ml_table_stats_ptr(c_pointer).
|
|
:- pragma foreign_type("C", ml_table_stats_ptr, "MR_TableStats *",
|
|
[can_pass_as_mercury_type]).
|
|
|
|
:- pred get_proc_info_direct_fields(ml_proc_table_info::in,
|
|
int::out, int::out, int::out,
|
|
ml_table_step_desc_ptr::out, ml_table_step_desc_ptr::out,
|
|
ml_table_stats_ptr::out, ml_table_stats_ptr::out,
|
|
ml_table_stats_ptr::out, ml_table_stats_ptr::out, io::di, io::uo) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_proc_info_direct_fields(Info::in,
|
|
HasAnswerTable::out, NumInputs::out, NumOutputs::out,
|
|
InputStepDescsPtr::out, OutputStepDescsPtr::out,
|
|
CurCallStatsPtr::out, PrevCallStatsPtr::out,
|
|
CurAnswerStatsPtr::out, PrevAnswerStatsPtr::out,
|
|
_IO0::di, _IO::uo),
|
|
[will_not_call_mercury, promise_pure, does_not_affect_liveness],
|
|
"
|
|
HasAnswerTable = ( Info->MR_pt_has_answer_table ? 1 : 0 );
|
|
NumInputs = Info->MR_pt_num_inputs;
|
|
NumOutputs = Info->MR_pt_num_outputs;
|
|
InputStepDescsPtr = Info->MR_pt_steps_desc[MR_TABLE_CALL_TABLE];
|
|
OutputStepDescsPtr = Info->MR_pt_steps_desc[MR_TABLE_ANSWER_TABLE];
|
|
CurCallStatsPtr = &(Info->
|
|
MR_pt_stats[MR_TABLE_CALL_TABLE][MR_TABLE_STATS_CURR]);
|
|
PrevCallStatsPtr = &(Info->
|
|
MR_pt_stats[MR_TABLE_CALL_TABLE][MR_TABLE_STATS_PREV]);
|
|
CurAnswerStatsPtr = &(Info->
|
|
MR_pt_stats[MR_TABLE_ANSWER_TABLE][MR_TABLE_STATS_CURR]);
|
|
PrevAnswerStatsPtr = &(Info->
|
|
MR_pt_stats[MR_TABLE_ANSWER_TABLE][MR_TABLE_STATS_PREV]);
|
|
").
|
|
|
|
:- pred get_one_table_stats(ml_table_step_desc_ptr::in, ml_table_stats_ptr::in,
|
|
int::in, table_stats::out, io::di, io::uo) is det.
|
|
|
|
get_one_table_stats(StepDescsPtr, StatsPtr, NumSteps, Stats, !IO) :-
|
|
get_one_table_overall_stats(StatsPtr, NumLookups, NumLookupsIsDupl, !IO),
|
|
get_one_table_stats_step_loop(StepDescsPtr, StatsPtr,
|
|
0, NumSteps, [], StepStats, !IO),
|
|
Stats = table_stats(NumLookups, NumLookupsIsDupl, StepStats).
|
|
|
|
:- pred get_one_table_overall_stats(ml_table_stats_ptr::in,
|
|
int::out, int::out, io::di, io::uo) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_one_table_overall_stats(StatsPtr::in,
|
|
NumLookups::out, NumLookupsIsDupl::out, _IO0::di, _IO::uo),
|
|
[will_not_call_mercury, promise_pure, does_not_affect_liveness],
|
|
"
|
|
NumLookups = StatsPtr->MR_ts_num_lookups;
|
|
NumLookupsIsDupl = StatsPtr->MR_ts_num_lookups_is_dupl;
|
|
").
|
|
|
|
:- pred get_one_table_stats_step_loop(ml_table_step_desc_ptr::in,
|
|
ml_table_stats_ptr::in, int::in, int::in,
|
|
list(table_step_stats)::in, list(table_step_stats)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
get_one_table_stats_step_loop(StepDescsPtr, StatsPtr, CurStep, NumSteps,
|
|
!StepStats, !IO) :-
|
|
( if CurStep >= NumSteps then
|
|
true
|
|
else
|
|
get_one_table_stats_step_loop(StepDescsPtr, StatsPtr,
|
|
CurStep + 1, NumSteps, !StepStats, !IO),
|
|
get_one_table_step_stats(StepDescsPtr, StatsPtr, CurStep, StepStats,
|
|
!IO),
|
|
!:StepStats = [StepStats | !.StepStats]
|
|
).
|
|
|
|
:- pred get_one_table_step_stats(ml_table_step_desc_ptr::in,
|
|
ml_table_stats_ptr::in, int::in, table_step_stats::out, io::di, io::uo)
|
|
is det.
|
|
|
|
get_one_table_step_stats(StepDescsPtr, StatsPtr, StepNum, Stats, !IO) :-
|
|
get_one_table_step_stat_details(StepDescsPtr, StatsPtr, StepNum, VarName,
|
|
NumLookups, NumLookupsIsDupl, KindInt,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries,
|
|
EnumNodeAllocs, EnumNodeBytes,
|
|
DuNodeAllocs, DuNodeBytes, DuArgLookups, DuExistLookups,
|
|
StartAllocs, StartBytes, !IO),
|
|
( if KindInt = 0 then % MR_TABLE_STATS_DETAIL_HASH
|
|
( if
|
|
EnumNodeAllocs = 0,
|
|
EnumNodeBytes = 0,
|
|
DuNodeAllocs = 0,
|
|
DuNodeBytes = 0,
|
|
DuArgLookups = 0,
|
|
DuExistLookups = 0,
|
|
StartAllocs = 0,
|
|
StartBytes = 0
|
|
then
|
|
Details = step_stats_hash(HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries)
|
|
else
|
|
unexpected($pred, "extra counts for hash")
|
|
)
|
|
else if KindInt = 1 then % MR_TABLE_STATS_DETAIL_ENUM
|
|
( if
|
|
HashTableAllocs = 0,
|
|
HashTableBytes = 0,
|
|
HashLinkChunkAllocs = 0,
|
|
HashLinkChunkBytes = 0,
|
|
HashKeyComparesNotDupl = 0,
|
|
HashKeyComparesIsDupl = 0,
|
|
HashResizes = 0,
|
|
HashResizeOldEntries = 0,
|
|
HashResizeNewEntries = 0,
|
|
DuNodeAllocs = 0,
|
|
DuNodeBytes = 0,
|
|
DuArgLookups = 0,
|
|
DuExistLookups = 0,
|
|
StartAllocs = 0,
|
|
StartBytes = 0
|
|
then
|
|
Details = step_stats_enum(EnumNodeAllocs, EnumNodeBytes)
|
|
else
|
|
unexpected($pred, "extra counts for enum")
|
|
)
|
|
else if KindInt = 2 then % MR_TABLE_STATS_DETAIL_START
|
|
( if
|
|
HashTableAllocs = 0,
|
|
HashTableBytes = 0,
|
|
HashLinkChunkAllocs = 0,
|
|
HashLinkChunkBytes = 0,
|
|
HashKeyComparesNotDupl = 0,
|
|
HashKeyComparesIsDupl = 0,
|
|
HashResizes = 0,
|
|
HashResizeOldEntries = 0,
|
|
HashResizeNewEntries = 0,
|
|
EnumNodeAllocs = 0,
|
|
EnumNodeBytes = 0,
|
|
DuNodeAllocs = 0,
|
|
DuNodeBytes = 0,
|
|
DuArgLookups = 0,
|
|
DuExistLookups = 0
|
|
then
|
|
Details = step_stats_start(StartAllocs, StartBytes)
|
|
else
|
|
unexpected($pred, "extra counts for start")
|
|
)
|
|
else if KindInt = 3 then % MR_TABLE_STATS_DETAIL_DU
|
|
( if
|
|
StartAllocs = 0,
|
|
StartBytes = 0
|
|
then
|
|
Details = step_stats_du(DuNodeAllocs, DuNodeBytes,
|
|
DuArgLookups, DuExistLookups, EnumNodeAllocs, EnumNodeBytes,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries)
|
|
else
|
|
unexpected($pred, "extra counts for du")
|
|
)
|
|
else if KindInt = 4 then % MR_TABLE_STATS_DETAIL_POLY
|
|
( if
|
|
StartAllocs = 0,
|
|
StartBytes = 0
|
|
then
|
|
Details = step_stats_poly(DuNodeAllocs, DuNodeBytes,
|
|
DuArgLookups, DuExistLookups, EnumNodeAllocs, EnumNodeBytes,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries)
|
|
else
|
|
unexpected($pred, "extra counts for poly")
|
|
)
|
|
else if KindInt = 5 then % MR_TABLE_STATS_DETAIL_NONE
|
|
( if
|
|
HashTableAllocs = 0,
|
|
HashTableBytes = 0,
|
|
HashLinkChunkAllocs = 0,
|
|
HashKeyComparesNotDupl = 0,
|
|
HashKeyComparesIsDupl = 0,
|
|
HashResizes = 0,
|
|
HashResizeOldEntries = 0,
|
|
HashResizeNewEntries = 0,
|
|
EnumNodeAllocs = 0,
|
|
EnumNodeBytes = 0,
|
|
DuNodeAllocs = 0,
|
|
DuNodeBytes = 0,
|
|
DuArgLookups = 0,
|
|
DuExistLookups = 0,
|
|
StartAllocs = 0,
|
|
StartBytes = 0
|
|
then
|
|
Details = step_stats_none
|
|
else
|
|
unexpected($pred, "extra counts for none")
|
|
)
|
|
else
|
|
unexpected($pred, "unexpected detail kind")
|
|
),
|
|
Stats = table_step_stats(VarName, NumLookups, NumLookupsIsDupl, Details).
|
|
|
|
:- pred get_one_table_step_stat_details(ml_table_step_desc_ptr::in,
|
|
ml_table_stats_ptr::in, int::in,
|
|
string::out, int::out, int::out, int::out,
|
|
int::out, int::out, int::out, int::out, int::out, int::out,
|
|
int::out, int::out, int::out,
|
|
int::out, int::out, int::out, int::out, int::out, int::out,
|
|
int::out, int::out,
|
|
io::di, io::uo) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_one_table_step_stat_details(StepDescsPtr::in, StatsStructPtr::in,
|
|
StepNum::in, VarName::out, NumLookups::out, NumLookupsIsDupl::out,
|
|
KindInt::out,
|
|
HashTableAllocs::out, HashTableBytes::out,
|
|
HashLinkChunkAllocs::out, HashLinkChunkBytes::out,
|
|
HashKeyComparesNotDupl::out, HashKeyComparesIsDupl::out,
|
|
HashResizes::out, HashResizeOldEntries::out, HashResizeNewEntries::out,
|
|
EnumNodeAllocs::out,EnumNodeBytes::out,
|
|
DuNodeAllocs::out, DuNodeBytes::out,
|
|
DuArgLookups::out, DuExistLookups::out,
|
|
StartAllocs::out, StartBytes::out, _IO0::di, _IO::uo),
|
|
[will_not_call_mercury, promise_pure, does_not_affect_liveness],
|
|
"
|
|
const MR_TableStepStats *ptr;
|
|
|
|
ptr = &(StatsStructPtr->MR_ts_steps[StepNum]);
|
|
|
|
// The casts are to discard const.
|
|
VarName = (MR_String) (MR_Integer) StepDescsPtr[StepNum].MR_tsd_var_name;
|
|
|
|
NumLookups = ptr->MR_tss_num_lookups;
|
|
NumLookupsIsDupl = ptr->MR_tss_num_lookups_is_dupl;
|
|
|
|
KindInt = (MR_Integer) ptr->MR_tss_detail_kind;
|
|
|
|
HashTableAllocs = ptr->MR_tss_hash_num_table_allocs;
|
|
HashTableBytes = ptr->MR_tss_hash_num_table_alloc_bytes;
|
|
HashLinkChunkAllocs = ptr->MR_tss_hash_num_link_chunk_allocs;
|
|
HashLinkChunkBytes = ptr->MR_tss_hash_num_link_chunk_alloc_bytes;
|
|
HashKeyComparesNotDupl = ptr->MR_tss_hash_num_key_compares_not_dupl;
|
|
HashKeyComparesIsDupl = ptr->MR_tss_hash_num_key_compares_dupl;
|
|
HashResizes = ptr->MR_tss_hash_num_resizes;
|
|
HashResizeOldEntries = ptr->MR_tss_hash_resize_old_entries;
|
|
HashResizeNewEntries = ptr->MR_tss_hash_resize_new_entries;
|
|
|
|
EnumNodeAllocs = ptr->MR_tss_enum_num_node_allocs;
|
|
EnumNodeBytes = ptr->MR_tss_enum_num_node_alloc_bytes;
|
|
|
|
DuNodeAllocs = ptr->MR_tss_du_num_node_allocs;
|
|
DuNodeBytes = ptr->MR_tss_du_num_node_alloc_bytes;
|
|
DuArgLookups = ptr->MR_tss_du_num_arg_lookups;
|
|
DuExistLookups = ptr->MR_tss_du_num_exist_lookups;
|
|
|
|
StartAllocs = ptr->MR_tss_start_num_allocs;
|
|
StartBytes = ptr->MR_tss_start_num_alloc_bytes;
|
|
").
|
|
|
|
:- pred copy_current_stats_to_prev(ml_table_stats_ptr::in,
|
|
ml_table_stats_ptr::in, int::in, io::di, io::uo) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
copy_current_stats_to_prev(CurPtr::in, PrevPtr::in, NumSteps::in,
|
|
_IO0::di, _IO::uo),
|
|
[will_not_call_mercury, promise_pure, does_not_affect_liveness],
|
|
"
|
|
MR_TableStepStats *cur;
|
|
MR_TableStepStats *prev;
|
|
int i;
|
|
|
|
PrevPtr->MR_ts_num_lookups = CurPtr->MR_ts_num_lookups;
|
|
PrevPtr->MR_ts_num_lookups_is_dupl = CurPtr->MR_ts_num_lookups_is_dupl;
|
|
|
|
for (i = 0; i < NumSteps; i++) {
|
|
cur = &(CurPtr->MR_ts_steps[i]);
|
|
prev = &(PrevPtr->MR_ts_steps[i]);
|
|
|
|
prev->MR_tss_num_lookups =
|
|
cur->MR_tss_num_lookups;
|
|
prev->MR_tss_num_lookups_is_dupl =
|
|
cur->MR_tss_num_lookups_is_dupl;
|
|
|
|
prev->MR_tss_hash_num_table_allocs =
|
|
cur->MR_tss_hash_num_table_allocs;
|
|
prev->MR_tss_hash_num_table_alloc_bytes =
|
|
cur->MR_tss_hash_num_table_alloc_bytes;
|
|
prev->MR_tss_hash_num_link_chunk_allocs =
|
|
cur->MR_tss_hash_num_link_chunk_allocs;
|
|
prev->MR_tss_hash_num_link_chunk_alloc_bytes =
|
|
cur->MR_tss_hash_num_link_chunk_alloc_bytes;
|
|
prev->MR_tss_hash_num_key_compares_not_dupl =
|
|
cur->MR_tss_hash_num_key_compares_not_dupl;
|
|
prev->MR_tss_hash_num_key_compares_dupl =
|
|
cur->MR_tss_hash_num_key_compares_dupl;
|
|
prev->MR_tss_hash_num_resizes =
|
|
cur->MR_tss_hash_num_resizes;
|
|
prev->MR_tss_hash_resize_old_entries =
|
|
cur->MR_tss_hash_resize_old_entries;
|
|
prev->MR_tss_hash_resize_new_entries =
|
|
cur->MR_tss_hash_resize_new_entries;
|
|
|
|
prev->MR_tss_enum_num_node_allocs =
|
|
cur->MR_tss_enum_num_node_allocs;
|
|
prev->MR_tss_enum_num_node_alloc_bytes =
|
|
cur->MR_tss_enum_num_node_alloc_bytes;
|
|
|
|
prev->MR_tss_du_num_node_allocs =
|
|
cur->MR_tss_du_num_node_allocs;
|
|
prev->MR_tss_du_num_node_alloc_bytes =
|
|
cur->MR_tss_du_num_node_alloc_bytes;
|
|
prev->MR_tss_du_num_arg_lookups =
|
|
cur->MR_tss_du_num_arg_lookups;
|
|
prev->MR_tss_du_num_exist_lookups =
|
|
cur->MR_tss_du_num_exist_lookups;
|
|
|
|
prev->MR_tss_start_num_allocs =
|
|
cur->MR_tss_start_num_allocs;
|
|
prev->MR_tss_start_num_alloc_bytes =
|
|
cur->MR_tss_start_num_alloc_bytes;
|
|
}
|
|
").
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
table_stats_difference(StatsA, StatsB) = StatsDiff :-
|
|
StatsA = table_stats(LookupsA, LookupsIsDuplA, StepsA),
|
|
StatsB = table_stats(LookupsB, LookupsIsDuplB, StepsB),
|
|
|
|
LookupsDiff = LookupsA - LookupsB,
|
|
LookupsIsDuplDiff = LookupsIsDuplA - LookupsIsDuplB,
|
|
StepsDiff = table_step_stats_diff(StepsA, StepsB),
|
|
|
|
StatsDiff = table_stats(LookupsDiff, LookupsIsDuplDiff, StepsDiff).
|
|
|
|
:- func table_step_stats_diff(list(table_step_stats), list(table_step_stats))
|
|
= list(table_step_stats).
|
|
|
|
table_step_stats_diff([], []) = [].
|
|
table_step_stats_diff([_ | _], []) = func_error("mismatched table stats").
|
|
table_step_stats_diff([], [_ | _]) = func_error("mismatched table stats").
|
|
table_step_stats_diff([StepA | StepsA], [StepB | StepsB])
|
|
= [StepDiff | StepDiffs] :-
|
|
StepA = table_step_stats(VarNameA, LookupsA, LookupsIsDuplA, DetailsA),
|
|
StepB = table_step_stats(VarNameB, LookupsB, LookupsIsDuplB, DetailsB),
|
|
|
|
require(unify(VarNameA, VarNameB),
|
|
"table_step_stats_diff: mismatches in variable name"),
|
|
LookupsDiff = LookupsA - LookupsB,
|
|
LookupsIsDuplDiff = LookupsIsDuplA - LookupsIsDuplB,
|
|
( if
|
|
table_step_stats_detail_diff(DetailsA, DetailsB, DetailsDiffPrime)
|
|
then
|
|
DetailsDiff = DetailsDiffPrime
|
|
else
|
|
unexpected($pred, "mismatches in details")
|
|
),
|
|
|
|
StepDiff = table_step_stats(VarNameA, LookupsDiff, LookupsIsDuplDiff,
|
|
DetailsDiff),
|
|
StepDiffs = table_step_stats_diff(StepsA, StepsB).
|
|
|
|
:- pred table_step_stats_detail_diff(table_step_stat_details::in,
|
|
table_step_stat_details::in, table_step_stat_details::out) is semidet.
|
|
|
|
table_step_stats_detail_diff(DetailsA, DetailsB, DetailsDiff) :-
|
|
(
|
|
DetailsA = step_stats_none,
|
|
DetailsB = step_stats_none,
|
|
DetailsDiff = step_stats_none
|
|
;
|
|
DetailsA = step_stats_start(StartAllocsA, StartBytesA),
|
|
DetailsB = step_stats_start(StartAllocsB, StartBytesB),
|
|
DetailsDiff = step_stats_start(StartAllocsA - StartAllocsB,
|
|
StartBytesA - StartBytesB)
|
|
;
|
|
DetailsA = step_stats_enum(EnumNodeAllocsA, EnumNodeBytesA),
|
|
DetailsB = step_stats_enum(EnumNodeAllocsB, EnumNodeBytesB),
|
|
DetailsDiff = step_stats_enum(EnumNodeAllocsA - EnumNodeAllocsB,
|
|
EnumNodeBytesA - EnumNodeBytesB)
|
|
;
|
|
DetailsA = step_stats_hash(HashTableAllocsA, HashTableBytesA,
|
|
HashLinkChunkAllocsA, HashLinkChunkBytesA,
|
|
HashKeyComparesNotDuplA, HashKeyComparesIsDuplA,
|
|
HashResizesA, HashResizeOldEntriesA, HashResizeNewEntriesA),
|
|
DetailsB = step_stats_hash(HashTableAllocsB, HashTableBytesB,
|
|
HashLinkChunkAllocsB, HashLinkChunkBytesB,
|
|
HashKeyComparesNotDuplB, HashKeyComparesIsDuplB,
|
|
HashResizesB, HashResizeOldEntriesB, HashResizeNewEntriesB),
|
|
DetailsDiff = step_stats_hash(HashTableAllocsA - HashTableAllocsB,
|
|
HashTableBytesA - HashTableBytesB,
|
|
HashLinkChunkAllocsA - HashLinkChunkAllocsB,
|
|
HashLinkChunkBytesA - HashLinkChunkBytesB,
|
|
HashKeyComparesNotDuplA - HashKeyComparesNotDuplB,
|
|
HashKeyComparesIsDuplA - HashKeyComparesIsDuplB,
|
|
HashResizesA - HashResizesB,
|
|
HashResizeOldEntriesA - HashResizeOldEntriesB,
|
|
HashResizeNewEntriesA - HashResizeNewEntriesB)
|
|
;
|
|
DetailsA = step_stats_du(DuNodeAllocsA, DuNodeBytesA,
|
|
DuArgLookupsA, DuExistLookupsA, EnumNodeAllocsA, EnumNodeBytesA,
|
|
HashTableAllocsA, HashTableBytesA,
|
|
HashLinkChunkAllocsA, HashLinkChunkBytesA,
|
|
HashKeyComparesNotDuplA, HashKeyComparesIsDuplA,
|
|
HashResizesA, HashResizeOldEntriesA, HashResizeNewEntriesA),
|
|
DetailsB = step_stats_du(DuNodeAllocsB, DuNodeBytesB,
|
|
DuArgLookupsB, DuExistLookupsB, EnumNodeAllocsB, EnumNodeBytesB,
|
|
HashTableAllocsB, HashTableBytesB,
|
|
HashLinkChunkAllocsB, HashLinkChunkBytesB,
|
|
HashKeyComparesNotDuplB, HashKeyComparesIsDuplB,
|
|
HashResizesB, HashResizeOldEntriesB, HashResizeNewEntriesB),
|
|
DetailsDiff = step_stats_du(DuNodeAllocsA - DuNodeAllocsB,
|
|
DuNodeBytesA - DuNodeBytesB,
|
|
DuArgLookupsA - DuArgLookupsB,
|
|
DuExistLookupsA - DuExistLookupsB,
|
|
EnumNodeAllocsA - EnumNodeAllocsB,
|
|
EnumNodeBytesA - EnumNodeBytesB,
|
|
HashTableAllocsA - HashTableAllocsB,
|
|
HashTableBytesA - HashTableBytesB,
|
|
HashLinkChunkAllocsA - HashLinkChunkAllocsB,
|
|
HashLinkChunkBytesA - HashLinkChunkBytesB,
|
|
HashKeyComparesNotDuplA - HashKeyComparesNotDuplB,
|
|
HashKeyComparesIsDuplA - HashKeyComparesIsDuplB,
|
|
HashResizesA - HashResizesB,
|
|
HashResizeOldEntriesA - HashResizeOldEntriesB,
|
|
HashResizeNewEntriesA - HashResizeNewEntriesB)
|
|
;
|
|
DetailsA = step_stats_poly(DuNodeAllocsA, DuNodeBytesA,
|
|
DuArgLookupsA, DuExistLookupsA, EnumNodeAllocsA, EnumNodeBytesA,
|
|
HashTableAllocsA, HashTableBytesA,
|
|
HashLinkChunkAllocsA, HashLinkChunkBytesA,
|
|
HashKeyComparesNotDuplA, HashKeyComparesIsDuplA,
|
|
HashResizesA, HashResizeOldEntriesA, HashResizeNewEntriesA),
|
|
DetailsB = step_stats_poly(DuNodeAllocsB, DuNodeBytesB,
|
|
DuArgLookupsB, DuExistLookupsB, EnumNodeAllocsB, EnumNodeBytesB,
|
|
HashTableAllocsB, HashTableBytesB,
|
|
HashLinkChunkAllocsB, HashLinkChunkBytesB,
|
|
HashKeyComparesNotDuplB, HashKeyComparesIsDuplB,
|
|
HashResizesB, HashResizeOldEntriesB, HashResizeNewEntriesB),
|
|
DetailsDiff = step_stats_poly(DuNodeAllocsA - DuNodeAllocsB,
|
|
DuNodeBytesA - DuNodeBytesB,
|
|
DuArgLookupsA - DuArgLookupsB,
|
|
DuExistLookupsA - DuExistLookupsB,
|
|
EnumNodeAllocsA - EnumNodeAllocsB,
|
|
EnumNodeBytesA - EnumNodeBytesB,
|
|
HashTableAllocsA - HashTableAllocsB,
|
|
HashTableBytesA - HashTableBytesB,
|
|
HashLinkChunkAllocsA - HashLinkChunkAllocsB,
|
|
HashLinkChunkBytesA - HashLinkChunkBytesB,
|
|
HashKeyComparesNotDuplA - HashKeyComparesNotDuplB,
|
|
HashKeyComparesIsDuplA - HashKeyComparesIsDuplB,
|
|
HashResizesA - HashResizesB,
|
|
HashResizeOldEntriesA - HashResizeOldEntriesB,
|
|
HashResizeNewEntriesA - HashResizeNewEntriesB)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
write_table_stats(Stats, !IO) :-
|
|
io.output_stream(OutStream, !IO),
|
|
write_table_stats(OutStream, Stats, !IO).
|
|
|
|
write_table_stats(OutStream, Stats, !IO) :-
|
|
Stats = table_stats(Lookups, LookupsIsDupl, Steps),
|
|
|
|
LookupsNotDupl = Lookups - LookupsIsDupl,
|
|
LookupsStr = string.int_to_string_thousands(Lookups),
|
|
LookupsIsDuplStr = string.int_to_string_thousands(LookupsIsDupl),
|
|
LookupsNotDuplStr = string.int_to_string_thousands(LookupsNotDupl),
|
|
|
|
io.format(OutStream,
|
|
"number of lookups: %9s\n",
|
|
[s(LookupsStr)], !IO),
|
|
( if Lookups > 0 then
|
|
FractionIsDuplStr = percentage_str(LookupsIsDupl, Lookups),
|
|
FractionNotDuplStr = percentage_str(LookupsNotDupl, Lookups),
|
|
|
|
io.format(OutStream,
|
|
"number of successful lookups (old calls): %9s %9s\n",
|
|
[s(LookupsIsDuplStr), s(FractionIsDuplStr)], !IO),
|
|
io.format(OutStream,
|
|
"number of unsuccessful lookups (new calls): %9s %9s\n",
|
|
[s(LookupsNotDuplStr), s(FractionNotDuplStr)], !IO),
|
|
io.write_string(OutStream,
|
|
"statistics for the individual steps:\n", !IO),
|
|
list.foldl2(write_table_step_stats_loop(OutStream), Steps, 1, _, !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred write_table_step_stats_loop(io.text_output_stream::in,
|
|
table_step_stats::in, int::in, int::out, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats_loop(OutStream, Step, !StepNum, !IO) :-
|
|
write_table_step_stats(OutStream, Step, !.StepNum, !IO),
|
|
!:StepNum = !.StepNum + 1.
|
|
|
|
:- pred write_table_step_stats_header(io.text_output_stream::in,
|
|
string::in, int::in, string::in, int::in, int::in, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats_header(OutStream, VarName, StepNum, KindStr,
|
|
Lookups, LookupsIsDupl, !IO) :-
|
|
io.format(OutStream,
|
|
"\nstep %d, variable %s: %s\n",
|
|
[i(StepNum), s(VarName), s(KindStr)], !IO),
|
|
|
|
LookupsNotDupl = Lookups - LookupsIsDupl,
|
|
LookupsStr = string.int_to_string_thousands(Lookups),
|
|
LookupsIsDuplStr = string.int_to_string_thousands(LookupsIsDupl),
|
|
LookupsNotDuplStr = string.int_to_string_thousands(LookupsNotDupl),
|
|
|
|
io.format(OutStream,
|
|
" number of lookups: %9s\n",
|
|
[s(LookupsStr)], !IO),
|
|
( if Lookups > 0 then
|
|
FractionIsDuplStr = percentage_str(LookupsIsDupl, Lookups),
|
|
FractionNotDuplStr = percentage_str(LookupsNotDupl, Lookups),
|
|
|
|
io.format(OutStream,
|
|
" number of successful lookups: %9s %9s\n",
|
|
[s(LookupsIsDuplStr), s(FractionIsDuplStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of unsuccessful lookups: %9s %9s\n",
|
|
[s(LookupsNotDuplStr), s(FractionNotDuplStr)], !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred write_table_step_stats_start(io.text_output_stream::in,
|
|
int::in, int::in, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats_start(OutStream, StartAllocs, StartBytes, !IO) :-
|
|
StartAllocsStr = string.int_to_string_thousands(StartAllocs),
|
|
StartBytesStr = string.int_to_string_thousands(StartBytes),
|
|
io.format(OutStream,
|
|
" number of array (re)allocations: %9s\n",
|
|
[s(StartAllocsStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of bytes (re)allocationed: %9s\n",
|
|
[s(StartBytesStr)], !IO).
|
|
|
|
:- pred write_table_step_stats_enum(io.text_output_stream::in,
|
|
int::in, int::in, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats_enum(OutStream, EnumNodeAllocs, EnumNodeBytes, !IO) :-
|
|
EnumNodeAllocsStr = string.int_to_string_thousands(EnumNodeAllocs),
|
|
EnumNodeBytesStr = string.int_to_string_thousands(EnumNodeBytes),
|
|
io.format(OutStream,
|
|
" number of enum node allocations: %9s\n",
|
|
[s(EnumNodeAllocsStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of bytes allocated for enum nodes: %9s\n",
|
|
[s(EnumNodeBytesStr)], !IO).
|
|
|
|
:- pred write_table_step_stats_hash(io.text_output_stream::in,
|
|
int::in, int::in, int::in, int::in, int::in, int::in,
|
|
int::in, int::in, int::in, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats_hash(OutStream, HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries, !IO) :-
|
|
HashTableAllocsStr =
|
|
string.int_to_string_thousands(HashTableAllocs),
|
|
HashTableBytesStr =
|
|
string.int_to_string_thousands(HashTableBytes),
|
|
HashLinkChunkAllocsStr =
|
|
string.int_to_string_thousands(HashLinkChunkAllocs),
|
|
HashLinkChunkBytesStr =
|
|
string.int_to_string_thousands(HashLinkChunkBytes),
|
|
HashKeyComparesNotDuplStr =
|
|
string.int_to_string_thousands(HashKeyComparesNotDupl),
|
|
HashKeyComparesIsDuplStr =
|
|
string.int_to_string_thousands(HashKeyComparesIsDupl),
|
|
HashResizesStr =
|
|
string.int_to_string_thousands(HashResizes),
|
|
HashResizeOldEntriesStr =
|
|
string.int_to_string_thousands(HashResizeOldEntries),
|
|
HashResizeNewEntriesStr =
|
|
string.int_to_string_thousands(HashResizeNewEntries),
|
|
io.format(OutStream,
|
|
" number of hash table allocations: %9s\n",
|
|
[s(HashTableAllocsStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of bytes allocated for hash tables: %9s\n",
|
|
[s(HashTableBytesStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of bulk hash link allocations: %9s\n",
|
|
[s(HashLinkChunkAllocsStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of bytes allocated for hash links: %9s\n",
|
|
[s(HashLinkChunkBytesStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of key compares when unsuccessful: %9s\n",
|
|
[s(HashKeyComparesNotDuplStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of key compares when successful: %9s\n",
|
|
[s(HashKeyComparesIsDuplStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of hash table resizes: %9s\n",
|
|
[s(HashResizesStr)], !IO),
|
|
( if HashResizes > 0 then
|
|
io.format(OutStream,
|
|
" number of old entries in resizes: %9s\n",
|
|
[s(HashResizeOldEntriesStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of new entries in resizes: %9s\n",
|
|
[s(HashResizeNewEntriesStr)], !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred write_table_step_stats_du(io.text_output_stream::in,
|
|
int::in, int::in, int::in, int::in, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats_du(OutStream, DuNodeAllocs, DuNodeBytes,
|
|
DuArgLookups, DuExistLookups, !IO) :-
|
|
DuNodeAllocsStr = string.int_to_string_thousands(DuNodeAllocs),
|
|
DuNodeBytesStr = string.int_to_string_thousands(DuNodeBytes),
|
|
DuArgLookupsStr = string.int_to_string_thousands(DuArgLookups),
|
|
DuExistLookupsStr = string.int_to_string_thousands(DuExistLookups),
|
|
io.format(OutStream,
|
|
" number of du functor node allocations: %9s\n",
|
|
[s(DuNodeAllocsStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of bytes allocated for du functors: %9s\n",
|
|
[s(DuNodeBytesStr)], !IO),
|
|
io.format(OutStream,
|
|
" number of du functor argument lookups: %9s\n",
|
|
[s(DuArgLookupsStr)], !IO),
|
|
( if DuExistLookups > 0 then
|
|
io.format(OutStream,
|
|
" number of du existential type lookups: %9s\n",
|
|
[s(DuExistLookupsStr)], !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred write_table_step_stats(io.text_output_stream::in,
|
|
table_step_stats::in, int::in, io::di, io::uo) is det.
|
|
|
|
write_table_step_stats(OutStream, Step, StepNum, !IO) :-
|
|
Step = table_step_stats(VarName, Lookups, LookupsIsDupl, Details),
|
|
(
|
|
Details = step_stats_none,
|
|
write_table_step_stats_header(OutStream, VarName, StepNum, "none",
|
|
Lookups, LookupsIsDupl, !IO)
|
|
;
|
|
Details = step_stats_start(StartAllocs, StartBytes),
|
|
write_table_step_stats_header(OutStream, VarName, StepNum,
|
|
"expandable array", Lookups, LookupsIsDupl, !IO),
|
|
( if Lookups > 0 then
|
|
write_table_step_stats_start(OutStream,
|
|
StartAllocs, StartBytes, !IO)
|
|
else
|
|
true
|
|
)
|
|
;
|
|
Details = step_stats_enum(EnumNodeAllocs, EnumNodeBytes),
|
|
write_table_step_stats_header(OutStream, VarName, StepNum,
|
|
"enum trie", Lookups, LookupsIsDupl, !IO),
|
|
( if Lookups > 0 then
|
|
write_table_step_stats_enum(OutStream,
|
|
EnumNodeAllocs, EnumNodeBytes, !IO)
|
|
else
|
|
true
|
|
)
|
|
;
|
|
Details = step_stats_hash(HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries),
|
|
write_table_step_stats_header(OutStream, VarName, StepNum,
|
|
"hash table", Lookups, LookupsIsDupl, !IO),
|
|
( if Lookups > 0 then
|
|
write_table_step_stats_hash(OutStream,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries, !IO)
|
|
else
|
|
true
|
|
)
|
|
;
|
|
(
|
|
Details = step_stats_du(DuNodeAllocs, DuNodeBytes,
|
|
DuArgLookups, DuExistLookups, EnumNodeAllocs, EnumNodeBytes,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries),
|
|
KindStr = "discriminated union nested trie",
|
|
MustHaveDu = yes
|
|
;
|
|
Details = step_stats_poly(DuNodeAllocs, DuNodeBytes,
|
|
DuArgLookups, DuExistLookups, EnumNodeAllocs, EnumNodeBytes,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries),
|
|
KindStr = "polymorphic table",
|
|
MustHaveDu = no
|
|
),
|
|
write_table_step_stats_header(OutStream, VarName, StepNum, KindStr,
|
|
Lookups, LookupsIsDupl, !IO),
|
|
( if Lookups > 0 then
|
|
( if DuNodeAllocs > 0 then
|
|
write_table_step_stats_du(OutStream, DuNodeAllocs, DuNodeBytes,
|
|
DuArgLookups, DuExistLookups, !IO)
|
|
else
|
|
(
|
|
MustHaveDu = no
|
|
;
|
|
MustHaveDu = yes,
|
|
error("write_table_step_stats: no du stats")
|
|
)
|
|
),
|
|
( if EnumNodeAllocs > 0 then
|
|
write_table_step_stats_enum(OutStream,
|
|
EnumNodeAllocs, EnumNodeBytes, !IO)
|
|
else
|
|
true
|
|
),
|
|
( if HashTableAllocs > 0 then
|
|
write_table_step_stats_hash(OutStream,
|
|
HashTableAllocs, HashTableBytes,
|
|
HashLinkChunkAllocs, HashLinkChunkBytes,
|
|
HashKeyComparesNotDupl, HashKeyComparesIsDupl,
|
|
HashResizes, HashResizeOldEntries, HashResizeNewEntries,
|
|
!IO)
|
|
else
|
|
true
|
|
)
|
|
else
|
|
true
|
|
)
|
|
).
|
|
|
|
:- func percentage_str(int, int) = string.
|
|
|
|
percentage_str(A, B) = PercentageStr :-
|
|
Percentage = float(100) * float(A) / float(B),
|
|
string.format("(%.2f%%)", [f(Percentage)], PercentageStr).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
dummy_proc_table_statistics = ProcTableStatistics :-
|
|
TableStats = table_stats(0, 0, []),
|
|
CallTableStats = table_stats_curr_prev(TableStats, TableStats),
|
|
ProcTableStatistics = proc_table_statistics(CallTableStats, no).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module table_statistics.
|
|
%---------------------------------------------------------------------------%
|