# profiler.h – performance profiling

Most of this module is only usable on certain platforms, while `timeit` functions is available on all platforms. The only platforms that can access the whole module is x86-64 and ARM64 on Unix type systems.

## Timer based on clock

void timeit_start(timeit_t t)
void timeit_stop(timeit_t t)
void timeit_print(timeit_t t, ulong reps)

  Gives wall and user time - useful for parallel programming.

  Example usage:

      timeit_t t0;
      timeit_start(t0);
      // do stuff, take some time
      timeit_stop(t0);
      timeit_print(t0, 1); // only one repetition was done

TIMEIT_REPEAT(timer, reps)
TIMEIT_END_REPEAT(timer, reps)

  Repeatedly runs the code between the `TIMEIT_REPEAT` and the `TIMEIT_END_REPEAT` markers, automatically increasing the number of repetitions until the elapsed time exceeds the timer resolution. The macro takes as input a predefined `timeit_t` object and an integer variable to hold the number of repetitions.

TIMEIT_START
TIMEIT_STOP

  Repeatedly runs the code between the `TIMEIT_START` and the `TIMEIT_STOP` markers, automatically increasing the number of repetitions until the elapsed time exceeds the timer resolution, and then prints the average elapsed cpu and wall time for a single repetition.

TIMEIT_ONCE_START
TIMEIT_ONCE_STOP

  Runs the code between the `TIMEIT_ONCE_START` and the `TIMEIT_ONCE_STOP` markers exactly once and then prints the elapsed cpu and wall time. This does not give a precise measurement if the elapsed time is short compared to the timer resolution.

## Timer based on cycle counter

void init_clock(int n)
void init_all_clocks(void)
void start_clock(int n)
void stop_clock(int n)
double get_clock(int n)

  Gives time based on cycle counter.

  First one must ensure the processor speed in cycles per second is set correctly in `profiler.h`, in the macro definition `#define FLINT_CLOCKSPEED`.

  One can access the cycle counter directly by `get_cycle_counter()` which returns the current cycle counter as a `double`.

  A sample usage of clocks is:

      init_all_clocks();
      start_clock(n);
      // do something
      stop_clock(n);
      flint_printf("Time in seconds is %f.3\n", get_clock(n));

  where `n` is a clock number (from 0-19 by default). The number of clocks can be changed by altering `FLINT_NUM_CLOCKS`. One can also initialise an individual clock with `init_clock(n)`.

void prof_repeat(double *min, double *max, profile_target_t target, void *arg)

  Allows one to automatically time a given function. Here is a sample usage:

  Suppose one has a function one wishes to profile:

      void myfunc(ulong a, ulong b);

  One creates a struct for passing arguments to our function:

      typedef struct { ulong a, b; } myfunc_t;

  a sample function:

      void sample_myfunc(void * arg, ulong count)
      {
          myfunc_t * params = (myfunc_t *) arg;

          ulong a = params->a;
          ulong b = params->b;

          for (ulong i = 0; i < count; i++)
          {
              prof_start();
              myfunc(a, b);
              prof_stop();
          }
      }

  Then we do the profile:

      double min, max;

      myfunc_t params;

      params.a = 3;
      params.b = 4;

      prof_repeat(&min, &max, sample_myfunc, &params);

      flint_printf("Min time is %lf.3s, max time is %lf.3s\n", min, max);

  If either of the first two parameters to `prof_repeat` is `NULL`, that value is not stored.

  One may set the minimum time in microseconds for a timing run by adjusting `DURATION_THRESHOLD` and one may set a target duration in microseconds by adjusting `DURATION_TARGET` in `profiler.h`.

## Memory usage

void fprint_memory_usage(FILE *fs)
void print_memory_usage(void)

  Obtains information about the memory usage of the current process.