Function frequency: Difference between revisions
Content added Content deleted
(Added Julia language) |
|||
Line 1,152: | Line 1,152: | ||
infix:<..> |
infix:<..> |
||
infix:<-></pre> |
infix:<-></pre> |
||
=={{header|Phix}}== |
|||
As Phix is self hosted, we can modify the compiler (or a copy of it) directly for this task.<br> |
|||
Add the line shown to procedure Call() in pmain.e, after the else on line 4938 (at the time of writing) |
|||
<pre> |
|||
else -- rType=FUNC|TYPE |
|||
log_function_call(rtnNo) |
|||
</pre> |
|||
Now create our test.exw program, which wraps the entire compiler: |
|||
<lang Phix>constant func_log = new_dict(), |
|||
func_freq = new_dict() |
|||
global procedure log_function_call(integer rtnNo) |
|||
integer node = getd_index(rtnNo,func_log) |
|||
setd(rtnNo,iff(node=NULL?1:getd_by_index(node,func_log)+1),func_log) |
|||
end procedure |
|||
include p.exw -- the phix compiler, full source |
|||
-- invert the dictionary, then print top ten |
|||
integer count = 0 |
|||
function visitor(object key, integer data, integer user_data) |
|||
if user_data=1 then -- invert |
|||
setd({data,key},0,func_freq) |
|||
else |
|||
key[2] = symtab[key[2]][S_Name] |
|||
?key |
|||
count += 1 |
|||
if count>10 then return 0 end if -- cease traversal |
|||
end if |
|||
return 1 |
|||
end function |
|||
constant r_visitor = routine_id("visitor") |
|||
rebuild_callback() -- (convert ternary tree indexes to readable names) |
|||
traverse_dict(r_visitor,1,func_log) -- invert |
|||
traverse_dict(r_visitor,2,func_freq,rev:=true) -- top 10</lang> |
|||
Invoke using "p test -norun test" (note you can omit the ".exw" part of "test.exw") |
|||
Notes:<br> |
|||
The log_function call is passed an index into the symbol table.<br> |
|||
For performance reasons the compiler uses integer indexes, so we need to invoke |
|||
rebuild_callback() to replace them with human-readable names in the symbol table.<br> |
|||
For more details of S_Name and other constants/contents of the symbol table, see pglobals.e<br> |
|||
The compiler (p.exe) interprets test.exw(+p.exw) which compiles a third copy of itself under -norun.<br> |
|||
Notice that it is not necessary to compile the compiler (using p -c p) to test changes in it, and in |
|||
fact weeks or months of work on the compiler often happens purely in interpreter mode, between actually |
|||
creating a new executable.<br> |
|||
If, instead, you want to know how many times a function is called at run-time, just add "with profile" |
|||
to the source and it will create a ex.pro listing which tells you. |
|||
Lastly, remember to remove/comment out that log_function_call() in pmain.e |
|||
{{out}} |
|||
<pre> |
|||
{1253,"length"} |
|||
{655,"and_bits"} |
|||
{354,"append"} |
|||
{308,"find"} |
|||
{163,"or_bits"} |
|||
{158,"repeat"} |
|||
{154,"SetField"} |
|||
{136,"sprintf"} |
|||
{119,"equal"} |
|||
{105,"sequence"} |
|||
{90,"platform"} |
|||
</pre> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |