Skip to content

Commit df946b4

Browse files
author
ron
committed
profiler
0 parents  commit df946b4

15 files changed

+1127
-0
lines changed

clocks.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
** LuaProfiler
3+
** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
4+
** $Id: clocks.c,v 1.4 2007-08-22 19:23:53 carregal Exp $
5+
*/
6+
7+
/*****************************************************************************
8+
clocks.c:
9+
Module to register the time (seconds) between two events
10+
11+
Design:
12+
'lprofC_start_timer()' marks the first event
13+
'lprofC_get_seconds()' gives you the seconds elapsed since the timer
14+
was started
15+
*****************************************************************************/
16+
17+
#include <stdio.h>
18+
#include "clocks.h"
19+
20+
/*
21+
Here you can choose what time function you are going to use.
22+
These two defines ('TIMES' and 'CLOCK') correspond to the usage of
23+
functions times() and clock() respectively.
24+
Which one is better? It depends on your needs:
25+
TIMES - returns the clock ticks since the system was up
26+
(you may use it if you want to measure a system
27+
delay for a task, like time spent to get input from keyboard)
28+
CLOCK - returns the clock ticks dedicated to the program
29+
(this should be prefered in a multithread system and is
30+
the default choice)
31+
32+
note: I guess TIMES don't work for win32
33+
*/
34+
35+
#ifdef TIMES
36+
37+
#include <sys/times.h>
38+
39+
static struct tms t;
40+
41+
#define times(t) times(t)
42+
43+
#else /* ifdef CLOCK */
44+
45+
#define times(t) clock()
46+
47+
#endif
48+
49+
50+
void lprofC_start_timer(clock_t *time_marker) {
51+
*time_marker = times(&t);
52+
}
53+
54+
static clock_t get_clocks(clock_t time_marker) {
55+
return times(&t) - time_marker;
56+
}
57+
58+
float lprofC_get_seconds(clock_t time_marker) {
59+
clock_t clocks;
60+
clocks = get_clocks(time_marker);
61+
return (float)clocks / (float)CLOCKS_PER_SEC;
62+
}
63+

clocks.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
** LuaProfiler
3+
** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
4+
** $Id: clocks.h,v 1.4 2007-08-22 19:23:53 carregal Exp $
5+
*/
6+
7+
/*****************************************************************************
8+
clocks.h:
9+
Module to register the time (seconds) between two events
10+
11+
Design:
12+
'lprofC_start_timer()' marks the first event
13+
'lprofC_get_seconds()' gives you the seconds elapsed since the timer
14+
was started
15+
*****************************************************************************/
16+
17+
#include <time.h>
18+
19+
void lprofC_start_timer(clock_t *time_marker);
20+
float lprofC_get_seconds(clock_t time_marker);

core_profiler.cpp

