diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luaprofiler')
11 files changed, 901 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/Makefile b/Build/source/texk/web2c/luatexdir/luaprofiler/Makefile new file mode 100644 index 00000000000..57ccbfd165f --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/Makefile @@ -0,0 +1,19 @@ + +srcdir=../../../src/libs/luaprofiler + +OBJS= clocks.o \ + core_profiler.o \ + function_meter.o \ + stack.o \ + lua50_profiler.o + + +profiler: $(OBJS) + ar cru libprofiler.a $(OBJS) + ranlib libprofiler.a + +clean: + rm -f $(OBJS) libprofiler.a + +%.o: $(srcdir)/%.c + $(CC) -c -I../../../src/libs/lua51 $< $(CFLAGS) -o $@ diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c new file mode 100644 index 00000000000..e693c48535f --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c @@ -0,0 +1,63 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: clocks.c,v 1.4 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +clocks.c: + Module to register the time (seconds) between two events + +Design: + 'lprofC_start_timer()' marks the first event + 'lprofC_get_seconds()' gives you the seconds elapsed since the timer + was started +*****************************************************************************/ + +#include <stdio.h> +#include "clocks.h" + +/* + Here you can choose what time function you are going to use. + These two defines ('TIMES' and 'CLOCK') correspond to the usage of + functions times() and clock() respectively. + Which one is better? It depends on your needs: + TIMES - returns the clock ticks since the system was up + (you may use it if you want to measure a system + delay for a task, like time spent to get input from keyboard) + CLOCK - returns the clock ticks dedicated to the program + (this should be prefered in a multithread system and is + the default choice) + + note: I guess TIMES don't work for win32 +*/ + +#ifdef TIMES + + #include <sys/times.h> + + static struct tms t; + + #define times(t) times(t) + +#else /* ifdef CLOCK */ + + #define times(t) clock() + +#endif + + +void lprofC_start_timer(clock_t *time_marker) { + *time_marker = times(&t); +} + +static clock_t get_clocks(clock_t time_marker) { + return times(&t) - time_marker; +} + +float lprofC_get_seconds(clock_t time_marker) { +clock_t clocks; + clocks = get_clocks(time_marker); + return (float)clocks / (float)CLOCKS_PER_SEC; +} + diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h new file mode 100644 index 00000000000..b2c7fd7d4d5 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h @@ -0,0 +1,20 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: clocks.h,v 1.4 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +clocks.h: + Module to register the time (seconds) between two events + +Design: + 'lprofC_start_timer()' marks the first event + 'lprofC_get_seconds()' gives you the seconds elapsed since the timer + was started +*****************************************************************************/ + +#include <time.h> + +void lprofC_start_timer(clock_t *time_marker); +float lprofC_get_seconds(clock_t time_marker); diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c new file mode 100644 index 00000000000..0f70fba106e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c @@ -0,0 +1,180 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005.2007 (http://www.keplerproject.org/luaprofiler) +** $Id: core_profiler.c,v 1.9 2008/05/19 18:36:23 mascarenhas Exp $ +*/ + +/***************************************************************************** +core_profiler.c: + Lua version independent profiler interface. + Responsible for handling the "enter function" and "leave function" events + and for writing the log file. + +Design (using the Lua callhook mechanism) : + 'lprofP_init_core_profiler' set up the profile service + 'lprofP_callhookIN' called whenever Lua enters a function + 'lprofP_callhookOUT' called whenever Lua leaves a function +*****************************************************************************/ + +/***************************************************************************** + The profiled program can be viewed as a graph with the following properties: +directed, multigraph, cyclic and connected. The log file generated by a +profiler section corresponds to a path on this graph. + There are several graphs for which this path fits on. Some times it is +easier to consider this path as being generated by a simpler graph without +properties like cyclic and multigraph. + The profiler log file can be viewed as a "reversed" depth-first search +(with the depth-first search number for each vertex) vertex listing of a graph +with the following properties: simple, acyclic, directed and connected, for +which each vertex appears as many times as needed to strip the cycles and +each vertex has an indegree of 1. + "reversed" depth-first search means that instead of being "printed" before +visiting the vertex's descendents (as done in a normal depth-first search), +the vertex is "printed" only after all his descendents have been processed (in +a depth-first search recursive algorithm). +*****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include "function_meter.h" + +#include "core_profiler.h" + + /* default log name (%s is used to place a random string) */ +#define OUT_FILENAME "lprof_%s.out" + + /* for faster execution (??) */ +static FILE *outf; +static lprofS_STACK_RECORD *info; +static float function_call_time; + + +/* output a line to the log file, using 'printf()' syntax */ +/* assume the timer is off */ +static void output(const char *format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(outf, format, ap); + va_end(ap); + + /* write now to avoid delays when the timer is on */ + fflush(outf); +} + + +/* do not allow a string with '\n' and '|' (log file format reserved chars) */ +/* - replace them by ' ' */ +static void formats(char *s) { + int i; + if (!s) + return; + for (i = strlen(s); i>=0; i--) { + if ((s[i] == '|') || (s[i] == '\n')) + s[i] = ' '; + } +} + + +/* computes new stack and new timer */ +void lprofP_callhookIN(lprofP_STATE* S, char *func_name, char *file, int linedefined, int currentline) { + S->stack_level++; + lprofM_enter_function(S, file, func_name, linedefined, currentline); +} + + +/* pauses all timers to write a log line and computes the new stack */ +/* returns if there is another function in the stack */ +int lprofP_callhookOUT(lprofP_STATE* S) { + + if (S->stack_level == 0) { + return 0; + } + + S->stack_level--; + + /* 0: do not resume the parent function's timer yet... */ + info = lprofM_leave_function(S, 0); + /* writing a log may take too long to be computed with the function's time ...*/ + lprofM_pause_total_time(S); + info->local_time += function_call_time; + info->total_time += function_call_time; + formats(info->file_defined); + formats(info->function_name); + output("%d\t%s\t%s\t%d\t%d\t%f\t%f\n", S->stack_level, info->file_defined, + info->function_name, + info->line_defined, info->current_line, + info->local_time, info->total_time); + /* ... now it's ok to resume the timer */ + if (S->stack_level != 0) { + lprofM_resume_function(S); + } + + return 1; + +} + + +/* opens the log file */ +/* returns true if the file could be opened */ +lprofP_STATE* lprofP_init_core_profiler(const char *_out_filename, int isto_printheader, float _function_call_time) { + lprofP_STATE* S; + char auxs[256]; + char *s; + char *randstr; + const char *out_filename; + + function_call_time = _function_call_time; + out_filename = (_out_filename) ? (_out_filename):(OUT_FILENAME); + + /* the random string to build the logname is extracted */ + /* from 'tmpnam()' (the '/tmp/' part is deleted) */ + randstr = tmpnam(NULL); + for (s = strtok(randstr, "/\\"); s; s = strtok(NULL, "/\\")) { + randstr = s; + } + + if(randstr[strlen(randstr)-1]=='.') + randstr[strlen(randstr)-1]='\0'; + + sprintf(auxs, out_filename, randstr); + outf = fopen(auxs, "a"); + if (!outf) { + return 0; + } + + if (isto_printheader) { + output("stack_level\tfile_defined\tfunction_name\tline_defined\tcurrent_line\tlocal_time\ttotal_time\n"); + } + + /* initialize the 'function_meter' */ + S = lprofM_init(); + if(!S) { + fclose(outf); + return 0; + } + + return S; +} + +void lprofP_close_core_profiler(lprofP_STATE* S) { + if(outf) fclose(outf); + if(S) free(S); +} + +lprofP_STATE* lprofP_create_profiler(float _function_call_time) { + lprofP_STATE* S; + + function_call_time = _function_call_time; + + /* initialize the 'function_meter' */ + S = lprofM_init(); + if(!S) { + return 0; + } + + return S; +} + diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h new file mode 100644 index 00000000000..d066ef3d08b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h @@ -0,0 +1,31 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: core_profiler.h,v 1.6 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +core_profiler.h: + Lua version independent profiler interface. + Responsible for handling the "enter function" and "leave function" events + and for writing the log file. + +Design (using the Lua callhook mechanism) : + 'lprofP_init_core_profiler' set up the profile service + 'lprofP_callhookIN' called whenever Lua enters a function + 'lprofP_callhookOUT' called whenever Lua leaves a function +*****************************************************************************/ + +#include "stack.h" + +/* computes new stack and new timer */ +void lprofP_callhookIN(lprofP_STATE* S, char *func_name, char *file, int linedefined, int currentline); + +/* pauses all timers to write a log line and computes the new stack */ +/* returns if there is another function in the stack */ +int lprofP_callhookOUT(lprofP_STATE* S); + +/* opens the log file */ +/* returns true if the file could be opened */ +lprofP_STATE* lprofP_init_core_profiler(const char *_out_filename, int isto_printheader, float _function_call_time); + diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c new file mode 100644 index 00000000000..2636ee16028 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c @@ -0,0 +1,203 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: function_meter.c,v 1.9 2008/05/19 18:36:23 mascarenhas Exp $ +*/ + +/***************************************************************************** +function_meter.c: + Module to compute the times for functions (local times and total times) + +Design: + 'lprofM_init' set up the function times meter service + 'lprofM_enter_function' called when the function stack increases one level + 'lprofM_leave_function' called when the function stack decreases one level + + 'lprofM_resume_function' called when the profiler is returning from a time + consuming task + 'lprofM_resume_total_time' idem + 'lprofM_resume_local_time' called when a child function returns the execution + to it's caller (current function) + 'lprofM_pause_function' called when the profiler need to do things that + may take too long (writing a log, for example) + 'lprofM_pause_total_time' idem + 'lprofM_pause_local_time' called when the current function has called + another one or when the function terminates +*****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "clocks.h" + +/* #include "stack.h" is done by function_meter.h */ +#include "function_meter.h" + +#ifdef DEBUG +#include <stdlib.h> +#define ASSERT(e, msg) if (!e) { \ + fprintf(stdout, \ + "function_meter.c: assertion failed: %s\n", \ + msg); \ + exit(1); } +#else +#define ASSERT(e, msg) +#endif + +/* structures to receive stack elements, declared globals */ +/* in the hope they will perform faster */ +static lprofS_STACK_RECORD newf; /* used in 'enter_function' */ +static lprofS_STACK_RECORD leave_ret; /* used in 'leave_function' */ + + + +/* sum the seconds based on the time marker */ +static void compute_local_time(lprofS_STACK_RECORD *e) { + ASSERT(e, "local time null"); + e->local_time += lprofC_get_seconds(e->time_marker_function_local_time); +} + + +/* sum the seconds based on the time marker */ +static void compute_total_time(lprofS_STACK_RECORD *e) { + ASSERT(e, "total time null"); + e->total_time += lprofC_get_seconds(e->time_marker_function_total_time); +} + + +/* compute the local time for the current function */ +void lprofM_pause_local_time(lprofP_STATE* S) { + compute_local_time(S->stack_top); +} + + +/* pause the total timer for all the functions that are in the stack */ +void lprofM_pause_total_time(lprofP_STATE* S) { + lprofS_STACK aux; + + ASSERT(S->stack_top, "pause_total_time: stack_top null"); + + /* auxiliary stack */ + aux = S->stack_top; + + /* pause */ + while (aux) { + compute_total_time(aux); + aux = aux->next; + } +} + + +/* pause the local and total timers for all functions in the stack */ +void lprofM_pause_function(lprofP_STATE* S) { + + ASSERT(S->stack_top, "pause_function: stack_top null"); + + lprofM_pause_local_time(S); + lprofM_pause_total_time(S); +} + + +/* resume the local timer for the current function */ +void lprofM_resume_local_time(lprofP_STATE* S) { + + ASSERT(S->stack_top, "resume_local_time: stack_top null"); + + /* the function is in the top of the stack */ + lprofC_start_timer(&(S->stack_top->time_marker_function_local_time)); +} + + +/* resume the total timer for all the functions in the stack */ +void lprofM_resume_total_time(lprofP_STATE* S) { + lprofS_STACK aux; + + ASSERT(S->stack_top, "resume_total_time: stack_top null"); + + /* auxiliary stack */ + aux = S->stack_top; + + /* resume */ + while (aux) { + lprofC_start_timer(&(aux->time_marker_function_total_time)); + aux = aux->next; + } +} + + +/* resume the local and total timers for all functions in the stack */ +void lprofM_resume_function(lprofP_STATE* S) { + + ASSERT(S->stack_top, "resume_function: stack_top null"); + + lprofM_resume_local_time(S); + lprofM_resume_total_time(S); +} + + +/* the local time for the parent function is paused */ +/* and the local and total time markers are started */ +void lprofM_enter_function(lprofP_STATE* S, char *file_defined, char *fcn_name, long linedefined, long currentline) { + char* prev_name; + char* cur_name; + /* the flow has changed to another function: */ + /* pause the parent's function timer timer */ + if (S->stack_top) { + lprofM_pause_local_time(S); + prev_name = S->stack_top->function_name; + } else prev_name = "top level"; + /* measure new function */ + lprofC_start_timer(&(newf.time_marker_function_local_time)); + lprofC_start_timer(&(newf.time_marker_function_total_time)); + newf.file_defined = file_defined; + if(fcn_name != NULL) { + newf.function_name = fcn_name; + } else if(strcmp(file_defined, "=[C]") == 0) { + cur_name = (char*)malloc(sizeof(char)*(strlen("called from ")+strlen(prev_name)+1)); + sprintf(cur_name, "called from %s", prev_name); + newf.function_name = cur_name; + } else { + cur_name = (char*)malloc(sizeof(char)*(strlen(file_defined)+12)); + sprintf(cur_name, "%s:%li", file_defined, linedefined); + newf.function_name = cur_name; + } + newf.line_defined = linedefined; + newf.current_line = currentline; + newf.local_time = 0.0; + newf.total_time = 0.0; + lprofS_push(&(S->stack_top), newf); +} + + +/* computes times and remove the top of the stack */ +/* 'isto_resume' specifies if the parent function's timer */ +/* should be restarted automatically. If it's false, */ +/* 'resume_local_time()' must be called when the resume */ +/* should be done */ +/* returns the funcinfo structure */ +/* warning: use it before another call to this function, */ +/* because the funcinfo will be overwritten */ +lprofS_STACK_RECORD *lprofM_leave_function(lprofP_STATE* S, int isto_resume) { + + ASSERT(S->stack_top, "leave_function: stack_top null"); + + leave_ret = lprofS_pop(&(S->stack_top)); + compute_local_time(&leave_ret); + compute_total_time(&leave_ret); + /* resume the timer for the parent function ? */ + if (isto_resume) + lprofM_resume_local_time(S); + return &leave_ret; +} + + +/* init stack */ +lprofP_STATE* lprofM_init() { + lprofP_STATE *S; + S = (lprofP_STATE*)malloc(sizeof(lprofP_STATE)); + if(S) { + S->stack_level = 0; + S->stack_top = NULL; + return S; + } else return NULL; +} diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h new file mode 100644 index 00000000000..d2eb5a7ca71 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h @@ -0,0 +1,64 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: function_meter.h,v 1.5 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +function_meter.c: + Module to compute the times for functions (local times and total times) + +Design: + 'lprofM_init' set up the function times meter service + 'lprofM_enter_function' called when the function stack increases one level + 'lprofM_leave_function' called when the function stack decreases one level + + 'lprofM_resume_function' called when the profiler is returning from a time + consuming task + 'lprofM_resume_total_time' idem + 'lprofM_resume_local_time' called when a child function returns the execution + to it's caller (current function) + 'lprofM_pause_function' called when the profiler need to do things that + may take too long (writing a log, for example) + 'lprofM_pause_total_time' idem + 'lprofM_pause_local_time' called when the current function has called + another one or when the function terminates +*****************************************************************************/ + +#include "stack.h" + + +/* compute the local time for the current function */ +void lprofM_pause_local_time(lprofP_STATE* S); + +/* pause the total timer for all the functions that are in the stack */ +void lprofM_pause_total_time(lprofP_STATE* S); + +/* pause the local and total timers for all functions in the stack */ +void lprofM_pause_function(lprofP_STATE* S); + +/* resume the local timer for the current function */ +void lprofM_resume_local_time(lprofP_STATE* S); + +/* resume the total timer for all the functions in the stack */ +void lprofM_resume_total_time(lprofP_STATE* S); + +/* resume the local and total timers for all functions in the stack */ +void lprofM_resume_function(lprofP_STATE* S); + +/* the local time for the parent function is paused */ +/* and the local and total time markers are started */ +void lprofM_enter_function(lprofP_STATE* S, char *file_defined, char *fcn_name, long linedefined, long currentline); + +/* computes times and remove the top of the stack */ +/* 'isto_resume' specifies if the parent function's timer */ +/* should be restarted automatically. If it's false, */ +/* 'resume_local_time()' must be called when the resume */ +/* should be done */ +/* returns the funcinfo structure */ +/* warning: use it before another call to this function, */ +/* because the funcinfo will be overwritten */ +lprofS_STACK_RECORD *lprofM_leave_function(lprofP_STATE* S, int isto_resume); + +/* init stack */ +lprofP_STATE* lprofM_init(); diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c b/Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c new file mode 100644 index 00000000000..54533425c3b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c @@ -0,0 +1,230 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: lua50_profiler.c,v 1.13 2008/05/19 18:36:23 mascarenhas Exp $ +*/ + +/***************************************************************************** +lua50_profiler.c: + Lua version dependent profiler interface +*****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "clocks.h" +#include "core_profiler.h" +#include "function_meter.h" + +#include "lua.h" +#include "lauxlib.h" + +/* Indices for the main profiler stack and for the original exit function */ +static int exit_id; +static int profstate_id; + +/* Forward declaration */ +static float calcCallTime(lua_State *L); + +/* called by Lua (via the callhook mechanism) */ +static void callhook(lua_State *L, lua_Debug *ar) { + int currentline; + lua_Debug previous_ar; + lprofP_STATE* S; + lua_pushlightuserdata(L, &profstate_id); + lua_gettable(L, LUA_REGISTRYINDEX); + S = (lprofP_STATE*)lua_touserdata(L, -1); + + if (lua_getstack(L, 1, &previous_ar) == 0) { + currentline = -1; + } else { + lua_getinfo(L, "l", &previous_ar); + currentline = previous_ar.currentline; + } + + lua_getinfo(L, "nS", ar); + + if (!ar->event) { + /* entering a function */ + lprofP_callhookIN(S, (char *)ar->name, + (char *)ar->source, ar->linedefined, + currentline); + } + else { /* ar->event == "return" */ + lprofP_callhookOUT(S); + } +} + + +/* Lua function to exit politely the profiler */ +/* redefines the lua exit() function to not break the log file integrity */ +/* The log file is assumed to be valid if the last entry has a stack level */ +/* of 1 (meaning that the function 'main' has been exited) */ +static void exit_profiler(lua_State *L) { + lprofP_STATE* S; + lua_pushlightuserdata(L, &profstate_id); + lua_gettable(L, LUA_REGISTRYINDEX); + S = (lprofP_STATE*)lua_touserdata(L, -1); + /* leave all functions under execution */ + while (lprofP_callhookOUT(S)) ; + /* call the original Lua 'exit' function */ + lua_pushlightuserdata(L, &exit_id); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_call(L, 0, 0); +} + +/* Our new coroutine.create function */ +/* Creates a new profile state for the coroutine */ +#if 0 +static int coroutine_create(lua_State *L) { + lprofP_STATE* S; + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + /* Inits profiler and sets profiler hook for this coroutine */ + S = lprofM_init(); + lua_pushlightuserdata(L, NL); + lua_pushlightuserdata(L, S); + lua_settable(L, LUA_REGISTRYINDEX); + lua_sethook(NL, (lua_Hook)callhook, LUA_MASKCALL | LUA_MASKRET, 0); + return 1; +} +#endif + +static int profiler_pause(lua_State *L) { + lprofP_STATE* S; + lua_pushlightuserdata(L, &profstate_id); + lua_gettable(L, LUA_REGISTRYINDEX); + S = (lprofP_STATE*)lua_touserdata(L, -1); + lprofM_pause_function(S); + return 0; +} + +static int profiler_resume(lua_State *L) { + lprofP_STATE* S; + lua_pushlightuserdata(L, &profstate_id); + lua_gettable(L, LUA_REGISTRYINDEX); + S = (lprofP_STATE*)lua_touserdata(L, -1); + lprofM_pause_function(S); + return 0; +} + +static int profiler_init(lua_State *L) { + lprofP_STATE* S; + const char* outfile; + float function_call_time; + + function_call_time = calcCallTime(L); + + outfile = NULL; + if(lua_gettop(L) == 1) + outfile = luaL_checkstring(L, -1); + + lua_sethook(L, (lua_Hook)callhook, LUA_MASKCALL | LUA_MASKRET, 0); + /* init with default file name and printing a header line */ + if (!(S=lprofP_init_core_profiler(outfile, 1, function_call_time))) { + luaL_error(L,"LuaProfiler error: output file could not be opened!"); + lua_pushnil(L); + return 1; + } + + lua_pushlightuserdata(L, &profstate_id); + lua_pushlightuserdata(L, S); + lua_settable(L, LUA_REGISTRYINDEX); + + /* use our own exit function instead */ + lua_getglobal(L, "os"); + lua_pushlightuserdata(L, &exit_id); + lua_pushstring(L, "exit"); + lua_gettable(L, -3); + lua_settable(L, LUA_REGISTRYINDEX); + lua_pushstring(L, "exit"); + lua_pushcfunction(L, (lua_CFunction)exit_profiler); + lua_settable(L, -3); + +#if 0 + /* use our own coroutine.create function instead */ + lua_getglobal(L, "coroutine"); + lua_pushstring(L, "create"); + lua_pushcfunction(L, (lua_CFunction)coroutine_create); + lua_settable(L, -3); +#endif + + /* the following statement is to simulate how the execution stack is */ + /* supposed to be by the time the profiler is activated when loaded */ + /* as a library. */ + + lprofP_callhookIN(S, "profiler_init", "(C)", -1, -1); + + lua_pushboolean(L, 1); + return 1; +} + +static int profiler_stop(lua_State *L) { + lprofP_STATE* S; + lua_sethook(L, (lua_Hook)callhook, 0, 0); + lua_pushlightuserdata(L, &profstate_id); + lua_gettable(L, LUA_REGISTRYINDEX); + if(!lua_isnil(L, -1)) { + S = (lprofP_STATE*)lua_touserdata(L, -1); + /* leave all functions under execution */ + while (lprofP_callhookOUT(S)); + lprofP_close_core_profiler(S); + lua_pushboolean(L, 1); + } else { lua_pushboolean(L, 0); } + return 1; +} + +/* calculates the approximate time Lua takes to call a function */ +static float calcCallTime(lua_State *L) { + clock_t timer; + char lua_code[] = " \ + function lprofT_mesure_function() \ + local i \ + \ + local t = function() \ + end \ + \ + i = 1 \ + while (i < 100000) do \ + t() \ + i = i + 1 \ + end \ + end \ + \ + lprofT_mesure_function() \ + lprofT_mesure_function = nil \ + "; + + lprofC_start_timer(&timer); + luaL_dostring(L, lua_code); + return lprofC_get_seconds(timer) / (float) 100000; +} + +static const luaL_reg prof_funcs[] = { + { "pause", profiler_pause }, + { "resume", profiler_resume }, + { "start", profiler_init }, + { "stop", profiler_stop }, + { NULL, NULL } +}; + +int luaopen_profiler(lua_State *L) { + luaL_openlib(L, "profiler", prof_funcs, 0); + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2003-2007 Kepler Project"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "LuaProfiler is a time profiler designed to help finding bottlenecks in your Lua program."); + lua_settable (L, -3); + lua_pushliteral (L, "_NAME"); + lua_pushliteral (L, "LuaProfiler"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "2.0.1"); + lua_settable (L, -3); + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h b/Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h new file mode 100644 index 00000000000..155f7996fef --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h @@ -0,0 +1,14 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: luaprofiler.h,v 1.4 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +luaprofiler.h: + Must be included by your main module, in order to profile Lua programs +*****************************************************************************/ + + +void init_profiler(void *); + diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/stack.c b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.c new file mode 100644 index 00000000000..07754ad95b1 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.c @@ -0,0 +1,33 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: stack.c,v 1.4 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +stack.c: + Simple stack manipulation +*****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include "stack.h" + +void lprofS_push(lprofS_STACK *p, lprofS_STACK_RECORD r) { +lprofS_STACK q; + q=(lprofS_STACK)malloc(sizeof(lprofS_STACK_RECORD)); + *q=r; + q->next=*p; + *p=q; +} + +lprofS_STACK_RECORD lprofS_pop(lprofS_STACK *p) { +lprofS_STACK_RECORD r; +lprofS_STACK q; + + r=**p; + q=*p; + *p=(*p)->next; + free(q); + return r; +} diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/stack.h b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.h new file mode 100644 index 00000000000..ac27aaa2907 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.h @@ -0,0 +1,44 @@ +/* +** LuaProfiler +** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler) +** $Id: stack.h,v 1.5 2007/08/22 19:23:53 carregal Exp $ +*/ + +/***************************************************************************** +stack.h: + Simple stack manipulation +*****************************************************************************/ + +#ifndef _STACK_H +#define _STACK_H + +#include <time.h> + +typedef struct lprofS_sSTACK_RECORD lprofS_STACK_RECORD; + +struct lprofS_sSTACK_RECORD { + clock_t time_marker_function_local_time; + clock_t time_marker_function_total_time; + char *file_defined; + char *function_name; + char *source_code; + long line_defined; + long current_line; + float local_time; + float total_time; + lprofS_STACK_RECORD *next; +}; + +typedef lprofS_STACK_RECORD *lprofS_STACK; + +typedef struct lprofP_sSTATE lprofP_STATE; + +struct lprofP_sSTATE { + int stack_level; + lprofS_STACK stack_top; +}; + +void lprofS_push(lprofS_STACK *p, lprofS_STACK_RECORD r); +lprofS_STACK_RECORD lprofS_pop(lprofS_STACK *p); + +#endif |