PreviousUpNext

15.4.458  src/lib/compiler/back/top/closures/allocprof.pkg

## Allocprof.pkg 
#

# Compiled by:
#     src/lib/compiler/core.sublib



#DO set_control "compiler::trap_int_overflow" "TRUE";

stipulate
    package fil =  file__premicrothread;                                # file__premicrothread  is from   src/lib/std/src/posix/file--premicrothread.pkg
    package ncf =  nextcode_form;                                       # nextcode_form         is from   src/lib/compiler/back/top/nextcode/nextcode-form.pkg
herein

    package allot_prof {
        #
        stipulate
            #
            issue_highcode_codetemp
                =
                highcode_codetemp::issue_highcode_codetemp;

            arrays =          0;
            arraysize =       1;
            strings =         2;
            stringsize =      3;
            refcells =        4;
            reflists =        5;
            closures' =       6;
            closureslots =    11;
            closureovfl =     (closures' + closureslots);
            kclosures' =      (closureovfl + 1);
            kclosureslots =   11;
            kclosureovfl =    (kclosures' + kclosureslots);
            cclosures' =      (kclosureovfl + 1);
            cclosureslots =   11;
            cclosureovfl =    (cclosures' + cclosureslots);
            links' =          (cclosureovfl + 1);
            linkslots =       11;
            linkovfl =        (links' + linkslots);
            splinks =         (linkovfl + 1);
            splinkslots =     11;
            splinkovfl =      (splinks + splinkslots);
            records' =        (splinkovfl + 1);
            recordslots =     11;
            recordovfl =      (records' + recordslots);
            spills' =         (recordovfl + 1);
            spillslots =      21;
            spillovfl =       (spills' + spillslots);
            knowncalls =      (spillovfl + 1);
            stdkcalls =       (knowncalls + 1);
            stdcalls =        (stdkcalls + 1);
            cntcalls =        (stdcalls + 1);
            cntkcalls =       (cntcalls + 1);
            cscntcalls =      (cntkcalls + 1);
            cscntkcalls =     (cscntcalls + 1);
            tlimitcheck =     (cscntkcalls+1);
            alimitcheck =     (tlimitcheck+1);
            arithovh =        (alimitcheck+1);
            arithslots =      5;

            # Make sure the rw_vector assigned
            # to current_thread_ptr in the runtime system
            # is at least this big!!
            # Test how big by doing an allocReset from batch.   XXX BUGGO FIXME test should be automated and done every run if needed.
            profsize =        (arithovh + arithslots);

            profreg = 0;  #  use pseudo register 0 

        herein

            stipulate
                #
                fun prof (s, i)         #  header to increment slot s by i 
                    =
                    (\\ next
                        =
                        {   a1 = issue_highcode_codetemp();
                            a2 = issue_highcode_codetemp();
                            x  = issue_highcode_codetemp();
                            n  = issue_highcode_codetemp();

                            ncf::FETCH_FROM_RAM
                              {
                                op   => ncf::p::PSEUDOREG_GET,
                                args => [ncf::INT profreg],
                                to_temp => a1,
                                type => ncf::bogus_pointer_type,
                                next => ncf::FETCH_FROM_RAM
                                          {
                                            op   => ncf::p::GET_VECSLOT_CONTENTS,
                                            args => [ncf::CODETEMP a1, ncf::INT s],
                                            to_temp => x,
                                            type => ncf::typ::INT,
                                            next => ncf::ARITH
                                                      {
                                                        op   => ncf::p::iadd,
                                                        args => [ncf::CODETEMP x, ncf::INT i],
                                                        to_temp => n,
                                                        type => ncf::typ::INT,
                                                        next => ncf::FETCH_FROM_RAM
                                                                  {
                                                                    op   => ncf::p::PSEUDOREG_GET,
                                                                    args => [ncf::INT profreg],
                                                                    to_temp => a2,
                                                                    type => ncf::bogus_pointer_type,
                                                                    next => ncf::STORE_TO_RAM
                                                                              { op   => ncf::p::SET_VECSLOT_TO_TAGGED_INT_VALUE,
                                                                                args => [ncf::CODETEMP a2, ncf::INT s, ncf::CODETEMP n],
                                                                                next
                                                                              }
                                                                  }
                                                    }
                                         }
                              };
                        }
                   );

                fun prof_slots (base, slots, ovfl) cost
                    =
                    if (cost < slots)
                         prof (base+cost, 1);
                    else prof (base, 1) o prof (ovfl, cost);
                    fi;

                id =   \\ x = x;

            herein

                stipulate
                    prof_links0 = prof_slots (links', linkslots, linkovfl); 
                herein 
                    fun prof_links (cost)
                        =
                        if (cost == 0)   id;
                        else             prof_links0 cost;
                        fi;
                end;

                fun prof_rec_links (l)
                    =
                    fold_backward
                        (\\ (cost, h) = prof_links (cost) o h)
                        id
                        l;

                stipulate
                    prof_record0 = prof_slots (records', recordslots, recordovfl); 
                herein
                    fun prof_record (cost) = if (cost==0 ) id; else prof_record0 cost;fi;
                end;

                prof_closure = prof_slots (closures', closureslots, closureovfl);

                prof_kclosure = prof_slots (kclosures', kclosureslots, kclosureovfl);

                prof_cclosure = prof_slots (cclosures', cclosureslots, cclosureovfl);

                prof_spill = prof_slots (spills', spillslots, spillovfl);

                prof_std_call = prof (stdcalls, 1);

                prof_stdk_call = prof (stdkcalls, 1);

                prof_count_call = prof (cntcalls, 1);

                prof_cntk_call = prof (cntkcalls, 1);

                prof_cscnt_call = prof (cscntcalls, 1);

                prof_cscntk_call = prof (cscntkcalls, 1);

                prof_known_call = prof (knowncalls, 1);

                fun prof_ref_cell k = prof (refcells, k);

                prof_ref_list = prof (reflists, 1);

                prof_tlcheck = prof (tlimitcheck, 1);

                prof_alcheck = prof (alimitcheck, 1);

            end; #  local 


            fun print_profile_info  outstrm
                =
                {   im = int::to_string;
                    #
                    fun pr x
                        =
                        fil::write (outstrm, x);

                    printf' = apply pr;

                    # Right justify st in a string of length w. 
                    #
                    fun field' (st, w)
                        =
                        if (w <= string::length_in_bytes st)
                             st;
                        else
                             s = "                              " + st;

                             substring (s, string::length_in_bytes s - w, w);
                        fi;

                    fun ifield (i, w)
                        =
                        field' (im i, w);

                    # Put a decimal point at position w in string st. 
                    #
                    fun decimal (st, w)
                        =
                        {   l = string::length_in_bytes st - w;
                            #
                            a =    l <= 0   ??   "0"
                                            ::   substring (st, 0, l);

                            st' = "0000000000" + st;

                            a + "." + substring (st', string::length_in_bytes st' - w, w);
                        };

                    fun muldiv (i, j, k)
                        =
                        (i*j / k)
                        except
                            OVERFLOW =   muldiv (i, j / 2, k / 2);

                    fun decfield (n, j, k, w1, w2)
                        = 
                        field' (   decimal (im (muldiv (n, j, k)), w1)
                                   except
                                       DIVIDE_BY_ZERO = "", w2
                               );

                    # Return the percentage i/j to 1
                    # decimal place in a field of width k:
                    #
                    fun percent (i, j, k)
                        =
                        decfield (1000, i, j, 1, k);

                    # Return the percentage i/j to 2
                    # decimal places in a field of width k:
                    #
                    fun percent2 (i, j, k)
                        =
                        decfield (10000, i, j, 2, k);

                    fun for' (start, upto, f)
                        =
                        iter (start, 0)
                        where
                            fun iter (i, accum: Int)
                                = 
                                i < upto   ??   iter (i+1, accum + f (i))
                                           ::   accum;

                        end;

                    fun for'' (start, upto, f)
                        =
                        iter  start
                        where
                            fun iter i
                                =
                                i < upto   ??   f i
                                           ::   iter (i+1);
                        end;


                    my profvec:  Rw_Vector( Int )
                        =
                        unsafe::get_pseudo (profreg);

                    fun getprof   (x) =   rw_vector::get (profvec, x);

                    fun links     (i) =   getprof (links'     + i);
                    fun closures  (i) =   getprof (closures'  + i);
                    fun kclosures (i) =   getprof (kclosures' + i);
                    fun cclosures (i) =   getprof (cclosures' + i);
                    fun records   (i) =   getprof (records'   + i);
                    fun spills    (i) =   getprof (spills'    + i);

                    num_calls = getprof knowncalls
                              + getprof stdkcalls
                              + getprof stdcalls
                              + getprof cntkcalls
                              + getprof cntcalls
                              + getprof cscntkcalls
                              + getprof cscntcalls;

                    num_closures   = for' (0, closureslots, \\ i = closures i);
                    space_closures = for' (1, closureslots, \\ i = closures i * (i+1));
                    space_closures = space_closures + getprof closureovfl + closures 0;

                    num_kclosures   = for' (0, kclosureslots, \\ i = kclosures i);
                    space_kclosures = for' (1, kclosureslots, \\ i = kclosures i * (i+1));
                    space_kclosures = space_kclosures + getprof kclosureovfl + kclosures 0;

                    num_cclosures   = for' (0, cclosureslots, \\ i = cclosures i);
                    space_cclosures = for' (1, cclosureslots, \\ i = cclosures i * (i+1));
                    space_cclosures = space_cclosures + getprof cclosureovfl + cclosures 0;

                    num_closure_accesses = for' (0, linkslots, \\ i = links i);
                    num_links_traced     = for' (1, linkslots, \\ i = links i * i);
                    num_links_traced     = num_links_traced + getprof linkovfl;

                    num_records   = for' (0, recordslots, \\ i = records i);
                    space_records = for' (1, recordslots, \\ i = records i * (i+1));
                    space_records = space_records + getprof recordovfl + records 0;

                    num_spills   = for' (0, spillslots, \\ i = spills i);
                    space_spills = for' (1, spillslots, \\ i = spills i * (i+1));
                    space_spills = space_spills + getprof spillovfl + spills 0;

                    total = space_closures
                          + space_kclosures
                          + space_cclosures
                          + space_records
                          + space_spills
                          + getprof arraysize
                          + getprof arrays
                          + getprof stringsize
                          + getprof strings
                          + getprof refcells * 2
                          + getprof reflists * 2;

                    descriptors
                        = num_closures
                        + num_kclosures
                        + num_cclosures
                        + num_records
                        + num_spills
                        + getprof arrays
                        + getprof strings
                        + getprof refcells;

                    sgetprof = im o getprof;

                    fun print_links()
                        =
                        if   (num_closure_accesses > 0)

                             for''(1, linkslots,
                                   \\ k =
                                      if (links k > 0)

                                           printf' [ifield (k, 4),
                                                  ifield (links (k), 13),
                                                  percent (links (k), num_closure_accesses, 12),
                                                  "%",
                                                  ifield (links (k) * k, 12),
                                                  percent (links (k) * k, num_links_traced, 9),
                                                  "%\n"];
                                      fi
                                  );

                              if   (links (0) > 0)

                                   printf' [
                                      ">",
                                      ifield (linkslots - 1, 5),
                                      ifield (links (0), 9),
                                      percent (links (0), num_closure_accesses, 10),
                                      "%",
                                      ifield (getprof (linkovfl), 13),
                                      percent (getprof (linkovfl), num_links_traced, 10),
                                      "%\n"
                                   ];
                              fi;

                              printf' [decfield (100, num_links_traced, num_closure_accesses, 2, 0),
                                   " links were traced per access on average.\n\n"];

                        else 
                             printf' ["\n"]; #  end function printLinks 
                        fi;

                    fun print1 (num, name, slots, getstat, ovfl, space)
                        =
                        if   (num > 0)

                             printf' [name, ":\n"];

                             for'' (   1, slots,
                                      \\ k =
                                         if   (getstat (k) > 0)

                                              printf' [ifield (k, 6),
                                                     ifield (getstat (k), 9),
                                                     percent (getstat (k), num, 9),
                                                     "%",
                                                     ifield (getstat (k) * (k+1), 13),
                                                     percent (getstat (k) * (k+1), total, 10),
                                                     "%\n"];
                                         fi
                                  );

                             if   (getstat 0 > 0)

                                  printf' [">",
                                         ifield (slots - 1, 5),
                                         ifield (getstat (0), 9),
                                         percent (getstat (0), num, 9),
                                         "%",
                                         ifield (getprof (ovfl)+getstat (0), 13),
                                         percent (getprof (ovfl)+getstat (0), total, 10),
                                         "%\n"];
                             fi;

                             printf' ["total:",
                                    ifield (num, 9),
                                    ifield (space, 23),
                                    percent (space, total, 10),
                                    "%  Average size ",
                                    decfield (100, space-num, num, 2, 0),
                                    "\n\n"];
                        else
                             if   (string::length_in_bytes name  >  12)
                                  printf' [name, ": 0\n\n"];
                             else printf' [name, ": ",
                                          ifield (0, 13 - string::length_in_bytes name), "\n\n"];
                             fi;
                        fi;
                    #  end function print1 

                    fun print2 (stat, size, name)
                        =
                        if (getprof stat != 0)
                            #
                            printf' [ name,
                                      ifield (getprof stat, 6),
                                      ifield (getprof size + getprof stat, 23),
                                      percent (getprof size + getprof stat, total, 10),
                                      "%  Average size ",
                                      decfield (100, getprof size, getprof stat, 2, 0),
                                      "\n"];
                        else
                            printf' [name, ifield (0, 6), "\n"];
                        fi;

                    fun print3 (stat, name)
                        =
                        if (getprof stat != 0)
                            #
                            printf' [name,
                                   ifield  (getprof stat, 6),
                                   ifield  (getprof stat * 2, 23),
                                   percent (getprof stat * 2, total, 10),
                                   "%\n"];
                        else
                            printf' [name, ifield (0, 6), "\n"];
                        fi;

                    fun print4 (stat, name)
                        =
                        if (getprof stat != 0)
                             #
                             printf' [ name, ifield (getprof stat, 10), "\n" ];
                        else printf' [ name, ifield (0,            12), "\n" ];
                        fi;


                    pr "\n-------------------- ALLOCATION PROFILE --------------------\n\n";

                    pr "\n                 ----- FUNCTION CALLS -----\n";

                    if (num_calls > 0)

                         printf' ["Known functions:                 ",
                                ifield (getprof (knowncalls), 10),
                                " (",
                                percent (getprof (knowncalls), num_calls, 4),
                                "%)\n",

                                "Escaping functions:              ",
                                ifield (getprof (stdcalls), 10),
                                " (",
                                percent (getprof (stdcalls), num_calls, 4),
                                "%)\n",


                                "Known escaping functions:        ",
                                ifield (getprof (stdkcalls), 10),
                                " (",
                                percent (getprof (stdkcalls), num_calls, 4),
                                "%)\n",

                                "Fates:                   ",
                                ifield (getprof (cntcalls), 10),
                                " (",
                                percent (getprof (cntcalls), num_calls, 4),
                                "%)\n",

                                "Known fates:             ",
                                ifield (getprof (cntkcalls), 10),
                                " (",
                                percent (getprof (cntkcalls), num_calls, 4),
                                "%)\n",

                                "Callee-save fates:       ",
                                ifield (getprof (cscntcalls), 10),
                                " (",
                                percent (getprof (cscntcalls), num_calls, 4),
                                "%)\n",

                                "Known callee-save fates: ",
                                ifield (getprof (cscntkcalls), 10),
                                " (",
                                percent (getprof (cscntkcalls), num_calls, 4),
                                "%)\n"];
                    fi;

                    printf' ["\nTotal function calls:            ",
                           ifield (num_calls, 10), "\n\n"];


                    pr "\n                ----- CLOSURE ACCESSES -----\n";
                    printf' ["Closure elements were accessed ",
                           im num_closure_accesses,
                           " times through ",
                           im num_links_traced,
                           " links:\n",
                           "Size     Accesses   % accesses       Links   % links\n"];

                    print_links ();

                    pr "\n                ----- HEAP ALLOCATIONS -----\n";
                    pr "             (only total sizes include descriptors)\n\n";
                    printf' ["TOTAL size ", im total];

                    if   (total > 0)

                            printf' ["; ",
                                   im descriptors, " descriptors accounted for ",
                                   percent (descriptors, total, 0), "%.\n\n"];
                    else
                         printf' [".\n\n"];
                    fi;

                    printf' ["  Size   Number   % total   Total size    % TOTAL\n\n"];

                    print1 (num_closures, "Closures for escaping functions",
                           closureslots, closures, closureovfl, space_closures);

                    print1 (num_kclosures, "Closures for known functions",
                           kclosureslots, kclosures, kclosureovfl, space_kclosures);

                    print1 (num_cclosures, "Closures for callee-save fates",
                           cclosureslots, cclosures, cclosureovfl, space_cclosures);

                    print1 (num_records, "Records", recordslots, records,
                           recordovfl, space_records);

                    print1 (num_spills, "Spills", spillslots, spills,
                           spillovfl, space_spills);

                    print2 (arrays, arraysize, "Arrays:  " );
                    print2 (strings, stringsize, "Strings: ");

                    print3 (refcells, "Refs:    ");
                    print3 (reflists, "Ref\n list:   ");

                    print4 (tlimitcheck, "Limit Checks for Fates Only: ");
                    print4 (alimitcheck, "Limit Checks for Other allocations: ");

                }; #  fun print_profile_info 


            fun reset ()
                =
                {   print "New  allot profvec, size "; 
                    print (int::to_string profsize); print "\n";
                    unsafe::set_pseudo (rw_vector::make_rw_vector (profsize, 0), profreg);
                };

        end;    # stipulate 
    };          # package allot_prof 
end;            # stipulate 



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext