A ppx that instruments OCaml code to produce traces of execution. Traces can be explored to understand the control flow and see where time is spent in a program. Traces can be compared to see how a patch affects control flow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

96 lines
2.1 KiB

#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
static int trail_initialized = 0;
static FILE *trail_index = NULL;
static FILE *trail_trace = NULL;
static uint32_t trail_next_atom = 0;
typedef struct {
uint32_t atom;
uint32_t sp;
uint64_t time;
} event_t;
#define TRAIL_BUFFER_SIZE 4096
static int trail_buffer_index = 0;
static event_t trail_buffer[TRAIL_BUFFER_SIZE];
static uint64_t trail_gettime(void)
{
struct timespec tp;
//clock_gettime(CLOCK_MONOTONIC_COARSE, &tp);
clock_gettime(CLOCK_MONOTONIC, &tp);
return tp.tv_sec * 1000000000 + tp.tv_nsec;
}
static void trail_flush(void)
{
fwrite(trail_buffer, sizeof(event_t), trail_buffer_index, trail_trace);
trail_buffer_index = 0;
}
static void trail_atexit(void)
{
trail_flush();
fclose(trail_index);
fclose(trail_trace);
}
static void trail_initialize(void)
{
char *trace_file = getenv("CAMTRAIL_FILE");
if (trace_file)
{
char index_file[1024];
strncpy(index_file, trace_file, 1023);
strncat(index_file, ".idx", 1023);
index_file[1023] = '\0';
trail_index = fopen(index_file, "wb");
trail_trace = fopen(trace_file, "wb");
atexit(&trail_atexit);
}
trail_initialized = 1;
}
static uint32_t trail_alloc_atom(value name)
{
uint32_t *buffer = (uint32_t*)String_val(name);
uint32_t result = 1024 + trail_next_atom;
trail_next_atom += 1;
*(uint32_t*)name = result;
uint32_t length = caml_string_length(name);
fwrite(&length, 4, 1, trail_index);
fwrite(buffer, length, 1, trail_index);
return result;
}
static event_t *trail_next_event(void)
{
if (trail_buffer_index == TRAIL_BUFFER_SIZE)
{
trail_flush();
trail_buffer_index = 0;
}
return &trail_buffer[trail_buffer_index++];
}
CAMLprim value camtrail_enter(value name)
{
if (!trail_initialized) trail_initialize();
if (!trail_trace) return Val_unit;
uint32_t atom = *(uint32_t*)String_val(name);
if (!atom) atom = trail_alloc_atom(name);
event_t *event = trail_next_event();
event->atom = atom;
event->sp = (uintptr_t)(void*)&name;
event->time = trail_gettime();
return Val_unit;
}