[m-rev.] for review: new module mdprof_CSS_above_threshold

Ralph Becket rafe at csse.unimelb.edu.au
Wed Oct 18 11:40:23 AEST 2006


[Forwarded by Ralph because Jerome is having e-mail trouble on this list.]

----- Forwarded message from Jerome Tannier <jerome.tannier at student.fundp.ac.be> -----

Branches: main

deep_profiler/mdprof_CSS_above_threshold.m:
        New module which writes to a file the list of call site statics
        whose matching call site dynamics have an average/median
        callseqs above a given threshold.

Jerome.

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2001, 2004-2006 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.
%-----------------------------------------------------------------------------%
%
% Author: tannier.
%
% This module contains the code for writing to a file the call site statics 
% for which the matching call site dynamics have an average/median callseqs
% above a given threshold. 
%
%-----------------------------------------------------------------------------%

:- module mdprof_CSS_above_threshold.

:- interface.

:- import_module io.

%-----------------------------------------------------------------------------%

:- pred main(io::di, io::uo) is det.

%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%

:- implementation.

:- import_module profile.
:- import_module list.
:- import_module array.
:- import_module measurements.
:- import_module string.
:- import_module require.
:- import_module int.
:- import_module library.
:- import_module startup.
:- import_module char.
:- import_module getopt.
:- import_module bool.
:- import_module conf.
:- import_module maybe.
:- import_module map.

%-----------------------------------------------------------------------------%

main(!IO) :-
    io.progname_base("Profiling feedback program", ProgName, !IO),
    io.command_line_arguments(Args0, !IO),
    getopt.process_options(option_ops_multi(short, long, defaults),
        Args0, Args, MaybeOptions),
    (
        MaybeOptions = ok(Options),
        lookup_bool_option(Options, help, Help),
        lookup_bool_option(Options, version, Version),
        (
            Help = yes,
            write_help_message(ProgName, !IO)
        ;
            Help = no
        ),
        (
            Version = yes,
            io.write_string(string.format("%s Version 1.0\n", [s(ProgName)]), 
                !IO)
        ;
            Version = no
        ),
        (
            Help = no,
            Version = no
        ->
            ( Args = [Input, Output] ->
                lookup_string_option(Options, distrib, Distrib),
                ( construct_distrib(Distrib, Distrib_type) ->
                    lookup_int_option(Options, threshold, Threshold),
                    read_deep_file(Input, Maybe_error, !IO),
                    (
                        Maybe_error = ok(Deep),
                        compute_list_CSS_above_threshold(0, Deep, Threshold, 
                            Distrib_type, [], List_CSS_above_threshold),
                        generate_file(List_CSS_above_threshold, Deep, 
                            Distrib_type, Threshold, Output, !IO)
                    ;
                        Maybe_error = error(Error),
                        io.set_exit_status(1, !IO),
                        io.format("%s: error reading deep file: %s\n",
                            [s(ProgName), s(Error)], !IO)
                    )   
                ;
                    io.set_exit_status(1, !IO),
                    write_help_message(ProgName, !IO)
                )
            ;
                io.set_exit_status(1, !IO),
                write_help_message(ProgName, !IO)
            )
        ;
            true
        )
    ;
        MaybeOptions = error(Msg),
        io.set_exit_status(1, !IO),
        io.format("%s: error parsing options: %s\n",
            [s(ProgName), s(Msg)], !IO)
    ).

:- pred write_help_message(string::in, io::di, io::uo) is det.

write_help_message(ProgName) -->
    io.format("Usage: %s [<options>] <input> <output>\n", [s(ProgName)]),
    io.format("<input> must name a deep profiling data file.\n", []),
    io.format("<output> is the file generated by this program.\n", []),
    io.format("You should specify the following option:\n", []),
    io.format("--threshold <value>\n", []),
    io.format("            Set the threshold to <value>.\n",[]),
    io.format("You may specify one of the following options:\n", []),
    io.format("--help      Generate this help message.\n", []),
    io.format("--version   Report the program's version number.\n", []),
    io.format("--distrib average|median\n",[]),
    io.format("            average : writes to the output the call site\n",[]),
    io.format("            statics for which the matching call site.\n",[]),
    io.format("            dynamics have an average callseqs above.\n",[]),
    io.format("            the specified threshold (default option).\n",[]),
    io.format("            median : writes to the output the call site\n",[]),
    io.format("            statics for which the matching call site.\n",[]),
    io.format("            dynamics have a median callseqs above.\n",[]),
    io.format("            the specified threshold.\n",[]).

