We will use a customer debugger hook that will count the number of port events. There will be a simple statistic that will show the relative counts. The Prolog text for the relative statistics is derived from the port statistics already found in the language reference document for the development environment. As a first step we have added a predicate time/1 to measure the used time. This predicate uses the new Java high resolution clock System.nanoTime(). We need this facility since our test program has execution time in the order of ~50ms.
As a test program we use the Einstein riddle. The Einstein riddle was first published under the heading "Who owns the Zebra?" in the Life International magazine on December 17, 1962 with solution given in the March 25, 1963 issue. The riddle given here is not a verbatim copy. We can use the time predicate to see how fast the riddle can be solved in Prolog. As a test machine we used a similar set-up as in the runtime library benchmark:
?- ['jekdev/study/ports/einstein.p']. ?- ['jekdev/study/ports/relative.p']. ?- time(test), time(test). test in 195.2 ms test in 47.7 ms
The difference between the first and second timing is probably due to the turbo boost feature of the test machine CPU. The CPU will automatically increase the clock rate on load and if only a single core is loaded. To perform the port sampling we will need to run the test program in debug mode. The test program runs a little slower in debug mode, since each instruction will be instrumented. But the overhead is not that great, since the Java Just-in-Time (JIT) compiler helps reducing the effort for the instrumentation code:
?- debug. ?- time(test), time(test). test in 121.3 ms test in 68.8 ms
As a next step we have changed the reporting predicate of the
port statistics. The relative port statistics will use the exact
same custom debugger hook as the absolute port statistics. But the
reporting predicate will show relative port statistics. The shown
relative number will express the ratio between the number of port
events and the total number of port events for the same port type:
We have realized the above formula in Prolog by first computing the sum as follows:
% sum_counts(+List,-CallExitRedoFail) sum_counts(,0-0-0-0). sum_counts([_-D|L],S) :- sum_counts(L,R), add_count(R,D,S). % show show :- findall(F/A-D,count(F,A,D),L), sum_counts(L,TR-TS-TT-TU),
The sums TR, TS, TI and TU are then used to compute the relative port statistics as follows:
write('Pred\tCall\tExit\tRedo\tFail'), nl, keysort(L,M), mem_counts(I-(R-S-T-U),M), RP is R*100 / TR, SP is S*100 / TS, TP is T*100 / TT, UP is U*100 / TU, ((RP >= 0.05; SP >=0.05; TP >=0.05; UP >=0.05) ->
The relative statistics in per cent are found in RP, SP, TP and UP. The keysort/2 predicate comes in handy to sort the results so that we will get a report that shows the predicate indicators in descending order. This makes it easier to compare different reports. The comparison with 0.05 is used to suppress result rows that would be shown as 0.0 0.0 0.0 0.0. This will assure that the report is not blown up by rarely called predicates.