WIP: Instruction timing

TODO:

 - add a --debug mode that prints only cycle counts, no refcounts, no
   values

 - add a --debug mode that prints stats at VM teardown or when
   `jq_next()` returns

    - for each opcode the count of instructions
    - for each opcode the total time or CPU cycles spent executing it
This commit is contained in:
Nicolas Williams committed 2023-07-14 23:30:43 -05:00
1 parent 092fef740a
commit 018716bf20
1 file changed
+31 -6
+31 -6
View File
@@ -1,5 +1,6 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <inttypes.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -337,6 +338,8 @@ static void set_error(jq_state *jq, jv value) {
#define ON_BACKTRACK(op) ((op)+NUM_OPCODES) #define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
jv jq_next(jq_state *jq) { jv jq_next(jq_state *jq) {
uint64_t tickstart, ticks, opticks[(STOREVN + 1) * 2];
memset(opticks, 0, sizeof(opticks));
jv cfunc_input[MAX_CFUNCTION_ARGS]; jv cfunc_input[MAX_CFUNCTION_ARGS];
jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data); jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data);
@@ -386,8 +389,6 @@ jv jq_next(jq_state *jq) {
} else { } else {
printf("\t<backtracking>"); printf("\t<backtracking>");
} }
printf("\n");
} }
if (backtracking) { if (backtracking) {
@@ -397,6 +398,13 @@ jv jq_next(jq_state *jq) {
} }
pc++; pc++;
{
unsigned optickc, optickd;
asm volatile("rdtsc" : "=a" (optickc), "=d" (optickd));
tickstart = (((uint64_t)optickc) | (((uint64_t)optickd) << 32));
}
switch (opcode) { switch (opcode) {
default: assert(0 && "invalid instruction"); default: assert(0 && "invalid instruction");
@@ -543,7 +551,6 @@ jv jq_next(jq_state *jq) {
if (jq->debug_trace_enabled) { if (jq->debug_trace_enabled) {
printf("V%d = ", v); printf("V%d = ", v);
jv_dump(jv_copy(*var), JV_PRINT_REFCOUNT); jv_dump(jv_copy(*var), JV_PRINT_REFCOUNT);
printf("\n");
} }
jv_free(stack_pop(jq)); jv_free(stack_pop(jq));
stack_push(jq, jv_copy(*var)); stack_push(jq, jv_copy(*var));
@@ -558,7 +565,6 @@ jv jq_next(jq_state *jq) {
if (jq->debug_trace_enabled) { if (jq->debug_trace_enabled) {
printf("V%d = ", v); printf("V%d = ", v);
jv_dump(jv_copy(*var), JV_PRINT_REFCOUNT); jv_dump(jv_copy(*var), JV_PRINT_REFCOUNT);
printf("\n");
} }
jv_free(stack_popn(jq)); jv_free(stack_popn(jq));
@@ -580,7 +586,7 @@ jv jq_next(jq_state *jq) {
if (jq->debug_trace_enabled) { if (jq->debug_trace_enabled) {
printf("V%d = ", v); printf("V%d = ", v);
jv_dump(jv_copy(val), 0); jv_dump(jv_copy(val), 0);
printf(" (%d)\n", jv_get_refcnt(val)); printf(" (%d)", jv_get_refcnt(val));
} }
jv_free(*var); jv_free(*var);
*var = val; *var = val;
@@ -798,8 +804,12 @@ jv jq_next(jq_state *jq) {
if (!jv_is_valid(jq->error)) { if (!jv_is_valid(jq->error)) {
jv error = jq->error; jv error = jq->error;
jq->error = jv_null(); jq->error = jv_null();
if (jq->debug_trace_enabled)
printf("\n");
return error; return error;
} }
if (jq->debug_trace_enabled)
printf("\n");
return jv_invalid(); return jv_invalid();
} }
backtracking = 1; backtracking = 1;
@@ -864,7 +874,10 @@ jv jq_next(jq_state *jq) {
case 5: top = ((func_5)function->fptr)(jq, in[0], in[1], in[2], in[3], in[4]); break; case 5: top = ((func_5)function->fptr)(jq, in[0], in[1], in[2], in[3], in[4]); break;
// FIXME: a) up to 7 arguments (input + 6), b) should assert // FIXME: a) up to 7 arguments (input + 6), b) should assert
// because the compiler should not generate this error. // because the compiler should not generate this error.
default: return jv_invalid_with_msg(jv_string("Function takes too many arguments")); default:
if (jq->debug_trace_enabled)
printf("\n");
return jv_invalid_with_msg(jv_string("Function takes too many arguments"));
} }
if (jv_is_valid(top)) { if (jv_is_valid(top)) {
@@ -938,6 +951,8 @@ jv jq_next(jq_state *jq) {
struct stack_pos spos = stack_get_pos(jq); struct stack_pos spos = stack_get_pos(jq);
stack_push(jq, jv_null()); stack_push(jq, jv_null());
stack_save(jq, pc - 1, spos); stack_save(jq, pc - 1, spos);
if (jq->debug_trace_enabled)
printf("\n");
return value; return value;
} }
stack_push(jq, value); stack_push(jq, value);
@@ -948,6 +963,16 @@ jv jq_next(jq_state *jq) {
goto do_backtrack; goto do_backtrack;
} }
} }
{
unsigned optickc, optickd;
asm volatile("rdtsc" : "=a" (optickc), "=d" (optickd));
ticks = (((uint64_t)optickc) | (((uint64_t)optickd) << 32)) - tickstart;
opticks[opcode] += ticks;
}
if (jq->debug_trace_enabled)
printf(" %"PRIu64" cycles\n", ticks);
} }
} }