%-----------------------------------------------------------------------------%

    % Reads a deep data file.
    % 
:- pred read_deep_file(string::in, maybe_error(deep)::out, io::di, io::uo) 
    is det.

read_deep_file(Input, Maybe_error, !IO) :-
    server_name(Machine, !IO),
    io.stdout_stream(Stdout, !IO),
    MaybeOutput = yes(Stdout),
    read_and_startup(Machine, [Input], no, MaybeOutput, [], [], Maybe_error, 
        !IO).

    % Determines the call site statics whose call site dynamics have an 
    % average/median above a given threshold.
    % 
:- pred compute_list_CSS_above_threshold(int::in, deep::in, int::in, 
    distrib_type::in, list(call_site_static)::in, list(call_site_static)::out) 
    is det.

compute_list_CSS_above_threshold(Index, Deep, Threshold, Distrib, Acc, List_CSS) :-
    array.size(Deep ^ call_site_statics, Size),
    ( Index = Size ->
        List_CSS = Acc
    ;
        Call_site_call = array.lookup(Deep ^ call_site_calls, Index),
        List_list_CSD = map.values(Call_site_call),
        List_CSD = list.condense(List_list_CSD),
        list.length(List_CSD, Length_List_CSD),
        ( Length_List_CSD = 0 ->
            % the call_site_static doesn't have any call_site_dynamics
            Callseqs = 0
        ;
            ( 
                Distrib = average,
                foldr(sum_callseqs_CSD_ptr(Deep), List_CSD, 0, Sum_callseqs),
                Callseqs = Sum_callseqs // Length_List_CSD
            ;
                Distrib = median,
                list.sort(compare_CSD_ptr(Deep), List_CSD, 
                    List_CSD_sorted),
                Index_median = Length_List_CSD // 2,
                list.index0_det(List_CSD_sorted, Index_median, Median_ptr),
                sum_callseqs_CSD_ptr(Deep, Median_ptr, 0, Callseqs)
            )
        ),
        ( Callseqs >= Threshold ->
            Call_site_static = array.lookup(Deep ^ call_site_statics, Index),
            Acc0 = [Call_site_static | Acc],
            compute_list_CSS_above_threshold(Index + 1, Deep, Threshold, 
                Distrib, Acc0, List_CSS)
        ;
            compute_list_CSS_above_threshold(Index + 1, Deep, Threshold, 
                Distrib, Acc, List_CSS)
        ) 
    ).

    % Adds the callseqs (own and desc) of call_site_dynamic_ptr to the 
    % accumulator.
    % 
:- pred sum_callseqs_CSD_ptr(deep::in, call_site_dynamic_ptr::in, int::in, 
    int::out) is det.

sum_callseqs_CSD_ptr(Deep, CSD_ptr, Acc, Sum) :-
    lookup_call_site_dynamics(Deep ^ call_site_dynamics, CSD_ptr, CSD),
    lookup_csd_desc(Deep ^ csd_desc, CSD_ptr, IPO),
    Sum = Acc + callseqs(CSD ^ csd_own_prof) + inherit_callseqs(IPO).

    % Compares 2 call_site_dynamic_ptr on the basis of their callseqs (own and 
    % desc).
    % 
:- pred compare_CSD_ptr(deep::in, call_site_dynamic_ptr::in, 
    call_site_dynamic_ptr::in, comparison_result::out) is det.

compare_CSD_ptr(Deep, CSD_ptr1, CSD_ptr2, Result) :-
    sum_callseqs_CSD_ptr(Deep, CSD_ptr1, 0, Sum1),
    sum_callseqs_CSD_ptr(Deep, CSD_ptr2, 0, Sum2),
    compare(Result, Sum1, Sum2).

    % Generates the profiling feedback file which contains the call site statics
    % whose call site dynamics have an average/median callseqs (own and desc) 
    % above the threshold. 
    % 
