Remove callgrind generation from VM
This commit is contained in:
parent
6b134d11ff
commit
0eaa455fbe
@ -45,8 +45,6 @@ Halts execution and calls the debugger before every instruction.
|
||||
Prints a message each time the garbage collector is run.
|
||||
- `KRK_GLOBAL_ENABLE_STRESS_GC`
|
||||
Causes the garbage collector to be called on every allocation (from the main thread).
|
||||
- `KRK_GLOBAL_CALLGRIND`
|
||||
Generate tracing data. `vm.callgrindFile` must be set to a writable stream to store the intermediate data collected by the VM.
|
||||
- `KRK_GLOBAL_CLEAN_OUTPUT`
|
||||
Disables automatic printing of uncaught exception tracebacks. Use `krk_dumpTraceback()` to print a traceback from the exception in the current thread to `stderr`.
|
||||
|
||||
|
@ -1,65 +0,0 @@
|
||||
'''
|
||||
@brief Tool to process VM trace reports and generate callgrind-formatted output.
|
||||
'''
|
||||
import kuroko
|
||||
import fileio
|
||||
|
||||
def processFile(sourcePath: str, pid: int , cmd: str):
|
||||
'''@brief Process @p sourcePath from process @p pid with command @p cmd as a VM trace file.'''
|
||||
let funcs = {}
|
||||
|
||||
with fileio.open(sourcePath,'r') as f:
|
||||
for line in f.readlines():
|
||||
let callerFile, callerFunc, callerLine, calleeFile, calleeFunc, calleeLine, nsecs = line.split(' ')
|
||||
nsecs = float(nsecs)
|
||||
let data = funcs.get((callerFile,callerFunc),{})
|
||||
let call = data.get((callerLine,calleeFile,calleeFunc,calleeLine),(0,0))
|
||||
let out = (call[0] + 1, call[1] + nsecs)
|
||||
data[callerLine,calleeFile,calleeFunc,calleeLine] = out
|
||||
funcs[callerFile,callerFunc] = data
|
||||
let called = funcs.get((calleeFile,calleeFunc),{})
|
||||
let times = called.get(None,(1,0))
|
||||
called[None] = (calleeLine, times[1] + nsecs)
|
||||
funcs[calleeFile,calleeFunc] = called
|
||||
|
||||
with fileio.open(f'callgrind.out.{pid}','w') as out:
|
||||
out.write('# callgrind format\n')
|
||||
out.write('creator: Kuroko\n')
|
||||
out.write('positions: line\n')
|
||||
out.write('events: nanoseconds\n')
|
||||
out.write(f'cmd: {cmd}\n\n')
|
||||
|
||||
def defloat(f):
|
||||
let s = int(f)
|
||||
let n = str(int(f * 1000000000))
|
||||
if len(n) > 9: n = n[-9:]
|
||||
let o = (str(s) + '0' * (9 - len(n)) + n).lstrip('0')
|
||||
return o if o else '0'
|
||||
|
||||
def cleanfunc(func):
|
||||
for s in ['<module>','<listcomp>','<setcomp>','<dictcomp>','<lambda>']:
|
||||
func = func.replace(s,'['+s[1:-1]+']')
|
||||
return func.replace('@','<') + '>'
|
||||
|
||||
for key, value in funcs.items():
|
||||
let sFile, sFunc = key
|
||||
out.write(f'fl={sFile}\n')
|
||||
out.write(f'fn={cleanfunc(sFunc)}\n')
|
||||
if not sFunc.startswith('(root)'):
|
||||
let startLine, totalNsecs = value[None]
|
||||
for k, v in value.items():
|
||||
if not k: continue
|
||||
let sourceLine, file, func, destLine = k
|
||||
let count, nsecs = v
|
||||
totalNsecs -= nsecs
|
||||
|
||||
out.write(f'{startLine} {defloat(totalNsecs)}\n')
|
||||
for k, v in value.items():
|
||||
if not k: continue
|
||||
let sourceLine, file, func, destLine = k
|
||||
let count, totalNsecs = v
|
||||
if file != sFile: out.write(f'cfi={file}\n')
|
||||
out.write(f'cfn={cleanfunc(func)}\n')
|
||||
out.write(f'calls={count} {destLine}\n')
|
||||
out.write(f'{sourceLine} {defloat(totalNsecs)}\n')
|
||||
out.write('\n')
|
22
src/kuroko.c
22
src/kuroko.c
@ -33,8 +33,6 @@
|
||||
#define PROMPT_MAIN ">>> "
|
||||
#define PROMPT_BLOCK " > "
|
||||
|
||||
#define CALLGRIND_TMP_FILE "/tmp/kuroko.callgrind.tmp"
|
||||
|
||||
static int enableRline = 1;
|
||||
static int exitRepl = 0;
|
||||
static int pasteEnabled = 0;
|
||||
@ -787,11 +785,6 @@ int main(int argc, char * argv[]) {
|
||||
/* Disassemble instructions as they are executed. */
|
||||
flags |= KRK_THREAD_ENABLE_TRACING;
|
||||
break;
|
||||
case 'T': {
|
||||
flags |= KRK_GLOBAL_CALLGRIND;
|
||||
vm.callgrindFile = fopen(CALLGRIND_TMP_FILE,"w");
|
||||
break;
|
||||
}
|
||||
case 'i':
|
||||
inspectAfter = 1;
|
||||
break;
|
||||
@ -837,7 +830,6 @@ int main(int argc, char * argv[]) {
|
||||
" -r Disable complex line editing in the REPL.\n"
|
||||
" -R depth Set maximum recursion depth.\n"
|
||||
" -t Disassemble instructions as they are exceuted.\n"
|
||||
" -T Write call trace file.\n"
|
||||
" -C file Compile 'file', but do not execute it.\n"
|
||||
" -M Print the default module import paths.\n"
|
||||
" -S Enable single-step debugging.\n"
|
||||
@ -1186,20 +1178,6 @@ _finishArgs:
|
||||
}
|
||||
}
|
||||
|
||||
if (vm.globalFlags & KRK_GLOBAL_CALLGRIND) {
|
||||
fclose(vm.callgrindFile);
|
||||
vm.globalFlags &= ~(KRK_GLOBAL_CALLGRIND);
|
||||
|
||||
krk_resetStack();
|
||||
krk_startModule("<callgrind>");
|
||||
krk_attachNamedObject(&krk_currentThread.module->fields, "filename", (KrkObj*)S(CALLGRIND_TMP_FILE));
|
||||
krk_interpret(
|
||||
"from callgrind import processFile\n"
|
||||
"import kuroko\n"
|
||||
"import os\n"
|
||||
"processFile(filename, os.getpid(), ' '.join(kuroko.argv))","<callgrind>");
|
||||
}
|
||||
|
||||
krk_freeVM();
|
||||
|
||||
if (IS_INTEGER(result)) return AS_INTEGER(result);
|
||||
|
@ -35,7 +35,6 @@ typedef int64_t krk_integer_type;
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define KRK_NO_DOCUMENTATION 1
|
||||
#define KRK_NO_GC_TRACING 1
|
||||
#define KRK_NO_CALLGRIND 1
|
||||
typedef intptr_t ssize_t;
|
||||
#pragma warning(disable : 4146) /* unary minus on unsigned */
|
||||
#pragma warning(disable : 4996) /* sterror */
|
||||
|
@ -7,7 +7,6 @@
|
||||
* for Kuroko, including initializing the VM and passing code to be interpreted.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include "kuroko.h"
|
||||
#include "value.h"
|
||||
@ -49,9 +48,6 @@ typedef struct {
|
||||
size_t outSlots; /**< Offset into the stack at which stackTop will be reset upon return */
|
||||
KrkTable * globals; /**< Pointer to the attribute table containing valud global vairables for this call */
|
||||
KrkValue globalsOwner; /**< Owner of the current globals context, to give to new closures. */
|
||||
#ifndef KRK_NO_CALLGRIND
|
||||
struct timespec in_time;
|
||||
#endif
|
||||
} KrkCallFrame;
|
||||
|
||||
/**
|
||||
@ -201,7 +197,6 @@ typedef struct KrkVM {
|
||||
KrkObj** grayStack; /**< Scan list */
|
||||
|
||||
KrkThreadState * threads; /**< Invasive linked list of all VM threads. */
|
||||
FILE * callgrindFile; /**< File to write unprocessed callgrind data to. */
|
||||
struct DebuggerState * dbgState; /**< Opaque debugger state pointer. */
|
||||
} KrkVM;
|
||||
|
||||
@ -218,7 +213,7 @@ typedef struct KrkVM {
|
||||
#define KRK_GLOBAL_ENABLE_STRESS_GC (1 << 8)
|
||||
#define KRK_GLOBAL_GC_PAUSED (1 << 9)
|
||||
#define KRK_GLOBAL_CLEAN_OUTPUT (1 << 10)
|
||||
#define KRK_GLOBAL_CALLGRIND (1 << 11)
|
||||
/* 11 is available again */
|
||||
#define KRK_GLOBAL_REPORT_GC_COLLECTS (1 << 12)
|
||||
#define KRK_GLOBAL_THREADS (1 << 13)
|
||||
#define KRK_GLOBAL_NO_DEFAULT_MODULES (1 << 14)
|
||||
|
40
src/vm.c
40
src/vm.c
@ -66,44 +66,6 @@ void krk_forceThreadData(void) {
|
||||
#define krk_currentThread (*_macos_currentThread())
|
||||
#endif
|
||||
|
||||
#if !defined(KRK_NO_TRACING) && !defined(__EMSCRIPTEN__) && !defined(KRK_NO_CALLGRIND)
|
||||
static void _frame_in(KrkCallFrame * frame) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &frame->in_time);
|
||||
}
|
||||
static void _frame_out(KrkCallFrame * frame) {
|
||||
if (frame->closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_IS_GENERATOR) return;
|
||||
|
||||
KrkCallFrame * caller = krk_currentThread.frameCount > 1 ? &krk_currentThread.frames[krk_currentThread.frameCount-2] : NULL;
|
||||
|
||||
struct timespec outTime, diff;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &outTime);
|
||||
diff.tv_sec = outTime.tv_sec - frame->in_time.tv_sec;
|
||||
diff.tv_nsec = outTime.tv_nsec - frame->in_time.tv_nsec;
|
||||
|
||||
if (diff.tv_nsec < 0) {
|
||||
diff.tv_sec--;
|
||||
diff.tv_nsec += 1000000000L;
|
||||
}
|
||||
|
||||
fprintf(vm.callgrindFile, "%s %s@%p %d %s %s@%p %d %lld.%.9ld\n",
|
||||
caller ? (caller->closure->function->chunk.filename->chars) : "stdin",
|
||||
caller ? (caller->closure->function->qualname ? caller->closure->function->qualname->chars : caller->closure->function->name->chars) : "(root)",
|
||||
caller ? ((void*)caller->closure->function) : NULL,
|
||||
caller ? ((int)krk_lineNumber(&caller->closure->function->chunk, caller->ip - caller->closure->function->chunk.code)) : 1,
|
||||
frame->closure->function->chunk.filename->chars,
|
||||
frame->closure->function->qualname ? frame->closure->function->qualname->chars : frame->closure->function->name->chars,
|
||||
(void*)frame->closure->function,
|
||||
(int)krk_lineNumber(&frame->closure->function->chunk, 0),
|
||||
(long long)diff.tv_sec, diff.tv_nsec);
|
||||
}
|
||||
# define FRAME_IN(frame) if (unlikely(vm.globalFlags & KRK_GLOBAL_CALLGRIND)) { _frame_in(frame); }
|
||||
# define FRAME_OUT(frame) if (unlikely(vm.globalFlags & KRK_GLOBAL_CALLGRIND)) { _frame_out(frame); }
|
||||
#else
|
||||
# define FRAME_IN(frame)
|
||||
# define FRAME_OUT(frame)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In some threading configurations, particular on Windows,
|
||||
* we can't have executables reference our thread-local thread
|
||||
@ -621,7 +583,6 @@ _finishKwarg:
|
||||
frame->outSlots = frame->slots - returnDepth;
|
||||
frame->globalsOwner = closure->globalsOwner;
|
||||
frame->globals = closure->globalsTable;
|
||||
FRAME_IN(frame);
|
||||
return 1;
|
||||
|
||||
_errorDuringPositionals:
|
||||
@ -2220,7 +2181,6 @@ _finishReturn: (void)0;
|
||||
break;
|
||||
}
|
||||
closeUpvalues(frame->slots);
|
||||
FRAME_OUT(frame);
|
||||
krk_currentThread.frameCount--;
|
||||
if (krk_currentThread.frameCount == 0) {
|
||||
krk_pop();
|
||||
|
@ -122,7 +122,6 @@ let modules = [
|
||||
'json',
|
||||
'collections',
|
||||
'string',
|
||||
'callgrind',
|
||||
|
||||
# Other stuff
|
||||
'tools.gendoc',
|
||||
|
Loading…
Reference in New Issue
Block a user