source: u8u16/tags/u8u16-0.92/Profiling/BOM_Profiler.c @ 5877

Last change on this file since 5877 was 5877, checked in by cameron, 14 months ago

Adding old u8u16 for Teradata

File size: 5.0 KB
Line 
1/*
2    BOM_Profiler.c - Binary Order of Magnitude Execution Time Profiler
3    Copyright (C) 2006, 2007  Robert D. Cameron
4    Version 0.2
5    Licensed to the general public under Academic Free License version 3.0
6
7BOM_Profiler provides a lightweight multiplatform execution time profiling
8utility based on processor cycle counters.  It uses a binary logarithmic
9histogram technique that is useful in both highlighting patterns of
10cycle time distributions as well as identifing outliers in timing events
11due to interruptions for operating system services.
12
13In essence, BOM profiler is designed to collect statistics over a number
14of repetitions of particular timed events.  Statistics are gathered in the
15form of a logarithmic histogram of cycle times for processing a fixed number
16of elements between calls to start_BOM_interval and end_BOM_interval. 
17For example, an interval may correspond to processing 1024 single-byte
18elements by a particular routine.
19
20A timer t is created and initialized by a call to t = init_BOM_timer(n), where
21n is the number of elements to be processed per interval.  Given a timer t,
22start_BOM_interval(t) initiates an interval measurement which completes
23with end_BOM_interval(t).  Between these events, a process may be interrupted
24and resumed arbitrarily with pause_BOM_timer(t) and resume_BOM_timer(t).
25
26dump_BOM_table(t) prints out a rudimentary histogram of the recorded
27intervals for a particular timer. 
28
29Although the basic concept of BOM_Profiler is architecture independent,
30processor-dependent routines for accessing time-stamp counters and
31determining the binary order of magnitude are included through external
32files.
33
34
35*/
36
37#ifndef BOM_Profiler_loaded
38#define BOM_Profiler_loaded 1
39
40#ifdef __i386
41#include "i386_timer.c"
42#endif
43#ifdef _ARCH_PPC
44#include "ppc_timer.c"
45#endif
46
47#define BIT_COUNT 64
48
49struct BOM_Table {
50  // an array of counts and timings per binary order of magnitude
51  int BOM_count[BIT_COUNT];
52  unsigned long long int BOM_total_time[BIT_COUNT];
53  // current timing interval information
54  int timer_on;
55  unsigned long long int accumulated_cycles; 
56  unsigned long long int current_timestamp;
57  unsigned int elements_per_BOM_interval;
58};
59
60typedef struct BOM_Table BOM_Table;
61
62BOM_Table * init_BOM_timer (unsigned int elems_per_interval) {
63  BOM_Table * timer_table = (BOM_Table *) malloc(sizeof(BOM_Table));
64  if (!timer_table) {
65    printf("Couldn't initialize BOM timer.\n");
66    exit(-1);
67  }
68  int i;
69  for (i = 0; i < BIT_COUNT; i++) {
70    timer_table -> BOM_count[i] = 0;
71    timer_table -> BOM_total_time[i] = 0ULL;
72  }
73  timer_table -> timer_on = 0;
74  timer_table -> accumulated_cycles = 0ULL;
75  timer_table -> current_timestamp = 0ULL;
76  timer_table -> elements_per_BOM_interval = elems_per_interval;
77  return timer_table;
78}
79
80
81void start_BOM_interval(BOM_Table * timer_table);
82void pause_BOM_timer(BOM_Table * timer_table);
83void resume_BOM_timer(BOM_Table * timer_table);
84void end_BOM_interval(BOM_Table * timer_table);
85
86void start_BOM_interval(BOM_Table * timer_table) {
87  timer_table->timer_on = 1;
88  timer_table->accumulated_cycles = 0ULL;
89  timer_table->current_timestamp = read_cycle_counter();
90}
91
92void pause_BOM_timer(BOM_Table * timer_table) {
93  if (timer_table->timer_on) {
94    timer_table->accumulated_cycles += read_cycle_counter() - timer_table->current_timestamp;
95    timer_table->timer_on = 0;
96  }
97}
98
99void resume_BOM_timer(BOM_Table * timer_table) {
100  timer_table->timer_on = 1;
101  timer_table->current_timestamp = read_cycle_counter();
102} 
103
104void end_BOM_interval(BOM_Table * timer_table) {
105  if (timer_table->timer_on) {
106    timer_table->accumulated_cycles += 
107      read_cycle_counter() - timer_table->current_timestamp;
108    timer_table->timer_on = 0;
109  }
110  if (timer_table->accumulated_cycles > 0ULL) {
111    int BOM = binary_order_of_magnitude(timer_table->accumulated_cycles);
112    timer_table->BOM_count[BOM]++;
113    timer_table->BOM_total_time[BOM] += timer_table->accumulated_cycles;
114    timer_table->accumulated_cycles = 0ULL;
115  }
116}
117
118void dump_BOM_table(BOM_Table * timer_table) {
119  int BOM;
120  int this_count;
121  int cum_count = 0;
122  unsigned long long int this_time;
123  unsigned long long int cum_time = 0ULL;
124  unsigned long long int this_avg;
125  unsigned long long int cum_avg;
126  unsigned int elems = timer_table -> elements_per_BOM_interval;
127  printf("Binary Order of Magnitude Profile\n");
128  for (BOM = 0; BOM < BIT_COUNT; BOM++) {
129    this_count = timer_table -> BOM_count[BOM];
130    cum_count += this_count;
131    this_time = timer_table -> BOM_total_time[BOM];
132    cum_time += this_time;
133    if (this_count == 0) this_avg = 0ULL;
134    else this_avg = (1000*this_time)/(this_count * elems);
135    if (cum_count == 0) cum_avg = 0ULL;
136    else cum_avg = (1000*cum_time)/(cum_count * elems);
137    if (this_count > 0) {  // Only report intervals with nonzero counts.
138      printf("BOM %i: %i ", BOM, this_count);
139      printf("(avg time: %i %s/kElem) ", (int) this_avg, cycle_counter_units);
140      printf("Cumulative: %i ", cum_count);
141      printf("(avg: %i %s/kElem)\n", (int) cum_avg, cycle_counter_units);
142    }
143  }           
144}
145#endif
Note: See TracBrowser for help on using the repository browser.