source: trunk/lib/perflib/BOM_Profiler.h @ 4063

Last change on this file since 4063 was 2479, checked in by lindanl, 7 years ago

Change to static functions.

File size: 6.5 KB
RevLine 
[462]1/*
2    BOM_Profiler.h - Binary Order of Magnitude Execution Time Profiler
3    Copyright (C) 2010  Robert D. Cameron and Dan Lin
4    Version 0.4
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(). 
21Given a timer t, start_BOM_interval(t) initiates an interval measurement
22which completes with end_BOM_interval(t, n), where n is the number of
23elements processed. 
24
25dump_BOM_table(t) prints out a rudimentary histogram of the recorded
26intervals for a particular timer. 
27
28Although the basic concept of BOM_Profiler is architecture independent,
29processor-dependent routines for accessing time-stamp counters and
30determining the binary order of magnitude are included through external
31files.
32
33
34*/
35
36#ifndef BOM_Profiler_H
37#define BOM_Profiler_H
38
39#include "i386_timer.h"
40
41#define BIT_COUNT 64
42#define MAX_TIMER_ENTRIES (1<<18)
43#define TIMER_SCALE_FACTOR 1000
44
45struct BOM_Table {
46  // current timing interval information
47  int timer_on;
48  int full;
49  timestamp_t interval_start[MAX_TIMER_ENTRIES];
50  timestamp_t interval_end[MAX_TIMER_ENTRIES];
51  unsigned int interval_elems[MAX_TIMER_ENTRIES]; 
52  unsigned int current_entry;
53};
54
55typedef struct BOM_Table BOM_Table;
56
[2479]57static inline BOM_Table * init_BOM_timer () {
[462]58  BOM_Table * timer_table = (BOM_Table *) malloc(sizeof(BOM_Table));
59  if (!timer_table) {
60    printf("Couldn't initialize BOM timer.\n");
61    exit(-1);
62  }
63  timer_table -> current_entry = 0;
64  timer_table -> full = 0;
65  timer_table -> timer_on = 0;
66  return timer_table;
67}
68
69
70static inline void start_BOM_interval(BOM_Table * timer_table) {
71  timer_table->timer_on = 1;
72  timer_table->interval_start[timer_table->current_entry] = read_cycle_counter();
73}
74
75static inline void end_BOM_interval(BOM_Table * timer_table, unsigned int elems) {
76  if (timer_table->timer_on) {
77    timer_table->interval_end[timer_table->current_entry] = read_cycle_counter();
78    timer_table->interval_elems[timer_table->current_entry] = elems;
79    timer_table->current_entry++;
80    if(timer_table->current_entry >= MAX_TIMER_ENTRIES) {
81      timer_table->full=1;
82      timer_table->current_entry=0;
83    }
84    timer_table->timer_on = 0;
85  }
86  else
87        fprintf(stderr,"Time interval end without a start!\n"); 
88}
89
[472]90#define SEQ_TIMESTAMP_COUNT 8
91
[2479]92static void dump_BOM_table(BOM_Table * timer_table) {
[462]93  // an array of counts and timings per binary order of magnitude
94  int BOM_count[BIT_COUNT];
95  unsigned int BOM_elems[BIT_COUNT]; 
96  timestamp_t BOM_total_time[BIT_COUNT];
[472]97  int i, BOM, b;
[462]98  int this_count;
[552]99  int total_count = 0;
[462]100  int cum_count = 0;
101  unsigned int entry = 0;
102  unsigned int total_entries;
103  unsigned int this_elems = 0;
104  unsigned int cum_elems = 0;
105  timestamp_t this_time;
106  timestamp_t cum_time = 0ULL;
107  timestamp_t this_avg;
108  timestamp_t cum_avg;
109  timestamp_t accumulated_cycles; 
[472]110  timestamp_t sequential_stamps[SEQ_TIMESTAMP_COUNT];
111  timestamp_t timestamp_overhead;
[462]112
[472]113/*  Calculate minimum overhead of timestamps.  */
114
115  sequential_stamps[0] = read_cycle_counter();
116  sequential_stamps[1] = read_cycle_counter();
117  sequential_stamps[2] = read_cycle_counter();
118  sequential_stamps[3] = read_cycle_counter();
119  sequential_stamps[4] = read_cycle_counter();
120  sequential_stamps[5] = read_cycle_counter();
121  sequential_stamps[6] = read_cycle_counter();
122  sequential_stamps[7] = read_cycle_counter();
123  timestamp_overhead = sequential_stamps[1] - sequential_stamps[0];
124  for (i = 2; i < SEQ_TIMESTAMP_COUNT; i++) {
125    if (sequential_stamps[i] - sequential_stamps[i-1] < timestamp_overhead)
126         timestamp_overhead = sequential_stamps[i] - sequential_stamps[i-1];
127  }
128//  fprintf(stderr, "timestamp_overhead = %i\n", timestamp_overhead);
129
130
[462]131  for (b = 0; b < BIT_COUNT; b++) {
132        BOM_count[b] = 0;
133        BOM_elems[b] = 0;
134        BOM_total_time[b] = 0;
135  }
136
137
138  total_entries = timer_table->full ? MAX_TIMER_ENTRIES : timer_table->current_entry;
139  for(entry = 0; entry < total_entries; entry++){
[472]140        accumulated_cycles = timer_table->interval_end[entry] - timer_table->interval_start[entry] - timestamp_overhead;
[462]141        if (accumulated_cycles > 0ULL) {
142//        cout << "accumulated_cycles =" << accumulated_cycles << "; elems = " << timer_table->interval_elems[entry] << endl;
143            BOM = binary_order_of_magnitude(accumulated_cycles*TIMER_SCALE_FACTOR/timer_table->interval_elems[entry]);
144            BOM_count[BOM]++;
145            BOM_elems[BOM] += timer_table->interval_elems[entry];
146            BOM_total_time[BOM] += accumulated_cycles;
147        }
148  }
[552]149#ifdef PERF_SCRIPT 
[462]150  for (b = 0; b < BIT_COUNT; b++) {
[552]151    total_count += BOM_count[b];
152  }
153#endif 
154//   printf("Binary Order of Magnitude Profile\n");
155  for (b = 0; b < BIT_COUNT; b++) {
[462]156    this_count = BOM_count[b];
157    cum_count += this_count;
158    this_time = BOM_total_time[b];
159    cum_time += this_time;
160    this_elems = BOM_elems[b];
161    cum_elems += this_elems;
162    if (this_count == 0) this_avg = 0ULL;
163    else this_avg = (TIMER_SCALE_FACTOR*this_time)/(this_elems);
164    if (cum_count == 0) cum_avg = 0ULL;
165    else cum_avg = (TIMER_SCALE_FACTOR*cum_time)/(cum_elems);
[552]166
167#ifndef PERF_SCRIPT
[462]168    if (this_count > 0) {  // Only report intervals with nonzero counts.
169      printf("BOM %i: %i ", b, this_count);
170      printf("(avg time: %i %s/kElem) ", (int) this_avg, cycle_counter_units);
171      printf("Cumulative: %i ", cum_count);
172      printf("(avg: %i %s/kElem)\n", (int) cum_avg, cycle_counter_units);
173    }
[552]174#endif
175#ifdef PERF_SCRIPT
176    if (cum_count>total_count*0.9){
[2207]177      fprintf(stderr,"%lu ",cum_avg);
[552]178      break;
179    }
180#endif
[462]181  }           
182}
[476]183
[2479]184static inline void destroy_BOM_timer(BOM_Table * timer_table) {
[476]185        if(timer_table) {
[477]186                free(timer_table);
[476]187        }
188       
189}
190
[462]191#endif
Note: See TracBrowser for help on using the repository browser.