iPXE
Functions | Variables
profile.c File Reference

Profiling. More...

#include <stdint.h>
#include <stdio.h>
#include <strings.h>
#include <limits.h>
#include <assert.h>
#include <ipxe/isqrt.h>
#include <ipxe/profile.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static const char * profile_hex_fraction (signed long long value, unsigned int shift)
 Format a hex fraction (for debugging) More...
 
static unsigned int profile_mean_shift (struct profiler *profiler)
 Calculate bit shift for mean sample value. More...
 
static unsigned int profile_accvar_shift (struct profiler *profiler)
 Calculate bit shift for accumulated variance value. More...
 
void profile_update (struct profiler *profiler, unsigned long sample)
 Update profiler with a new sample. More...
 
unsigned long profile_mean (struct profiler *profiler)
 Get mean sample value. More...
 
unsigned long profile_variance (struct profiler *profiler)
 Get sample variance. More...
 
unsigned long profile_stddev (struct profiler *profiler)
 Get sample standard deviation. More...
 

Variables

unsigned long profile_excluded
 Accumulated time excluded from profiling. More...
 

Detailed Description

Profiling.

The profiler computes basic statistics (mean, variance, and standard deviation) for the samples which it records. Note that these statistics need not be completely accurate; it is sufficient to give a rough approximation.

The algorithm for updating the mean and variance estimators is from The Art of Computer Programming (via Wikipedia), with adjustments to avoid the use of floating-point instructions.

Definition in file profile.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ profile_hex_fraction()

static const char* profile_hex_fraction ( signed long long  value,
unsigned int  shift 
)
static

Format a hex fraction (for debugging)

Parameters
valueValue
shiftBit shift
Return values
stringFormatted hex fraction

Definition at line 58 of file profile.c.

59  {
60  static char buf[23] = "-"; /* -0xXXXXXXXXXXXXXXXX.XX + NUL */
61  unsigned long long int_part;
62  uint8_t frac_part;
63  char *ptr;
64 
65  if ( value < 0 ) {
66  value = -value;
67  ptr = &buf[0];
68  } else {
69  ptr = &buf[1];
70  }
71  int_part = ( value >> shift );
72  frac_part = ( value >> ( shift - ( 8 * sizeof ( frac_part ) ) ) );
73  snprintf ( &buf[1], ( sizeof ( buf ) - 1 ), "%#llx.%02x",
74  int_part, frac_part );
75  return ptr;
76 }
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
unsigned char uint8_t
Definition: stdint.h:10
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382

References snprintf(), and value.

Referenced by profile_update().

◆ profile_mean_shift()

static unsigned int profile_mean_shift ( struct profiler profiler)
inlinestatic

Calculate bit shift for mean sample value.

Parameters
profilerProfiler
Return values
shiftBit shift

Definition at line 84 of file profile.c.

84  {
85 
86  return ( ( ( 8 * sizeof ( profiler->mean ) ) - 1 ) /* MSB */
87  - 1 /* Leave sign bit unused */
88  - profiler->mean_msb );
89 }
A data structure for storing profiling information.
Definition: profile.h:26
unsigned int mean_msb
Mean sample value MSB.
Definition: profile.h:42
unsigned long mean
Mean sample value (scaled)
Definition: profile.h:36

References profiler::mean, and profiler::mean_msb.

Referenced by profile_mean(), and profile_update().

◆ profile_accvar_shift()

static unsigned int profile_accvar_shift ( struct profiler profiler)
inlinestatic

Calculate bit shift for accumulated variance value.

Parameters
profilerProfiler
Return values
shiftBit shift

Definition at line 97 of file profile.c.

97  {
98 
99  return ( ( ( 8 * sizeof ( profiler->accvar ) ) - 1 ) /* MSB */
100  - 1 /* Leave top bit unused */
101  - profiler->accvar_msb );
102 }
unsigned long long accvar
Accumulated variance (scaled)
Definition: profile.h:44
A data structure for storing profiling information.
Definition: profile.h:26
unsigned int accvar_msb
Accumulated variance MSB.
Definition: profile.h:50

References profiler::accvar, and profiler::accvar_msb.

Referenced by profile_update(), and profile_variance().

◆ profile_update()

void profile_update ( struct profiler profiler,
unsigned long  sample 
)

Update profiler with a new sample.

Parameters
profilerProfiler
sampleSample value

Definition at line 110 of file profile.c.