+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
** LuaProfiler
3+
** Copyright Kepler Project 2005.2007 (http://www.keplerproject.org/luaprofiler)
4+
** $Id: core_profiler.c,v 1.10 2009-01-29 12:39:28 jasonsantos Exp $
5+
*/
6+
7+
/*****************************************************************************
8+
core_profiler.c:
9+
Lua version independent profiler interface.
10+
Responsible for handling the "enter function" and "leave function" events
11+
and for writing the log file.
12+
13+
Design (using the Lua callhook mechanism) :
14+
'lprofP_init_core_profiler' set up the profile service
15+
'lprofP_callhookIN' called whenever Lua enters a function
16+
'lprofP_callhookOUT' called whenever Lua leaves a function
17+
*****************************************************************************/
18+
19+
/*****************************************************************************
20+
The profiled program can be viewed as a graph with the following properties:
21+
directed, multigraph, cyclic and connected. The log file generated by a
22+
profiler section corresponds to a path on this graph.
23+
There are several graphs for which this path fits on. Some times it is
24+
easier to consider this path as being generated by a simpler graph without
25+
properties like cyclic and multigraph.
26+
The profiler log file can be viewed as a "reversed" depth-first search
27+
(with the depth-first search number for each vertex) vertex listing of a graph
28+
with the following properties: simple, acyclic, directed and connected, for
29+
which each vertex appears as many times as needed to strip the cycles and
30+
each vertex has an indegree of 1.
31+
"reversed" depth-first search means that instead of being "printed" before
32+
visiting the vertex's descendents (as done in a normal depth-first search),
33+
the vertex is "printed" only after all his descendents have been processed (in
34+
a depth-first search recursive algorithm).
35+
*****************************************************************************/
36+
37+
#include <stdio.h>
38+
#include <stdlib.h>
39+
#include <string.h>
40+
#include <stdarg.h>
41+
42+
#include "function_meter.h"
43+
44+
#include "core_profiler.h"
45+
46+
/* default log name (%s is used to place a random string) */
47+
#define OUT_FILENAME "lprof_%s.out"
48+
49+
#define MAX_FUNCTION_NAME_LENGTH 20
50+
51+
/* for faster execution (??) */
52+
static FILE *outf;
53+
static lprofS_STACK_RECORD *info;
54+
//static float function_call_time;
55+
56+
57+
/* output a line to the log file, using 'printf()' syntax */
58+
/* assume the timer is off */
59+
static void output(const char *format, ...) {
60+
va_list ap;
61+
va_start(ap, format);
62+
vfprintf(outf, format, ap);
63+
va_end(ap);
64+
65+
/* write now to avoid delays when the timer is on */
66+
fflush(outf);
67+
}
68+
69+
70+
/* do not allow a string with '\n' and '|' (log file format reserved chars) */
71+
/* - replace them by ' ' */
72+
static void formats(char *s) {
73+
int i;
74+
if (!s)
75+
return;
76+
for (i = strlen(s); i >= 0; i--) {
77+
if ((s[i] == '|') || (s[i] == '\n'))
78+
s[i] = ' ';
79+
}
80+
}
81+
82+
int lprofP_output(lprofP_STATE* S){
83+
if (S->stack_level == 0) {
84+
return 0;
85+
}
86+
87+
S->stack_level--;
88+
89+
info = &lprofS_pop(&(S->stack_top));
90+
91+
char* name = info->function_name;
92+
if (strlen(name) > MAX_FUNCTION_NAME_LENGTH) {
93+
name = (char*)malloc(MAX_FUNCTION_NAME_LENGTH + 10);
94+
name[0] = '\"';
95+
strncpy(name + 1, info->function_name, MAX_FUNCTION_NAME_LENGTH);
96+
name[MAX_FUNCTION_NAME_LENGTH] = '"';
97+
name[MAX_FUNCTION_NAME_LENGTH + 1] = '\0';
98+
}
99+
formats(name);
100+
101+
output("%d\t%s\t%s\t%d\t%d\t%f\t%f\n", info->stack_level, info->file_defined, name,
102+
info->line_defined, info->current_line,
103+
info->local_time, info->total_time);
104+
105+
return 1;
106+
}
107+
108+
/* computes new stack and new timer */
109+
void lprofP_callhookIN(lprofP_STATE* S, char *func_name, char *file, int linedefined, int currentline) {
110+
S->stack_level++;
111+
lprofM_enter_function(S, file, func_name, linedefined, currentline);
112+
}
113+
114+
/* pauses all timers to write a log line and computes the new stack */
115+
/* returns if there is another function in the stack */
116+
int lprofP_callhookOUT(lprofP_STATE* S, lprofP_STATE* R) {
117+
if (S->stack_level == 0) {
118+
return 0;
119+
}
120+
121+
S->stack_level--;
122+
123+
/* 0: do not resume the parent function's timer yet... */
124+
info = lprofM_leave_function(S, 0);
125+
126+
// for call stack level
127+
R->stack_level++;
128+
info->stack_level = S->stack_level;
129+
lprofS_push(&(R->stack_top), *info);
130+
131+
if (S->stack_level != 0) {
132+
lprofM_resume_local_time(S);
133+
}
134+
135+
// writing a log may take too long to be computed with the function's time ...
136+
//lprofM_pause_total_time(S);
137+
138+
//if (info->local_time > 0.0000001 || info->total_time > 0.0000001)
139+
//{
140+
// char* source = info->file_defined;
141+
// //if (source[0] != '@') {
142+
// // source = "(string)";
143+
// //}
144+
// //else {
145+
// // formats(source);
146+
// //}
147+
// char* name = info->function_name;
148+
149+
// if (strlen(name) > MAX_FUNCTION_NAME_LENGTH) {
150+
// name = (char*)malloc(MAX_FUNCTION_NAME_LENGTH + 10);
151+
// name[0] = '\"';
152+
// strncpy(name + 1, info->function_name, MAX_FUNCTION_NAME_LENGTH);
153+
// name[MAX_FUNCTION_NAME_LENGTH] = '"';
154+
// name[MAX_FUNCTION_NAME_LENGTH + 1] = '\0';
155+
// }
156+
// formats(name);
157+
// output("%d\t%s\t%s\t%d\t%d\t%f\t%f\n", S->stack_level, source, name,
158+
// info->line_defined, info->current_line,
159+
// info->local_time, info->total_time);
160+
//}
161+
162+
//// ... now it's ok to resume the timer
163+
//if (S->stack_level != 0) {
164+
// lprofM_resume_function(S);
165+
//}
166+
167+
return 1;
168+
169+
}
170+
171+
172+
/* opens the log file */
173+
/* returns true if the file could be opened */
174+
lprofP_STATE* lprofP_init_core_profiler(const char *_out_filename, int isto_printheader, float _function_call_time) {
175+
lprofP_STATE* S;
176+
char auxs[256];
177+
char *s;
178+
char *randstr;
179+
const char *out_filename;
180+
181+
//function_call_time = _function_call_time;
182+
out_filename = (_out_filename) ? (_out_filename) : (OUT_FILENAME);
183+
184+
/* the random string to build the logname is extracted */
185+
/* from 'tmpnam()' (the '/tmp/' part is deleted) */
186+
randstr = tmpnam(NULL);
187+
for (s = strtok(randstr, "/\\"); s; s = strtok(NULL, "/\\")) {
188+
randstr = s;
189+
}
190+
191+
if (randstr[strlen(randstr) - 1] == '.')
192+
randstr[strlen(randstr) - 1] = '\0';
193+
194+
sprintf(auxs, out_filename, randstr);
195+
outf = fopen(auxs, "a");
196+
if (!outf) {
197+
return 0;
198+
}
199+
200+
if (isto_printheader) {
201+
output("stack_level\tfile_defined\tfunction_name\tline_defined\tcurrent_line\tlocal_time\ttotal_time\n");
202+
}
203+
204+
/* initialize the 'function_meter' */
205+
S = lprofM_init();
206+
if (!S) {
207+
fclose(outf);
208+
return 0;
209+
}
210+
211+
return S;
212+
}
213+
214+
void lprofP_close_core_profiler(lprofP_STATE* S) {
215+
if (outf) fclose(outf);
216+
if (S) free(S);
217+
}

core_profiler.h

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
** LuaProfiler
3+
** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
4+
** $Id: core_profiler.h,v 1.6 2007-08-22 19:23:53 carregal Exp $
5+
*/
6+
7+
/*****************************************************************************
8+
core_profiler.h:
9+
Lua version independent profiler interface.
10+
Responsible for handling the "enter function" and "leave function" events
11+
and for writing the log file.
12+
13+
Design (using the Lua callhook mechanism) :
14+
'lprofP_init_core_profiler' set up the profile service
15+
'lprofP_callhookIN' called whenever Lua enters a function
16+
'lprofP_callhookOUT' called whenever Lua leaves a function
17+
*****************************************************************************/
18+
19+
#include "stack.h"
20+
21+
// output result into profiler file
22+
int lprofP_output(lprofP_STATE* S);
23+
24+
/* computes new stack and new timer */
25+
void lprofP_callhookIN(lprofP_STATE* S, char *func_name, char *file, int linedefined, int currentline);
26+
27+
/* pauses all timers to write a log line and computes the new stack */
28+
/* returns if there is another function in the stack */
29+
int lprofP_callhookOUT(lprofP_STATE* S, lprofP_STATE* R);
30+
31+
/* opens the log file */
32+
/* returns true if the file could be opened */
33+
lprofP_STATE* lprofP_init_core_profiler(const char *_out_filename, int isto_printheader, float _function_call_time);
34+
35+
36+
void lprofP_close_core_profiler(lprofP_STATE* S);

0 commit comments

Comments
 (0)