profile.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* profiling operations
  2. Copyright (C) 2006 Dennis Furey
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software Foundation,
  13. Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #include <avm/error.h>
  16. #include <avm/chrcodes.h>
  17. #include <avm/compare.h>
  18. #include <avm/profile.h>
  19. /* a data base of profile statistics, with one item for each profiled code fragment */
  20. static score board = NULL;
  21. /* non-zero means local variables are initialized */
  22. static int initialized = 0;
  23. /* represents (nil,nil) */
  24. static list shared_cell = NULL;
  25. /* an error message represented as a list of lists of character representations */
  26. static list memory_overflow = NULL;
  27. score
  28. avm_entries (team, message, fault)
  29. list team;
  30. list *message;
  31. int *fault;
  32. /* This looks up an entry in the score board whose team is given,
  33. or creates it if there isn't one, and returns the pointer to
  34. it; also increments the number of calls to the one looked
  35. up. */
  36. {
  37. list temporary;
  38. score opened;
  39. int found;
  40. opened = board;
  41. found = *fault = 0;
  42. *message = NULL;
  43. while (!!opened & !*fault & !found)
  44. {
  45. if (found = ((*message = avm_binary_comparison (team, opened->team, fault)) ? !*fault : 0))
  46. {
  47. avm_dispose (*message);
  48. (opened->calls)++;
  49. *message = NULL;
  50. }
  51. else if (!*fault)
  52. opened = opened->league;
  53. }
  54. if (!*fault & !found)
  55. {
  56. if (*fault = !(opened = (score) (malloc (sizeof (*opened)))))
  57. *message = avm_copied (memory_overflow);
  58. else
  59. {
  60. memset (opened, 0, sizeof (*opened));
  61. opened->team = avm_copied (team);
  62. opened->league = board;
  63. board = opened;
  64. }
  65. }
  66. return (*fault ? NULL : opened);
  67. }
  68. void
  69. avm_tally (filename)
  70. char *filename;
  71. /* This outputs profile information to the file in a bare bones
  72. format suitable for major embellishments. */
  73. {
  74. FILE *pro_file;
  75. int ioerror;
  76. list name;
  77. score old,reversed_board,temporary;
  78. double total,average,percentage;
  79. counter calls,reductions;
  80. int warned;
  81. int datum;
  82. if (!initialized)
  83. avm_initialize_profile ();
  84. total = 0.0;
  85. old = board;
  86. warned = 0;
  87. while (old)
  88. {
  89. total = total + (double) (old->reductions);
  90. old = old->league;
  91. }
  92. reversed_board = NULL;
  93. while (board)
  94. {
  95. temporary = board;
  96. board = board->league;
  97. temporary->league = reversed_board;
  98. reversed_board = temporary;
  99. }
  100. board = reversed_board; /* display in order of invocation */
  101. if (board ? board->league : 0) /* except for the unprofiled */
  102. {
  103. old = board;
  104. temporary = board;
  105. board = board->league;
  106. while (temporary ? temporary->league : 0)
  107. temporary = temporary->league;
  108. old->league = NULL;
  109. temporary->league = old;
  110. }
  111. if (board ? board->league : 0)
  112. {
  113. if (ioerror = !(pro_file = fopen (filename, "w")))
  114. avm_non_fatal_io_error ("can't write", filename, errno);
  115. else
  116. {
  117. ioerror = fprintf(pro_file, "\n%12s %12s %12s %12s\n\n","invocations","reductions", "average", "percentage");
  118. if (ioerror = (ioerror == EOF))
  119. avm_non_fatal_io_error ("can't write to", filename, errno);
  120. while (!!board & !ioerror)
  121. {
  122. ioerror = (EOF == fprintf(pro_file, "%12u ",calls = board->calls + 1));
  123. ioerror = (ioerror ? 1 : (EOF == fprintf(pro_file, "%12u ",reductions = board->reductions)));
  124. average = ((double) reductions) / ((double) calls);
  125. percentage = 100.0 * (((double) reductions) / total);
  126. ioerror = (ioerror ? 1 : (EOF == fprintf(pro_file, "%12.1f ",average)));
  127. ioerror = (ioerror ? 1 : (EOF == fprintf(pro_file, "%12.3f ",percentage)));
  128. name = board->team;
  129. while (!ioerror & !!name)
  130. {
  131. if (ioerror = ((datum = avm_character_code (name->head)) < 0))
  132. {
  133. if(warned ? 0 : ++warned)
  134. avm_warning ("invalid profile identifier");
  135. }
  136. else if (ioerror = (putc (datum, pro_file) != datum))
  137. avm_non_fatal_io_error ("can't write to", filename,errno);
  138. name = name->tail;
  139. }
  140. if (ioerror = (putc ('\n', pro_file) != '\n'))
  141. avm_non_fatal_io_error ("can't write to", filename, errno);
  142. avm_dispose (board->team);
  143. board = (old = board)->league;
  144. free (old);
  145. }
  146. if (EOF == fprintf (pro_file, "\n%.0f reductions in total\n\n", total))
  147. avm_non_fatal_io_error ("can't write to", filename, errno);
  148. if (fclose (pro_file))
  149. avm_non_fatal_io_error ("can't close", filename, errno);
  150. }
  151. }
  152. }
  153. void
  154. avm_initialize_profile ()
  155. /* This initializes static data, which includes a global table of
  156. profile statistics. */
  157. {
  158. if (initialized)
  159. return;
  160. initialized = 1;
  161. avm_initialize_lists ();
  162. avm_initialize_chrcodes ();
  163. avm_initialize_compare ();
  164. memory_overflow = avm_join (avm_strung ("memory overflow"), NULL);
  165. }
  166. void
  167. avm_count_profile ()
  168. /* This frees static data. */
  169. {
  170. score old;
  171. if (!initialized)
  172. return;
  173. initialized = 0;
  174. avm_dispose (memory_overflow);
  175. memory_overflow = NULL;
  176. while (board)
  177. {
  178. avm_dispose (board->team);
  179. board = (old = board)->league;
  180. free (old);
  181. }
  182. }