ticks{                                     ⍝ Sample Dfn execution clock ticks.

    ⍝---------------------- entry / exit monitor code.

    ⍙_←{⎕IO←0                               ⍝ line entry monitor
        ⍵{                                  ⍝ ⍵ is line number.
            ⍙_t[1+⍙_l]+←⍵-⍙_m               ⍝ increment time for line.
            ⍙_e[1+⍙_l]+←⍵≠⍙_m               ⍝ increment entry call count.
            ⍙_n[1+⍺]+←⍺≠⍙_l                 ⍝ increment line hits.
         0⊣⍙_m ⍙_l∘←⍵ ⍺                    ⍝ save time and current line number.
        }1⊃⎕AI                              ⍝ time now.
    }

    _⍙←{⎕IO←0                               ⍝ line exit monitor
        ⍵⊣⍺{                                ⍝ pass back result of line
            ⍙_t[1+⍺]+←⍵-⍙_m                 ⍝ increment time for line.
            ⍙_x[1+⍺]+←⍵≠⍙_m                 ⍝ increment exit call count.
         ⊢⍙_m ⍙_l∘←⍵,2⊃⎕LC                  ⍝ save time and current line number.
        }1⊃⎕AI                              ⍝ time now.
    }

    ⍝---------------------- fix function "⍙_f" with embedded monitoring code:

    ⍙_f←⍺⍺                                  ⍝ rename operand function.

    2≠≡⎕NR'⍙_f':'bad operand'⎕SIGNAL 11     ⍝ perhaps a derived fn?

    ⍙_s←⎕NR{                                ⍝ source of,
        ⎕IO⊃⍵/⍨(1↓⎕NR'⍙_f')∘{               ⍝ function whose trailing lines,
            ⍺≡1↓⎕NR ⍵                       ⍝ match those of operand function.
        }¨⍵                                 ⍝ for each function,
    }(~∘' '¨↓⎕NL 3)~⊂'⍙_f'                  ⍝ in namespace.

    0⊣⎕FX(-∘⎕IO⍳⍴⎕NR'⍙_f'){⎕IO ⎕ML←0 1      ⍝ fix function with monitor code.
        rmqt←{(~≠\''''=⍵){⍺\⍺/⍵}⍵}          ⍝ ignore quoted strings.
        rmcm←{(1,¯1↓∧\⍵≠'⍝'){⍺\⍺/⍵}⍵}       ⍝ ignore comments.
        subs←{                              ⍝ subs mon expr for ⊣⍵ ⍺⊣.
            to fm←⍺                         ⍝ [to/fm]⍵
            mask←1,1↓(-⍴fm){⍵∨⍺⌽⍵}fm⍷⍵      ⍝ fm string breaks.
            ↑,/{(fm≡⍵)⊃⍵ tomask⊂⍵         ⍝ to for fm in ⍵.
        }
        toksrmcm rmqt ⍵,' '                ⍝ active tokens.
        ⍺{
            emon←'⍙_ ',⍕⍺                   ⍝ entry monitor ⍙_ n.
            xmon(⍕⍺),' _⍙ '                ⍝ exit monitor n _⍙.
            esub(emon,':')'⊣⍵'             ⍝ entry monitor subs.
            xsubxmon'⍺⊣'                   ⍝ exit monitor subs.
            line←↑subs/esub xsub ⍵          ⍝ monitor substitution.
            '⍙_f←{'{⍺≡(⍴⍺)↑⍵}⍵:line         ⍝ first line: done
            ' ⍙_ ',(⍕⍺),': ⋄',line          ⍝ montior entry for each line.
        }↑,/{                               ⍝ raw token segments.
            ' '∧.=⍵:⍵                       ⍝ ignore blank segment.
            '{'=⊃⌽⍵:⍵,'⊣⍵⋄'                 ⍝ definition: entry (and exit) code.
            ∧/⍵∊' ⍝':⍵                      ⍝ ignore comment line.
            ':'=⊃⌽⍵:⍵                       ⍝ ignore guard.
            ((~'←'∊rmcm)/'⍺⊣'),⍵          ⍝ local defn or rslt expression.
        }¨(1,¯1↓toks∊':⋄{⍝')⊂⍵,' '          ⍝ each guard/diamond/defn/comment.
    }¨⎕NR'⍙_f':                             ⍝ each line in subject function.

    ⍝---------------------- determine time for 1000 clock ticks.

    ⍙_m ⍙_q←{                               ⍝ start and stop time.
        ai←⍬⍴1↓⎕AI                          ⍝ time now.
        ⍵=ai:∇ ⍵                            ⍝ no ticks: continue.
        ai+0 1000×ai-⍵                      ⍝ time now and 1000 ticks later.
    }⍬⍴1↓⎕AI                                ⍝ time now.

    ⍝---------------------- exercise function "⍙_f" for 1000 clock ticks.

    ⍙_n ⍙_e ⍙_x ⍙_t←⊂0,0⊣¨⍙_s               ⍝ initial counts.
    ⍙_l←0                                   ⍝ local line.

    ⍺←⊢ ⋄ ⍙_a←⍺                             ⍝ left arg or id fn.

    ⍙_z←{                                   ⍝ exercise function for 1000 ticks.
        ⍙_l←¯1                              ⍝ initial previous line.
        ⍙_n[⎕IO]+←1                         ⍝ increment loops counter.
        ⍙_z←⍎'⍙_a ⍙_f ⍵'                    ⍝ execute monadic function.
        ⍙_m⍙_q:⍙_z                         ⍝ time up: quit.
        ∇ ⍵                                 ⍝ time to spare: go round again.
    }⍵

    ⎕IO ⎕ML←0                               ⍝ now safe to set local envt.

    tvec evec xvec←1↓¨⍙_t ⍙_e ⍙_x           ⍝ save time and entry/exit counts.
    hits←1↓⍙_n÷⊃⍙_n                         ⍝ line hits.

    ⍝---------------------- calculate entry / exit monitor code overhead time.

    ⍙_t ⍙_e ⍙_x←⊂0⊣¨⍙_s                     ⍝ reset counters.
    ⍙_l←0                                   ⍝ reset last line.

    pref←'(1⊃⎕AI){0=⍵:(1⊃⎕AI)-⍺ ⋄'          ⍝ code preface.
    loop←' ⍺ ∇ '                            ⍝ recursive loop.
    post←' ⍵-1}+/'                          ⍝ code postscript.
    emon←'⍙_ 0: ⋄'                          ⍝ entry monitor code.
    xmon←' 0 _⍙ '                           ⍝ exit monitor code.

    lcodepref,loop,post,'evec,xvec'        ⍝ raw loop.
    ecodepref,emon,loop,post,'evec'        ⍝ loop with entry monitor.
    xcodepref,loop,xmon,post,'xvec'        ⍝ loop with exit monitor.

    ltime←⍎lcode                            ⍝ raw loop time.
    extime←⍎¨ecode xcode                    ⍝ entry / exit monitor time.
    nettsextime×1-ltime÷+/extime           ⍝ nett entry and exit time.
    unit←{⍵÷+/⍵}                            ⍝ adjust to unit sum.
    oheadnetts×unit¨evec xvec              ⍝ entry and exit overhead per line.

    ⍝---------------------- display monitor stats; return shy result.

    pcent←⌊0.5+100×unit tvec-↑+/ohead       ⍝ approx percentage time per line.
    trim←{r c←⍴⍵ ⋄ (r,c⌊⎕PW)↑⍵}             ⍝ trim to ⎕pw cols.
    ⎕←trim ⎕FMT hits,pcent,' ',↑⍙_s         ⍝ display monitor information.
    1:shy⍙_z                               ⍝ return shy result.
}
code_colours

test script

Back to: notes

Back to: Workspaces