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)
 
 FILE_SECBOOT (PERMITTED)
 
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  )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED  )

◆ 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 59 of file profile.c.

60  {
61  static char buf[23] = "-"; /* -0xXXXXXXXXXXXXXXXX.XX + NUL */
62  unsigned long long int_part;
63  uint8_t frac_part;
64  char *ptr;
65 
66  if ( value < 0 ) {
67  value = -value;
68  ptr = &buf[0];
69  } else {
70  ptr = &buf[1];
71  }
72  int_part = ( value >> shift );
73  frac_part = ( value >> ( shift - ( 8 * sizeof ( frac_part ) ) ) );
74  snprintf ( &buf[1], ( sizeof ( buf ) - 1 ), "%#llx.%02x",
75  int_part, frac_part );
76  return ptr;
77 }
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:383

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 85 of file profile.c.

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

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 98 of file profile.c.

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

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 111 of file profile.c.

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

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 242 of file profile.c.

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

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 256 of file profile.c.

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

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 276 of file profile.c.

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

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 50 of file profile.c.

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