110  {
111  unsigned int sample_msb;
112  unsigned int mean_shift;
113  unsigned int delta_shift;
114  signed long pre_delta;
115  signed long post_delta;
116  signed long long accvar_delta;
117  unsigned int accvar_delta_shift;
118  unsigned int accvar_delta_msb;
119  unsigned int accvar_shift;
120 
121  /* Our scaling logic assumes that sample values never overflow
122  * a signed long (i.e. that the high bit is always zero).
123  */
124  assert ( ( ( signed ) sample ) >= 0 );
125 
126  /* Update sample count, limiting to avoid signed overflow */
127  if ( profiler->count < INT_MAX )
128  profiler->count++;
129 
130  /* Adjust mean sample value scale if necessary. Skip if
131  * sample is zero (in which case flsl(sample)-1 would
132  * underflow): in the case of a zero sample we have no need to
133  * adjust the scale anyway.
134  */
135  if ( sample ) {
136  sample_msb = ( flsl ( sample ) - 1 );
137  if ( profiler->mean_msb < sample_msb ) {
138  profiler->mean >>= ( sample_msb - profiler->mean_msb );
139  profiler->mean_msb = sample_msb;
140  }
141  }
142 
143  /* Scale sample to internal units */
144  mean_shift = profile_mean_shift ( profiler );
145  sample <<= mean_shift;
146 
147  /* Update mean */
148  pre_delta = ( sample - profiler->mean );
149  profiler->mean += ( pre_delta / ( ( signed ) profiler->count ) );
150  post_delta = ( sample - profiler->mean );
151  delta_shift = mean_shift;
152  DBGC ( profiler, "PROFILER %p sample %#lx mean %s", profiler,
153  ( sample >> mean_shift ),
154  profile_hex_fraction ( profiler->mean, mean_shift ) );
155  DBGC ( profiler, " pre %s",
156  profile_hex_fraction ( pre_delta, delta_shift ) );
157  DBGC ( profiler, " post %s\n",
158  profile_hex_fraction ( post_delta, delta_shift ) );
159 
160  /* Scale both deltas to fit in half of an unsigned long long
161  * to avoid potential overflow on multiplication. Note that
162  * shifting a signed quantity is "implementation-defined"
163  * behaviour in the C standard, but gcc documents that it will
164  * always perform sign extension.
165  */
166  if ( sizeof ( pre_delta ) > ( sizeof ( accvar_delta ) / 2 ) ) {
167  unsigned int shift = ( 8 * ( sizeof ( pre_delta ) -
168  ( sizeof ( accvar_delta ) / 2 ) ));
169  pre_delta >>= shift;
170  post_delta >>= shift;
171  delta_shift -= shift;
172  }
173 
174  /* Update variance, if applicable. Skip if either delta is
175  * zero (in which case flsl(delta)-1 would underflow): in the
176  * case of a zero delta there is no change to the accumulated
177  * variance anyway.
178  */
179  if ( pre_delta && post_delta ) {
180 
181  /* Calculate variance delta */
182  accvar_delta = ( ( ( signed long long ) pre_delta ) *
183  ( ( signed long long ) post_delta ) );
184  accvar_delta_shift = ( 2 * delta_shift );
185  assert ( accvar_delta > 0 );
186 
187  /* Calculate variance delta MSB, using flsl() on each
188  * delta individually to provide an upper bound rather
189  * than requiring the existence of flsll().
190  */
191  accvar_delta_msb = ( flsll ( accvar_delta ) - 1 );
192  if ( accvar_delta_msb > accvar_delta_shift ) {
193  accvar_delta_msb -= accvar_delta_shift;
194  } else {
195  accvar_delta_msb = 0;
196  }
197 
198  /* Adjust scales as necessary */
199  if ( profiler->accvar_msb < accvar_delta_msb ) {
200  /* Rescale accumulated variance */
201  profiler->accvar >>= ( accvar_delta_msb -
202  profiler->accvar_msb );
203  profiler->accvar_msb = accvar_delta_msb;
204  } else {
205  /* Rescale variance delta */
206  accvar_delta >>= ( profiler->accvar_msb -
207  accvar_delta_msb );
208  accvar_delta_shift -= ( profiler->accvar_msb -
209  accvar_delta_msb );
210  }
211 
212  /* Scale delta to internal units */
213  accvar_shift = profile_accvar_shift ( profiler );
214  accvar_delta <<= ( accvar_shift - accvar_delta_shift );
215 
216  /* Accumulate variance */
217  profiler->accvar += accvar_delta;
218 
219  /* Adjust scale if necessary */
220  if ( profiler->accvar &
221  ( 1ULL << ( ( 8 * sizeof ( profiler->accvar ) ) - 1 ) ) ) {
222  profiler->accvar >>= 1;
223  profiler->accvar_msb++;
224  accvar_delta >>= 1;
225  accvar_shift--;
226  }
227 
228  DBGC ( profiler, "PROFILER %p accvar %s", profiler,
229  profile_hex_fraction ( profiler->accvar, accvar_shift ));
230  DBGC ( profiler, " delta %s\n",
231  profile_hex_fraction ( accvar_delta, accvar_shift ) );
232  }
233 }
static unsigned int profile_mean_shift(struct profiler *profiler)
Calculate bit shift for mean sample value.
Definition: profile.c:84
#define DBGC(...)
Definition: compiler.h:505
unsigned long long accvar
Accumulated variance (scaled)
Definition: profile.h:44
#define flsll(x)
Find last (i.e.
Definition: strings.h:148
A data structure for storing profiling information.
Definition: profile.h:26
unsigned int mean_msb
Mean sample value MSB.
Definition: profile.h:42
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
unsigned int count
Number of samples.
Definition: profile.h:34
#define flsl(x)
Find last (i.e.
Definition: strings.h:157
#define INT_MAX
Definition: limits.h:37
unsigned int accvar_msb
Accumulated variance MSB.
Definition: profile.h:50
unsigned long mean
Mean sample value (scaled)
Definition: profile.h:36
static const char * profile_hex_fraction(signed long long value, unsigned int shift)
Format a hex fraction (for debugging)
Definition: profile.c:58
static unsigned int profile_accvar_shift(struct profiler *profiler)
Calculate bit shift for accumulated variance value.
Definition: profile.c:97

References profiler::accvar, profiler::accvar_msb, assert(), profiler::count, DBGC, flsl, flsll, INT_MAX, profiler::mean, profiler::mean_msb, profile_accvar_shift(), profile_hex_fraction(), and profile_mean_shift().

Referenced by profile_custom(), profile_okx(), and profile_stop_at().

◆ profile_mean()

unsigned long profile_mean ( struct profiler profiler)

Get mean sample value.

Parameters
profilerProfiler
Return values
meanMean sample value

Definition at line 241 of file profile.c.

241  {
242  unsigned int mean_shift = profile_mean_shift ( profiler );
243 
244  /* Round to nearest and scale down to original units */
245  return ( ( profiler->mean + ( 1UL << ( mean_shift - 1 ) ) )
246  >> mean_shift );
247 }
static unsigned int profile_mean_shift(struct profiler *profiler)
Calculate bit shift for mean sample value.
Definition: profile.c:84
A data structure for storing profiling information.
Definition: profile.h:26
unsigned long mean
Mean sample value (scaled)
Definition: profile.h:36

References profiler::mean, and profile_mean_shift().

Referenced by cipher_cost(), digest_cost(), memcpy_test_speed(), profile_okx(), profstat(), and tcpip_random_okx().

◆ profile_variance()

unsigned long profile_variance ( struct profiler profiler)

Get sample variance.

Parameters
profilerProfiler
Return values
varianceSample variance

Definition at line 255 of file profile.c.

255  {
256  unsigned int accvar_shift = profile_accvar_shift ( profiler );
257 
258  /* Variance is zero if fewer than two samples exist (avoiding
259  * division by zero error).
260  */
261  if ( profiler->count < 2 )
262  return 0;
263 
264  /* Calculate variance, round to nearest, and scale to original units */
265  return ( ( ( profiler->accvar / ( profiler->count - 1 ) )
266  + ( 1ULL << ( accvar_shift - 1 ) ) ) >> accvar_shift );
267 }
unsigned long long accvar
Accumulated variance (scaled)
Definition: profile.h:44
A data structure for storing profiling information.
Definition: profile.h:26
unsigned int count
Number of samples.
Definition: profile.h:34
static unsigned int profile_accvar_shift(struct profiler *profiler)
Calculate bit shift for accumulated variance value.
Definition: profile.c:97

References profiler::accvar, profiler::count, and profile_accvar_shift().

Referenced by profile_stddev().

◆ profile_stddev()

unsigned long profile_stddev ( struct profiler profiler)

Get sample standard deviation.

Parameters
profilerProfiler
Return values
stddevSample standard deviation

Definition at line 275 of file profile.c.

275  {
276 
277  return isqrt ( profile_variance ( profiler ) );
278 }
unsigned long isqrt(unsigned long value)
Find integer square root.
Definition: isqrt.c:40
A data structure for storing profiling information.
Definition: profile.h:26
unsigned long profile_variance(struct profiler *profiler)
Get sample variance.
Definition: profile.c:255

References isqrt(), and profile_variance().

Referenced by memcpy_test_speed(), profile_okx(), profstat(), and tcpip_random_okx().

Variable Documentation

◆ profile_excluded

unsigned long profile_excluded

Accumulated time excluded from profiling.

Definition at line 49 of file profile.c.

Referenced by profile_exclude(), profile_start_at(), profile_started(), profile_stop_at(), and profile_stopped().