report ← {larg} (dfn ##.mdf) rarg ⍝ Monitor D function.
Mdf applies its operand D function to (or between) its argument(s) then displays
the function with a count of the number of times each line was executed. This
output is a useful indication of the "hot spots" in the subject function where
it might pay to review the code in order to improve overall performance.
NB: From dyalog V13, ⎕PROFILE will supply this information directly. <V>
Technical notes:
The coding of this operator is "nasty" in the sense that there is extensive in-
terference between the operator and its subject D function. In particular, there
is scope for name clashes, which with luck, have been avoided by choosing unlik-
ely names, and refraining from naming transient values where possible.
The operator initialises a count vector "_mdf_c" with zeros corresponding to
each line of the subject function. It then makes a temporary copy "_mdf_f" of
the subject function, prefacing each line with a segment of code that increments
the count for this line:
_mdf_c[⎕io+⍬⍴⎕lc]+←1 ⋄
Further nastiness occurs in order to determine the name of the subject function.
The approach taken is to compare all but the header source line of the temporary
function with those of all functions in the current namespace.
From Dyalog V13, this operator can be coded in a more pleasant way: <V>
mdf←{ ⍝ Line hits for function ⍺⍺.
name←⍺⍺¨{ff←⍺⍺ ⋄ (⍕⎕OR'ff')~'∇ ¨'}⍬ ⍝ deduce name of operand fn.
_←⎕PROFILE¨'reset' 'on' ⍝ initialise profilng.
⍺←{⍵} ⋄ _←⍺ ⍺⍺ ⍵ ⍝ apply function.
data _←⎕PROFILE¨('data'name)'reset' ⍝ profiling data for ⍺⍺.
lines count←1↓¨1↓3↑↓⍉data ⍝ lines visited and hit-count.
code←⎕CR name ⍝ source code for ⍺⍺.
v←{0}¨↓code ⍝ initial hits vector.
v[lines+⎕IO]←count ⍝ insert hits.
v,code ⍝ hits followed by source.
}
Bugs:
[1] An inner D-fn that has executable code on its first (or only) line:
inner←{⍺←0
or:
free←{⍵~¨⍺+(⍴⍵)↑cvex}
reports a count corresponding to the definition rather than the execution of
the first line. In order to examine such cases in more detail, split them
over several lines. For example in queens below, splitting the definition of
inner function "free" over two lines, shows it defined once but called 862
times:
1 free←{
862 ⍵~¨⍺+(⍴⍵)↑cvex} ⍝ Unchecked squares.
[2] A subject operand function that happened to contain either of the names
"_mdf_c" or "_mdf_f" would produce unpredictable results.
[3] The subject operand function may not be more exotic than a named simple D-
fn. In particular, it may not be:
a derived function as in:
foo¨mdf 0
foo∘goo mdf 0
foo mdf mdf 0
an unnamed function such as:
{⍵ ⍵}mdf 0
Examples:
⍝ Monitored application of various functions:
osc mdf 27
0 osc←{ ⍝ Oscillate - probably returns 1.
112 1=⍵:1
111 2|⍵:∇ 1+3×⍵
70 ∇ ⍵÷2
0 }
105 gcd mdf 330
0 gcd←{ ⍝ Greatest common divisor.
4 ⍵=0:⍺
3 ⍵ ∇ ⍵|⍺
0 }
sieve mdf 2 to 100
0 sieve←{ ⍝ Sieve of Eratosthenes.
5 ⍺←⍬ ⍝ Default no primes yet.
5 nxt←1↑⍵ ⍝ Next prime, and
5 msk←×nxt|⍵ ⍝ ... mask of non-multiples.
5 ^/1↓msk:⍺,⍵ ⍝ All non multiples - finished.
4 (⍺,nxt)∇ msk/⍵ ⍝ Sieve remainder.
0 }
queens mdf 8
0 queens←{⎕ML ⎕IO←0 ⍝ The N-queens problem.
1
1 search←{ ⍝ Search for all solutions.
863 (⊂⍬)∊⍵:0⍴⊂⍬ ⍝ stitched: abandon this branch.
583 0=⍴⍵:rmdups ⍺ ⍝ all done: solution!
537 hd tl←(⊃⍵)(1↓⍵) ⍝ head 'n tail of remaining ranks.
537 next←⍺∘,¨hd ⍝ possible next steps.
537 rems←hd free¨⊂tl ⍝ unchecked squares.
537 ↑,/next ∇¨rems ⍝ ... in following ranks.
0 }
1
1 cvex←(1+⍳⍵)×⊂¯1 0 1 ⍝ Checking vectors.
1
1 free←{⍵~¨⍺+(⍴⍵)↑cvex} ⍝ Unchecked squares.
1
1 rmdups←{ ⍝ Ignore duplicate solution.
46 rots←{{⍒⍵}\4/⊂⍵} ⍝ 4 rotations.
46 refs←{{⍋⍵}\2/⊂⍵} ⍝ 2 reflections.
46 best←{(⊃⍋↑⍵)⊃⍵} ⍝ best (=lowest) solution.
46 all8←,↑refs¨rots ⍵ ⍝ all 8 orientations.
46 (⍵≡best all8)⊃⍬(,⊂⍵) ⍝ ignore if not best.
0 }
1
1 fmt←{ ⍝ Format solution.
1 chars←'·⍟'[(↑⍵)∘.=⍳⍺] ⍝ char array of placed queens.
1 expd←1↓,↑⍺⍴⊂0 1 ⍝ expansion mask.
1 ↑¨↓↓expd\chars ⍝ vector of char matrices.
0 }
1
1 squares←(⊂⍳⌈⍵÷2),1↓⍵⍴⊂⍳⍵ ⍝ initial squares
1
1 ⍵ fmt ⍬ search squares ⍝ all distinct solutions.
0 }
3 ack mdf 3 ⍝ Ackermann's function.
0 ack←{
2432 ⍺=0:⍵+1
1244 ⍵=0:(⍺-1)∇ 1
1187 (⍺-1)∇ ⍺ ∇ ⍵-1
0 }
See also: ticks cmpx time
Back to: contents
Back to: Workspaces
Trouble seeing APL font?