summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2023-07-14 23:30:43 -0500
committerNicolas Williams <nico@cryptonector.com>2023-07-14 23:30:43 -0500
commit018716bf2053f47b467a2be810978ba177667fbe (patch)
tree2d2de7bb64280597e2f42f7a7de717b424e371a2
parent092fef740a0d1a0ddf61cf9e7af88915071c0705 (diff)
WIP: Instruction timingnicowilliams/inst-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
-rw-r--r--src/execute.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/src/execute.c b/src/execute.c
index e1894aa5..e804fd7a 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <errno.h>
+#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -337,6 +338,8 @@ static void set_error(jq_state *jq, jv value) {
#define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
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_nomem_handler(jq->nomem_handler, jq->nomem_handler_data);
@@ -386,8 +389,6 @@ jv jq_next(jq_state *jq) {
} else {
printf("\t<backtracking>");
}
-
- printf("\n");
}
if (backtracking) {
@@ -397,6 +398,13 @@ jv jq_next(jq_state *jq) {
}
pc++;
+ {
+ unsigned optickc, optickd;
+
+ asm volatile("rdtsc" : "=a" (optickc), "=d" (optickd));
+ tickstart = (((uint64_t)optickc) | (((uint64_t)optickd) << 32));
+ }
+
switch (opcode) {
default: assert(0 && "invalid instruction");
@@ -543,7 +551,6 @@ jv jq_next(jq_state *jq) {
if (jq->debug_trace_enabled) {
printf("V%d = ", v);
jv_dump(jv_copy(*var), JV_PRINT_REFCOUNT);
- printf("\n");
}
jv_free(stack_pop(jq));
stack_push(jq, jv_copy(*var));
@@ -558,7 +565,6 @@ jv jq_next(jq_state *jq) {
if (jq->debug_trace_enabled) {
printf("V%d = ", v);
jv_dump(jv_copy(*var), JV_PRINT_REFCOUNT);
- printf("\n");
}
jv_free(stack_popn(jq));
@@ -580,7 +586,7 @@ jv jq_next(jq_state *jq) {
if (jq->debug_trace_enabled) {
printf("V%d = ", v);
jv_dump(jv_copy(val), 0);
- printf(" (%d)\n", jv_get_refcnt(val));
+ printf(" (%d)", jv_get_refcnt(val));
}
jv_free(*var);
*var = val;
@@ -798,8 +804,12 @@ jv jq_next(jq_state *jq) {
if (!jv_is_valid(jq->error)) {
jv error = jq->error;
jq->error = jv_null();
+ if (jq->debug_trace_enabled)
+ printf("\n");
return error;
}
+ if (jq->debug_trace_enabled)
+ printf("\n");
return jv_invalid();
}
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;
// FIXME: a) up to 7 arguments (input + 6), b) should assert
// 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)) {
@@ -938,6 +951,8 @@ jv jq_next(jq_state *jq) {
struct stack_pos spos = stack_get_pos(jq);
stack_push(jq, jv_null());
stack_save(jq, pc - 1, spos);
+ if (jq->debug_trace_enabled)
+ printf("\n");
return value;
}
stack_push(jq, value);
@@ -948,6 +963,16 @@ jv jq_next(jq_state *jq) {
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);
}
}