CACAO
statistics.hpp
Go to the documentation of this file.
1 /* src/vm/statistics.hpp - exports global varables for statistics
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 /**
26  * @file
27  *
28  * This file contains the statistics framework.
29  *
30  * @ingroup statistics
31  */
32 
33 /**
34  * @defgroup statistics Statistics framework
35  * Statistics framework.
36  *
37  * The framework provides several facilities to collect information about a
38  * virtual machine invocation. The idea is to create objects of specific
39  * classes which represent a statistic entity. For different task different
40  * classes are provided.
41  *
42  * ### Variables ###
43  *
44  * The most general class is cacao::StatVar. It can be used as a wrapper for
45  * almost any type. Statistic variables of this type can be altered in various
46  * ways although the most common usage is to increment the value. At the end of
47  * the virtual machine run the value is emitted.
48  *
49  * #### Macros ####
50  *
51  * The following macros should be used to define and declare
52  * variables of type cacao::StatVar.
53  *
54  * - STAT_REGISTER_VAR(type, var, init, name, description)
55  * - STAT_DECLARE_VAR(type, var, init)
56  * - STAT_REGISTER_VAR_EXTERN(type, var, init, name, description)
57  * - STAT_REGISTER_GROUP_VAR(type, var, init, name, description, group)
58  * - STAT_REGISTER_GROUP_VAR_EXTERN(type, var, init, name, description, group)
59  *
60  * #### Example ####
61  *
62  * @code
63  * // somewhere on a file global scope
64  * STAT_REGISTER_VAR(int,count_all_methods,0,"all methods","Number of loaded Methods")
65  * ..
66  *
67  * void handle_method() {
68  * // somewhere inside normal code
69  * STATISTICS(count_all_methods++);
70  * ...
71  * }
72  * @endcode
73  *
74  * Note: The STATISTICS() macro is used to wrap statistics only code.
75  *
76  * ### Distribution Tables ###
77  *
78  * Distribution tables can be used to collect the distribution of a value.
79  * There are two different kinds. The cacao::StatDist has a fixed start, step
80  * and end value whereas cacao::StatDistRange can be used to construct arbitrary
81  * tables. The usage of both classes is the same.
82  *
83  * #### Macros ####
84  *
85  * - STAT_REGISTER_DIST(counttype, indextype, var, start, end, step, init, name, description)
86  * - STAT_REGISTER_DIST_RANGE(counttype, indextype, var, range, range_size, init, name, description)
87  *
88  *
89  * #### Example ####
90  *
91  * @code
92  * // somewhere on a file global scope
93  * STAT_REGISTER_DIST(unsigned int,unsigned int,count_block_stack,0,9,1,0,"stack size dist",
94  * "Distribution of stack sizes at block boundary")
95  *
96  * static const unsigned int count_method_bb_distribution_range[] = {5,10,15,20,30,40,50,75};
97  * STAT_REGISTER_DIST_RANGE(unsigned int,unsigned int,count_method_bb_distribution,
98  * count_method_bb_distribution_range,8,0,"method bb dist.","Distribution of basic blocks per method")
99  * ...
100  *
101  * void handle_method() {
102  * // somewhere inside normal code
103  * STATISTICS(count_block_stack[indepth]++);
104  * ...
105  * STATISTICS(count_method_bb_distribution[basicblockcount]++);
106  * ...
107  * }
108  * @endcode
109  *
110  * ### Groups ###
111  *
112  * Groups are used to structure statistics entities.
113  *
114  * #### Macros ####
115  *
116  * - STAT_DECLARE_GROUP(var)
117  * - STAT_REGISTER_GROUP(var,name,description)
118  * - STAT_REGISTER_SUBGROUP(var,name,description,group)
119  *
120  * #### Example ####
121  *
122  * @code
123  * // somewhere on a file global scope
124  * STAT_REGISTER_GROUP(const_pcmd_stat,"const pcmd","Number of Const Pseudocommands")
125  * STAT_REGISTER_GROUP_VAR(int,count_pcmd_load,0,"pcmd load","Number of Const Pseudocommands (load)",const_pcmd_stat)
126  * ...
127  * @endcode
128  *
129  * ### Summary Groups ###
130  *
131  * Summary groups are a special form of groups. The only difference is that a
132  * summary group sums up the values of all children and prints it.
133  *
134  * #### Macros ####
135  *
136  * - STAT_REGISTER_SUM_GROUP(var,name,description)
137  * - STAT_REGISTER_SUM_SUBGROUP(var,name,description,group)
138  *
139  * #### Example ####
140  *
141  * @code
142  * // somewhere on a file global scope
143  * STAT_REGISTER_SUM_GROUP(const_pcmd_stat,"const pcmd","Number of Const Pseudocommands")
144  * STAT_REGISTER_GROUP_VAR(int,count_pcmd_load,0,"pcmd load","Number of Const Pseudocommands (load)",const_pcmd_stat)
145  * STAT_REGISTER_GROUP_VAR(int,count_pcmd_zero,0,"pcmd zero","Number of Const Pseudocommands (zero)",const_pcmd_stat)
146  * ...
147  * @endcode
148  *
149  *
150  */
151 
152 /**
153  * @addtogroup statistics
154  * @{
155  */
156 
157 /**
158  * @def STAT_REGISTER_VAR(type, var, init, name, description)
159  *
160  * Register an external statistics variable.
161  *
162  * This macros defines a static variable of type cacao::StatVar<type,init> and
163  * adds it to the root statistics group. All STAT_REGISTER_* macros should only
164  * occur in implementation files. If a variable is used in several compilation
165  * units STAT_REGISTER_VAR_EXTERN() and STAT_DECLARE_VAR() should be used.
166  *
167  * @param type Type of the variable. It should support the basic operators
168  * (arithmetic, assigment, etc.) as well as operator<<(OStream&, type) for
169  * printing support.
170  * @param var Name of the statistic variable.
171  * @param init Initial value for the variable.
172  * @param name Printable name of the variable.
173  * @param description Printable description of the variable.
174  *
175  * @see STAT_DECLARE_VAR
176  * @see STAT_REGISTER_VAR_EXTERN
177  * @see STAT_REGISTER_GROUP_VAR
178  **/
179 
180 /**
181  * @def STAT_DECLARE_VAR(type, var, init)
182  *
183  * Declare an external statistics variable.
184  *
185  * The definition should be done via the STAT_REGISTER_VAR_EXTERN() macro.
186  *
187  * @param type Type of the variable. It should support the basic operators
188  * (arithmetic, assigment, etc.) as well as operator<<(OStream&, type) for
189  * printing support.
190  * @param var Name of the statistic variable.
191  * @param init Initial value for the variable.
192  *
193  * @see STAT_REGISTER_VAR_EXTERN
194  **/
195 
196 /**
197  * @def STAT_REGISTER_VAR_EXTERN(type, var, init, name, description)
198  *
199  * Register an external statistics variable.
200  *
201  * In contrast to STAT_REGISTER_VAR() variables defined via
202  * STAT_REGISTER_VAR_EXTERN() are not declared static static and therefore
203  * allows external binding. If a statistics variable is only used in one
204  * compilation unit, STAT_REGISTER_VAR() is preferable.
205  *
206  * @param type Type of the variable. It should support the basic operators
207  * (arithmetic, assigment, etc.) as well as operator<<(OStream&, type) for
208  * printing support.
209  * @param var Name of the statistic variable.
210  * @param init Initial value for the variable.
211  * @param name Printable name of the variable.
212  * @param description Printable description of the variable.
213  *
214  * @see STAT_DECLARE_VAR
215  * @see STAT_REGISTER_VAR
216  **/
217 
218 /**
219  * @def STAT_REGISTER_GROUP_VAR(type, var, init, name, description, group)
220  *
221  * Register an statistics variable and add it to a group.
222  *
223  * This is the same as STAT_REGISTER_VAR() but the variable is added to group.
224  *
225  * @param type Type of the variable. It should support the basic operators
226  * (arithmetic, assigment, etc.) as well as operator<<(OStream&, type) for
227  * printing support.
228  * @param var Name of the statistic variable.
229  * @param init Initial value for the variable.
230  * @param name Printable name of the variable.
231  * @param description Printable description of the variable.
232  * @param group Parent group of this variable.
233  *
234  * @see STAT_REGISTER_VAR
235  * @see STAT_REGISTER_GROUP_VAR_EXTERN
236  **/
237 
238 /**
239  * @def STAT_REGISTER_GROUP_VAR_EXTERN(type, var, init, name, description, group)
240  *
241  * Register an external statistics variable and add it to a group.
242  *
243  * The difference to STAT_REGISTER_GROUP_VAR() is the same as between
244  * STAT_REGISTER_VAR_EXTERN and STAT_REGISTER_VAR().
245  *
246  * @param type Type of the variable. It should support the basic operators
247  * (arithmetic, assigment, etc.) as well as operator<<(OStream&, type) for
248  * printing support.
249  * @param var Name of the statistic variable.
250  * @param init Initial value for the variable.
251  * @param name Printable name of the variable.
252  * @param description Printable description of the variable.
253  * @param group Parent group of this variable.
254  *
255  * @see STAT_DECLARE_VAR
256  * @see STAT_REGISTER_VAR
257  **/
258 
259 /**
260  * @def STAT_REGISTER_DIST(counttype, indextype, var, start, end, step, init, name, description)
261  *
262  * Define a distribution table (steps).
263  *
264  * This macro creates a distribution table for some statistic values (e.g.
265  * number of basic blocks per method). In principle a static cacao::StatDist
266  * object is created which can be used to collect value distributions.
267  *
268  * The "width of the table columns" are fixed by the step parameter. All columns
269  * have the same width (besides the first and last one).
270  *
271  * <b>Example:</b>
272  * @code
273  * STAT_REGISTER_DIST(unsigned int,unsigned int,count_block_stack,0,9,1,0,"stack size dist",
274  * "Distribution of stack sizes at block boundary")
275  * @endcode
276  *
277  * <b>Result:</b>
278 @verbatim
279 Distribution of stack sizes at block boundary(stack size dist):
280  0] 1] 2] 3] 4] 5] 6] 7] 8] 9]( 9
281  4017 325 20 8 7 4 1 0 0 0 0
282  0.92 0.07 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 ratio
283  0.92 0.99 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 cumulated ratio
284 @endverbatim
285  *
286  *
287  * @param counttype Type of the "table entries".
288  * In most cases unsigned is the right choice.
289  * @param indextype Type of the "table index".
290  * This is the type of the things you want to count. It should support the
291  * basic arithmetic operations as well as operator<<(OStream&).
292  * @param var Name of the statistic distribution variable.
293  * @param start Start of the table.
294  * @param end End of the table.
295  * @param step Step size.
296  * @param init Initial value for the variable.
297  * @param name Printable name of the variable.
298  * @param description Printable description of the variable.
299  *
300  * @see cacao::StatDist
301  * @see STAT_REGISTER_DIST_RANGE
302  **/
303 
304 /**
305  * @def STAT_REGISTER_DIST_RANGE(counttype, indextype, var, range, range_size, init, name, description)
306  *
307  * Define a distribution table (range).
308  *
309  * In contrast to STAT_REGISTER_DIST() the "width of the columns" can be set arbitrary.
310  *
311  * <b>Example:</b>
312  * @code
313  * static const unsigned int count_method_bb_distribution_range[] = {5,10,15,20,30,40,50,75};
314  * STAT_REGISTER_DIST_RANGE(unsigned int,unsigned int,count_method_bb_distribution,
315  * count_method_bb_distribution_range,8,0,"method bb dist.","Distribution of basic blocks per method")
316  * @endcode
317  *
318  * <b>Result:</b>
319 @verbatim
320 Distribution of basic blocks per method(method bb dist.):
321  5] 10] 15] 20] 30] 40] 50] 75]( 75
322  774 96 45 17 15 3 5 3 2
323  0.81 0.10 0.05 0.02 0.02 0.00 0.01 0.00 0.00 ratio
324  0.81 0.91 0.95 0.97 0.99 0.99 0.99 1.00 1.00 cumulated ratio
325 @endverbatim
326  *
327  * @param counttype Type of the "table entries".
328  * In most cases unsigned is the right choice.
329  * @param indextype Type of the "table index".
330  * This is the type of the things you want to count. It should support the
331  * basic arithmetic operations as well as operator<<(OStream&).
332  * @param var Name of the statistic distribution variable.
333  * @param range Array of table values.
334  * @param range_size Size of the range array.
335  * @param init Initial value for the variable.
336  * @param name Printable name of the variable.
337  * @param description Printable description of the variable.
338  *
339  * @see cacao::StatDistRange
340  * @see STAT_REGISTER_DIST
341  **/
342 
343 /**
344  * @def STAT_REGISTER_GROUP(var,name,description)
345  *
346  * Register a statistics group.
347  *
348  * Create a new statistics group and add it to the root group.
349  * Groups are used to organize statistics entries (variables or groups).
350  *
351  * @param var Name of the statistic group.
352  * @param name Printable name of the group.
353  * @param description Printable description of the group.
354  *
355  * @see STAT_DECLARE_GROUP
356  * @see STAT_REGISTER_SUBGROUP
357  **/
358 
359 /**
360  * @def STAT_REGISTER_SUBGROUP(var,name,description,group)
361  *
362  * Register a statistics group and add it to a group.
363  *
364  * Create a new statistics group and add it to a specified group.
365  *
366  * @param var Name of the statistic group.
367  * @param name Printable name of the group.
368  * @param description Printable description of the group.
369  * @param group Parent group of this variable.
370  *
371  * @see STAT_DECLARE_GROUP
372  * @see STAT_REGISTER_GROUP
373  **/
374 
375 /**
376  * @def STAT_DECLARE_GROUP(var)
377  *
378  * Declare an external group (or subgroup).
379  *
380  * In contrast to variables are groups always defined at a global scope. This
381  * can be prevented by e.g. an anonymous namespace.
382  *
383  * @param var Variable name of the statistic group.
384  *
385  * @see STAT_REGISTER_GROUP
386  * @see STAT_REGISTER_SUBGROUP
387  **/
388 
389 /**
390  * @def STAT_REGISTER_SUM_GROUP(var,name,description)
391  *
392  * Register a statistics summary group.
393  *
394  * Create a new statistics group and add it to the root group.
395  * Summary groups are used to calculate the sum of several dependant statistic
396  * entries e.g. memory usage of the compiler
397  *
398  * <b>Example:</b>
399  * @code
400  * STAT_REGISTER_SUM_GROUP(info_struct_stat,"info structs","info struct usage")
401  * STAT_REGISTER_GROUP_VAR(int,size_classinfo,0,"size classinfo","classinfo",info_struct_stat)
402  * STAT_REGISTER_GROUP_VAR(int,size_fieldinfo,0,"size fieldinfo","fieldinfo",info_struct_stat)
403  * STAT_REGISTER_GROUP_VAR(int,size_methodinfo,0,"size methodinfo","methodinfo",info_struct_stat)
404  * STAT_REGISTER_GROUP_VAR(int,size_codeinfo,0,"size codeinfo","codeinfo",info_struct_stat)
405  * STAT_REGISTER_GROUP_VAR(int,size_lineinfo,0,"size lineinfo","lineinfo",info_struct_stat)
406  * @endcode
407  *
408  * <b>Result:</b>
409 @verbatim
410  size classinfo 147656 : classinfo
411  size fieldinfo 78272 : fieldinfo
412  size methodinfo 830024 : methodinfo
413  size lineinfo 91192 : lineinfo
414  size codeinfo 158400 : codeinfo
415  -------
416  sum 1305544 : info struct usage
417 @endverbatim
418  * @param var Name of the statistic group.
419  * @param name Printable name of the group.
420  * @param description Printable description of the group.
421  *
422  * @see STAT_REGISTER_SUM_SUBGROUP
423  **/
424 
425 /**
426  * @def STAT_REGISTER_SUM_SUBGROUP(var,name,description,group)
427  *
428  * Register a statistics summary group.
429  *
430  * Create a new statistics group and add it to a specified group.
431  *
432  * @param var Name of the statistic group.
433  * @param name Printable name of the group.
434  * @param description Printable description of the group.
435  * @param group Parent group of this group.
436  *
437  * @see STAT_REGISTER_SUM_GROUP
438  **/
439 
440 /**
441  * @def STATISTICS(x)
442  *
443  * Wrapper for statistics only code.
444  **/
445 
446 /** @} */
447 
448 #ifndef STATISTICS_HPP_
449 #define STATISTICS_HPP_ 1
450 
451 #include "config.h"
452 
453 #if defined(ENABLE_STATISTICS)
454 
455 #include <assert.h>
456 #include <vector>
457 #include <deque>
458 
459 #include "toolbox/OStream.hpp"
460 
461 extern bool opt_stat;
462 
463 namespace cacao {
464 
465 /**
466  * @addtogroup statistics
467  * @{
468  */
469 
470 /**
471  * Superclass of statistic group entries.
472  */
473 class StatEntry {
474 protected:
475  const char* name;
476  const char* description;
477 
478  typedef std::deque<const StatEntry*> StatStack;
479 
480  void print_csv_entry(OStream &O,StatStack &s,unsigned long v) const {
481  for(StatStack::const_iterator i = s.begin(), e = s.end() ; i != e; ++i) {
482  O << (*i)->name << '.';
483  }
484  O << name << ';' << description << ';' << v << cacao::nl;
485  }
486 public:
487  /**
488  * Constructor.
489  */
490  StatEntry(const char* name, const char* description) : name(name), description(description) {}
491  /**
492  * Print the statistics information to an OStream.
493  * @param[in,out] O output stream
494  */
495  virtual void print(OStream &O) const = 0;
496  /**
497  * Print the csv statistics information to an OStream.
498  * name,description,value
499  * @param[in,out] O output stream
500  */
501  void print_csv(OStream &O) const {
502  StatStack s;
503  print_csv_intern(O,s);
504  }
505  static void print_csv_header(OStream &O) {
506  O << "name;description;value" << nl;
507  }
508  virtual void print_csv_intern(OStream &O,StatStack &s) const = 0;
509 
510  /**
511  * Get the value of a stat entry.
512  */
513  virtual unsigned long get_value() const { return 0; }
514 
515  virtual ~StatEntry() {}
516 
517 };
518 
519 /**
520  * Statistics group.
521  * Used to collect a set of StatEntry's
522  */
523 class StatGroup : public StatEntry {
524 protected:
525  typedef std::vector<StatEntry*> StatEntryList;
526  /**
527  * List of members.
528  * @note: this must be a pointer. If it is changes to a normal variable strange
529  * things will happen!
530  */
531  StatEntryList *members;
532 
533  StatGroup(const char* name, const char* description) : StatEntry(name, description) {
534  members = new StatEntryList();
535  }
536 public:
537  /**
538  * Get the root group
539  */
540  static StatGroup& root() {
541  static StatGroup rg("root","Statistics");
542  return rg;
543  }
544 
545  /**
546  * Create a new statistics group.
547  * @param[in] name name of the group
548  * @param[in] description description of the group
549  * @param[in] group parent group.
550  */
551  StatGroup(const char* name, const char* description, StatGroup &group) : StatEntry(name, description) {
552  members = new StatEntryList();
553  group.add(this);
554  }
555 
556  ~StatGroup() {
557  delete members;
558  }
559 
560  /**
561  * Add an entry to the group
562  */
563  void add(StatEntry *re) {
564  members->push_back(re);
565  }
566 
567  virtual void print(OStream &O) const {
568  O << nl << description << ':' << nl;
569  //O << indent;
570  for(StatEntryList::const_iterator i = members->begin(), e= members->end(); i != e; ++i) {
571  StatEntry* re = *i;
572  re->print(O);
573  }
574  //O << dedent;
575  O << nl;
576  }
577  virtual void print_csv_intern(OStream &O,StatStack &s) const {
578  s.push_back(this);
579  for(StatEntryList::const_iterator i = members->begin(), e= members->end(); i != e; ++i) {
580  StatEntry* re = *i;
581  re->print_csv_intern(O,s);
582  }
583  s.pop_back();
584  }
585 
586 };
587 
588 /**
589  * Summary group.
590  * Used to collect a set of StatEntry's
591  */
592 class StatSumGroup : public StatGroup {
593 public:
594 
595  /**
596  * Create a new statistics group.
597  * @param[in] name name of the group
598  * @param[in] description description of the group
599  * @param[in] group parent group.
600  */
601  StatSumGroup(const char* name, const char* description, StatGroup &group)
602  : StatGroup(name,description,group) {}
603 
604  virtual void print(OStream &O) const {
605  unsigned long sum = 0;
606  //O << setw(10) << left << name << right <<" " << description << nl;
607  O << nl;
608  //O << indent;
609  for(StatEntryList::const_iterator i = members->begin(), e= members->end(); i != e; ++i) {
610  StatEntry* se = *i;
611  se->print(O);
612  sum += se->get_value();
613  }
614  //O << dedent;
615  O << setw(40) << "-------" << nl;
616  O << setw(30) << "sum"
617  << setw(10) << sum
618  << " : " << description << nl;
619  }
620  virtual void print_csv_intern(OStream &O,StatStack &s) const {
621  unsigned long sum = 0;
622  s.push_back(this);
623  for(StatEntryList::const_iterator i = members->begin(), e= members->end(); i != e; ++i) {
624  StatEntry* se = *i;
625  se->print_csv_intern(O,s);
626  sum += se->get_value();
627  }
628  s.pop_back();
629  print_csv_entry(O,s,sum);
630  }
631 
632  virtual unsigned long get_value() const {
633  unsigned long sum = 0;
634  for(StatEntryList::const_iterator i = members->begin(), e= members->end(); i != e; ++i) {
635  StatEntry* se = *i;
636  sum += se->get_value();
637  }
638  return sum;
639  }
640 };
641 
642 /**
643  * Statistics Distribution (abstract base).
644  */
645 template<typename _COUNT_TYPE, typename _INDEX_TYPE>
646 class StatDistAbst : public StatEntry {
647 protected:
648  _COUNT_TYPE *table; //< table
649  const std::size_t table_size; //< size of the table
650 
651  StatDistAbst(const char* name, const char* description, StatGroup &parent,
652  _INDEX_TYPE table_size, _COUNT_TYPE init)
653  : StatEntry(name, description), table_size(table_size) {
654  parent.add(this);
655  table = new _COUNT_TYPE[table_size + 1];
656 
657  for(std::size_t i = 0; i <= table_size; ++i ) {
658  table[i] = init;
659  }
660  }
661 
662  virtual ~StatDistAbst() {
663  delete table;
664  }
665 
666  virtual void print_header(OStream &O, std::size_t first, std::size_t last) const = 0;
667 
668 public:
669  virtual void print(OStream &O) const {
670  _COUNT_TYPE sum = 0;
671  _COUNT_TYPE cumulated = 0;
672 
673  for(int first = 0, end = table_size +1, last = end;
674  first != end; first = last) {
675  if (end - first > 15) {
676  last = first + 10;
677  } else {
678  last = end;
679  }
680  O << description << '(' << name << (first == 0 ? "):" : ") (cont):") << nl;
681 
682  print_header(O,first,last);
683 
684  // ratio
685  for(int i = first; i < last; ++i ) {
686  O << setw(6) << table[i];
687  sum += table[i];
688  }
689  O << nl;
690  for(int i = first; i < last; ++i ) {
691  O << setw(6) << setprecision(2) << float(table[i])/sum;
692  }
693  O << " ratio" << nl;
694  // cumulated ratio
695  for(int i = first; i < last; ++i ) {
696  cumulated += table[i];
697  O << setw(6) << setprecision(2) << float(cumulated)/sum;
698  }
699  O << " cumulated ratio" << nl;
700  }
701  O << nl;
702  }
703  virtual void print_csv_intern(OStream &O,StatStack &s) const {
704  // not yet supported
705  }
706 };
707 
708 /**
709  * Statistics Distribution.
710  *
711  * @note: step is a template variable to allow the compiler to remove the /step calculation
712  * in case step equals 1 (most common case).
713  */
714 template<typename _COUNT_TYPE, typename _INDEX_TYPE, _INDEX_TYPE step>
715 class StatDist : public StatDistAbst<_COUNT_TYPE,_INDEX_TYPE> {
716 private:
717  const _INDEX_TYPE start;
718  const _INDEX_TYPE end;
719 
720 protected:
721  virtual void print_header(OStream &O, std::size_t first, std::size_t last) const {
722  O << ' ';
723  std::size_t i;
724  for(i = first; i < last && i < this->table_size; ++i ) {
725  O << setw(5) << start + i * step << ']';
726  }
727  if (i == this->table_size) {
728  O << '(' << setw(4) << start + (this->table_size-1)*step;
729  }
730  O << nl;
731  }
732 
733 public:
734  /**
735  * Create a new statistics distribution.
736  * @param[in] name name of the variable
737  * @param[in] description description of the variable
738  * @param[in] parent parent group.
739  * @param[in] start first entry in the distribution table
740  * @param[in] end last entry in the distribution table
741  * @param[in] init initial value of the distribution table entries
742  */
743  StatDist(const char* name, const char* description, StatGroup &parent,
744  _INDEX_TYPE start, _INDEX_TYPE end, _COUNT_TYPE init)
745  : StatDistAbst<_COUNT_TYPE,_INDEX_TYPE>(name, description, parent,
746  (end - start)/step + 1, init),
747  start(start), end(end) {
748  assert(step);
749  }
750 
751  /// index operator
752  inline _COUNT_TYPE& operator[](const _INDEX_TYPE i) {
753  if (i <= start) {
754  return this->table[0];
755  }
756  if (i > end) {
757  return this->table[this->table_size];
758  }
759  return this->table[( (i-start)%step == 0 ? (i-start)/step : (i-start+step)/step )];
760  }
761 };
762 
763 /**
764  * Statistics Distribution (Range).
765  *
766  * @note: step is a template variable to allow the compiler to remove the /step calculation
767  * in case step equals 1 (most common case).
768  */
769 template<typename _COUNT_TYPE, typename _INDEX_TYPE>
770 class StatDistRange : public StatDistAbst<_COUNT_TYPE,_INDEX_TYPE> {
771 private:
772  const _INDEX_TYPE *range; //< range table
773 
774 protected:
775  virtual void print_header(OStream &O, std::size_t first, std::size_t last) const {
776  O << ' ';
777  std::size_t i;
778  for(i = first; i < last && i < this->table_size; ++i ) {
779  O << setw(5) << range[i] << ']';
780  }
781  if (i == this->table_size) {
782  O << '(' << setw(4) << range[this->table_size-1];
783  }
784  O << nl;
785  }
786 
787 public:
788  /**
789  * Create a new statistics distribution.
790  * @param[in] name name of the variable
791  * @param[in] description description of the variable
792  * @param[in] parent parent group.
793  * @param[in] range range header
794  * @param[in] range_size size of the range array
795  * @param[in] init initial value of the distribution table entries
796  */
797  StatDistRange(const char* name, const char* description, StatGroup &parent,
798  const _INDEX_TYPE range[], const int range_size, _COUNT_TYPE init)
799  : StatDistAbst<_COUNT_TYPE,_INDEX_TYPE>(name, description, parent,
800  range_size, init),
801  range(range) {}
802 
803  /// index operator
804  inline _COUNT_TYPE& operator[](const _INDEX_TYPE v) {
805  for (std::size_t i = 0; i < this->table_size; ++i ) {
806  if (v <= range[i])
807  return this->table[i];
808  }
809  return this->table[this->table_size];
810  }
811 };
812 
813 /**
814  * Statistics Variable.
815  */
816 template<typename _T, _T init>
817 class StatVar : public StatEntry {
818 private:
819  _T var; //< variable
820 public:
821  /**
822  * Create a new statistics variable.
823  * @param[in] name name of the variable
824  * @param[in] description description of the variable
825  * @param[in] group parent group.
826  */
827  StatVar(const char* name, const char* description, StatGroup &parent)
828  : StatEntry(name, description), var(init) {
829  parent.add(this);
830  }
831 
832  virtual unsigned long get_value() const {
833  return (unsigned long)var;
834  }
835 
836  _T get() const {
837  return var;
838  }
839 
840  void print(OStream &O) const {
841  O << setw(30) << name
842  << setw(10) << var
843  << " : " << description << nl;
844  }
845  virtual void print_csv_intern(OStream &O,StatStack &s) const {
846  print_csv_entry(O,s,get_value());
847  }
848  /// maximum
849  inline StatVar& max(const _T& i) {
850  if (i > var)
851  var = i;
852  return *this;
853  }
854 
855  /// mininum
856  inline StatVar& min(const _T& i) {
857  if (i < var)
858  var = i;
859  return *this;
860  }
861 
862  /// prefix operator
863  inline StatVar& operator++() {
864  ++var;
865  return *this;
866  }
867  /// postfix operator
868  inline StatVar operator++(int) {
869  StatVar copy(*this);
870  ++var;
871  return copy;
872  }
873  /// increment operator
874  inline StatVar& operator+=(const _T& i) {
875  var+=i;
876  return *this;
877  }
878  /// prefix operator
879  inline StatVar& operator--() {
880  --var;
881  return *this;
882  }
883  /// postfix operator
884  inline StatVar operator--(int) {
885  StatVar copy(*this);
886  --var;
887  return copy;
888  }
889  /// decrement operator
890  inline StatVar& operator-=(const _T& i) {
891  var-=i;
892  return *this;
893  }
894 
895  /// assignment operator
896  inline StatVar& operator=(const _T& i) {
897  var=i;
898  return *this;
899  }
900 };
901 
902 /** @} */
903 
904 } // end namespace cacao
905 
906 /* statistic macros ***********************************************************/
907 
908 #define STAT_DECLARE_VAR(type, var, init) \
909  extern cacao::StatVar<type,init> var;
910 
911 #define STAT_REGISTER_VAR_EXTERN(type, var, init, name, description) \
912  cacao::StatVar<type,init> var(name,description,cacao::StatGroup::root());
913 
914 #define STAT_REGISTER_GROUP_VAR_EXTERN(type, var, init, name, description, group) \
915  cacao::StatVar<type,init> var(name,description,group##_group());
916 
917 #define STAT_REGISTER_VAR(type, var, init, name, description) \
918  static cacao::StatVar<type,init> var(name,description,cacao::StatGroup::root());
919 
920 #define STAT_REGISTER_GROUP_VAR(type, var, init, name, description, group) \
921  static cacao::StatVar<type,init> var(name,description,group##_group());
922 
923 #define STAT_REGISTER_DIST(counttype, indextype, var, start, end, step, init, name, description) \
924  static cacao::StatDist<counttype,indextype,step> var(name,description,cacao::StatGroup::root(),start,end,init);
925 
926 #define STAT_REGISTER_DIST_RANGE(counttype, indextype, var, range, range_size, init, name, description) \
927  static cacao::StatDistRange<counttype,indextype> var(name,description,cacao::StatGroup::root(),range,range_size,init);
928 
929 #define STAT_DECLARE_GROUP(var) \
930  cacao::StatGroup& var##_group();
931 
932 #define STAT_DECLARE_SUM_GROUP(var) \
933  cacao::StatSumGroup& var##_group();
934 
935 #define STAT_REGISTER_GROUP(var,name,description) \
936  cacao::StatGroup& var##_group() { \
937  static cacao::StatGroup var(name,description,cacao::StatGroup::root());\
938  return var; \
939  }
940 
941 #define STAT_REGISTER_SUM_GROUP(var,name,description) \
942  cacao::StatSumGroup& var##_group() { \
943  static cacao::StatSumGroup var(name,description, \
944  cacao::StatGroup::root()); \
945  return var; \
946  }
947 
948 #define STAT_REGISTER_SUM_SUBGROUP(var,name,description,group) \
949  cacao::StatSumGroup& var##_group() { \
950  static cacao::StatSumGroup var(name,description, group##_group()); \
951  return var; \
952  }
953 
954 #define STAT_REGISTER_SUBGROUP(var,name,description,group) \
955  cacao::StatGroup& var##_group() { \
956  static cacao::StatGroup var(name,description, group##_group()); \
957  return var; \
958  }
959 
960 #define STATISTICS(x) do { x; } while (0)
961 
962 #else
963 #define STAT_DECLARE_VAR(type, var, init)
964 #define STAT_REGISTER_VAR_EXTERN(type, var, init, name, description)
965 #define STAT_REGISTER_GROUP_VAR_EXTERN(type, var, init, name, description, group)
966 #define STAT_REGISTER_VAR(type, var, init, name, description)
967 #define STAT_REGISTER_GROUP_VAR(type, var, init, name, description, group)
968 #define STAT_REGISTER_DIST(counttype, indextype, var, start, end, step, init, name, description)
969 #define STAT_REGISTER_DIST_RANGE(counttype, indextype, var, range, range_size, init, name, description)
970 #define STAT_DECLARE_GROUP(var)
971 #define STAT_REGISTER_GROUP(var,name,description)
972 #define STAT_REGISTER_SUM_GROUP(var,name,description)
973 #define STAT_REGISTER_SUM_SUBGROUP(var,name,description,group)
974 #define STAT_REGISTER_SUBGROUP(var,name,description,group)
975 #define STATISTICS(x) /* nothing */
976 #endif
977 
978 #ifdef ENABLE_STATISTICS
979 
980 /// @cond
981 // exclude from doxygen
982 
983 /* function prototypes ********************************************************/
984 
985 void loadingtime_start(void);
986 void loadingtime_stop(void);
987 void compilingtime_start(void);
988 void compilingtime_stop(void);
989 
990 #if 0
991 void statistics_print_date(void);
992 void statistics_print_memory_usage(void);
993 void statistics_print_gc_memory_usage(void);
994 #endif
995 
996 /// @endcond
997 // end exclude from doxygen
998 
999 #endif /* ENABLE_STATISTICS */
1000 
1001 #endif // STATISTICS_HPP_
1002 
1003 
1004 /*
1005  * These are local overrides for various environment variables in Emacs.
1006  * Please do not remove this and leave it at the end of the file, where
1007  * Emacs will automagically detect them.
1008  * ---------------------------------------------------------------------
1009  * Local variables:
1010  * mode: c++
1011  * indent-tabs-mode: t
1012  * c-basic-offset: 4
1013  * tab-width: 4
1014  * End:
1015  * vim:noexpandtab:sw=4:ts=4:
1016  */
static SetWidth setw(size_t w)
Definition: OStream.hpp:395
#define max(a, b)
Definition: lsra.hpp:80
JNIEnv jclass jobject const char * name
Definition: jvmti.h:312
static SetPrecision setprecision(int p)
Definition: OStream.hpp:401
OptionPrefix & root()
Definition: Option.cpp:34
#define min(a, b)
Definition: lsra.hpp:79
MIIterator i
MIIterator e
void compilingtime_start(void)
Definition: statistics.cpp:81
void loadingtime_stop(void)
Definition: statistics.cpp:65
Nl nl
Definition: OStream.cpp:56
LoopTreeGraph * parent
void compilingtime_stop(void)
Definition: statistics.cpp:96
void loadingtime_start(void)
Definition: statistics.cpp:49