:- pred generate_file(list(call_site_static)::in, deep::in, 
    distrib_type::in, int::in, string::in, io::di, io::uo) is det.
    
generate_file(List_CSS, Deep, Distrib, Threshold, Output, !IO) :-
    io.open_output(Output, Result, !IO),
    (
        Result = io.error(Err),
        io.write_string(io.error_message(Err) ++ "\n", !IO)
    ;
        Result = ok(OutStrm),
        io.write_string(OutStrm, "Profiling feedback file\n", !IO),
        io.write_string(OutStrm, "Version = 1.0\n", !IO),
        (
            Distrib = average,
            io.write_string(OutStrm, "Distrib = average\n", !IO)
        ;
            Distrib = median,
            io.write_string(OutStrm, "Distrib = median\n", !IO)
        ),
        io.write_string(OutStrm, string.format("Threshold = %i\n", 
            [i(Threshold)]), !IO),
        write_list_CSS(List_CSS, Deep, OutStrm, !IO),
        io.close_output(OutStrm, !IO)
    ).

    % Writes to the output the list of call site static     
    % 
:- pred write_list_CSS(list(call_site_static)::in, deep::in, output_stream::in, 
    io::di, io::uo) is det.
    
write_list_CSS(List_CSS, Deep, OutStrm, !IO) :-
    (
        List_CSS=[]
    ;
        List_CSS=[CSS | List_CSS0],
        
        % Prints the caller
        lookup_proc_statics(Deep ^ proc_statics, CSS ^ css_container, 
            Caller),
        io.write_string(OutStrm, Caller ^ ps_raw_id ++ " ", !IO),
            
        % Prints the slot number of the call_site_static
        io.write_int(OutStrm, CSS ^ css_slot_num, !IO),
        io.write_string(OutStrm, " ", !IO),
        
        % Prints the callee
        (
            CSS ^ css_kind = normal_call_and_callee(Ps_ptr, _),
            lookup_proc_statics(Deep ^ proc_statics, Ps_ptr, Callee),
            io.write_string(OutStrm, string.format("normal_call %s\n", 
                [s(Callee ^ ps_raw_id)]), !IO)
        ;
            CSS ^ css_kind = special_call_and_no_callee,
            io.write_string(OutStrm, "special_call\n", !IO)
        ;
            CSS ^ css_kind = higher_order_call_and_no_callee,
            io.write_string(OutStrm, "higher_order_call\n", !IO)
        ;
            CSS ^ css_kind = method_call_and_no_callee,
            io.write_string(OutStrm, "method_call\n", !IO)
        ;
            CSS ^ css_kind = callback_and_no_callee,
            io.write_string(OutStrm, "callback\n", !IO)
        ),
        
        write_list_CSS(List_CSS0, Deep, OutStrm, !IO)
    ).

%-----------------------------------------------------------------------------%

:- type option
    --->    threshold
    ;       help
    ;       version
    ;       distrib.

:- type distrib_type
    --->    average
    ;       median.

:- type options ---> options.
:- type option_table == (option_table(option)).

:- pred short(char::in, option::out) is semidet.

short('t',  threshold).
short('h',  help).
short('v',  version).
short('d',  distrib).


:- pred long(string::in, option::out) is semidet.

long("threshold",           threshold).
long("help",                help).
long("version",             version).
long("distrib",             distrib).

:- pred defaults(option::out, option_data::out) is multi.

defaults(threshold,         int(100000)).
defaults(help,              bool(no)).
defaults(version,           bool(no)).
defaults(distrib,           string("average")).

:- pred construct_distrib(string::in, distrib_type::out) is semidet.

construct_distrib("average",    average).
construct_distrib("median",     median).

%-----------------------------------------------------------------------------%
:- end_module mdprof_CSS_above_threshold.
%-----------------------------------------------------------------------------%

----- End forwarded message -----
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list