mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
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, 2025 The Mercury team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: table_statistics.m.
|
|
% Author: zs.
|
|
% Stability: high.
|
|
%
|
|
% 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.
|
|
%---------------------------------------------------------------------------%
|