Fossil SCM

Added fossil_timer_xxx() family of functions and g.mainTimerId.

stephan 2013-05-08 19:45 trunk
Commit e28433a692fa606e3f12b47aa6d961cc409fd6a3
3 files changed +8 -129 +6 -1 +156
+8 -129
--- src/json.c
+++ src/json.c
@@ -53,131 +53,10 @@
5353
"resultText" /*resultText*/,
5454
"timestamp" /*timestamp*/
5555
};
5656
5757
58
-/* Timer code taken from sqlite3's shell.c, modified slightly.
59
- FIXME: move the timer into the fossil core API so that we can
60
- start the timer early on in the app init phase. Right now we're
61
- just timing the json ops themselves.
62
-*/
63
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
64
-#include <sys/time.h>
65
-#include <sys/resource.h>
66
-
67
-/* Saved resource information for the beginning of an operation */
68
-static struct rusage sBegin;
69
-
70
-/*
71
-** Begin timing an operation
72
-*/
73
-static void beginTimer(void){
74
- getrusage(RUSAGE_SELF, &sBegin);
75
-}
76
-
77
-/* Return the difference of two time_structs in milliseconds */
78
-static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
79
- return ((pEnd->tv_usec - pStart->tv_usec)*0.001 +
80
- (double)((pEnd->tv_sec - pStart->tv_sec)*1000.0));
81
-}
82
-
83
-/*
84
-** Print the timing results.
85
-*/
86
-static double endTimer(void){
87
- struct rusage sEnd;
88
- getrusage(RUSAGE_SELF, &sEnd);
89
-#if 0
90
- printf("CPU Time: user %f sys %f\n",
91
- timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
92
- timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
93
-#endif
94
- return timeDiff(&sBegin.ru_utime, &sEnd.ru_utime)
95
- + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime);
96
-}
97
-
98
-#define BEGIN_TIMER beginTimer()
99
-#define END_TIMER endTimer()
100
-#define HAS_TIMER 1
101
-
102
-#elif (defined(_WIN32) || defined(WIN32))
103
-
104
-#include <windows.h>
105
-
106
-/* Saved resource information for the beginning of an operation */
107
-static HANDLE hProcess;
108
-static FILETIME ftKernelBegin;
109
-static FILETIME ftUserBegin;
110
-typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
111
-static GETPROCTIMES getProcessTimesAddr = NULL;
112
-
113
-/*
114
-** Check to see if we have timer support. Return 1 if necessary
115
-** support found (or found previously).
116
-*/
117
-static int hasTimer(void){
118
- if( getProcessTimesAddr ){
119
- return 1;
120
- } else {
121
- /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions.
122
- ** See if the version we are running on has it, and if it does, save off
123
- ** a pointer to it and the current process handle.
124
- */
125
- hProcess = GetCurrentProcess();
126
- if( hProcess ){
127
- HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
128
- if( NULL != hinstLib ){
129
- getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
130
- if( NULL != getProcessTimesAddr ){
131
- return 1;
132
- }
133
- FreeLibrary(hinstLib);
134
- }
135
- }
136
- }
137
- return 0;
138
-}
139
-
140
-/*
141
-** Begin timing an operation
142
-*/
143
-static void beginTimer(void){
144
- if( getProcessTimesAddr ){
145
- FILETIME ftCreation, ftExit;
146
- getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin);
147
- }
148
-}
149
-
150
-/* Return the difference of two FILETIME structs in milliseconds */
151
-static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
152
- sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
153
- sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
154
- return (double) ((i64End - i64Start) / 10000.0);
155
-}
156
-
157
-/*
158
-** Print the timing results.
159
-*/
160
-static double endTimer(void){
161
- if(getProcessTimesAddr){
162
- FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
163
- getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);
164
- return timeDiff(&ftUserBegin, &ftUserEnd) +
165
- timeDiff(&ftKernelBegin, &ftKernelEnd);
166
- }
167
- return 0.0;
168
-}
169
-
170
-#define BEGIN_TIMER beginTimer()
171
-#define END_TIMER endTimer()
172
-#define HAS_TIMER hasTimer()
173
-
174
-#else
175
-#define BEGIN_TIMER
176
-#define END_TIMER 0.0
177
-#define HAS_TIMER 0
178
-#endif
17958
18059
/*
18160
** Returns true (non-0) if fossil appears to be running in JSON mode.
18261
*/
18362
char fossil_has_json(){
@@ -814,10 +693,11 @@
814693
** up. e.g. it must not use cgi_parameter() and friends because this
815694
** must be called before those data are initialized.
816695
*/
817696
void json_main_bootstrap(){
818697
cson_value * v;
698
+ g.json.timerId = fossil_timer_start();
819699
assert( (NULL == g.json.gc.v) && "cgi_json_bootstrap() was called twice!" );
820700
821701
/* g.json.gc is our "garbage collector" - where we put JSON values
822702
which need a long lifetime but don't have a logical parent to put
823703
them in.
@@ -1544,22 +1424,23 @@
15441424
cson_object_set( o, "cmd.offset", tmp );
15451425
cson_object_set( o, "isCGI", cson_value_new_bool( g.isHTTP ) );
15461426
}
15471427
}
15481428
1549
- if(HAS_TIMER){
1429
+ if(fossil_has_timer()){
15501430
/* This is, philosophically speaking, not quite the right place
15511431
for ending the timer, but this is the one function which all of
15521432
the JSON exit paths use (and they call it after processing,
15531433
just before they end).
15541434
*/
1555
- double span;
1556
- span = END_TIMER;
1557
- /* I'm actually seeing sub-ms runtimes in some tests, but a time of
1558
- 0 is "just wrong", so we'll bump that up to 1ms.
1435
+ sqlite3_uint64 span = fossil_timer_fetch(g.json.timerId);
1436
+ /* I'm actually seeing sub-uSec runtimes in some tests, but a time of
1437
+ 0 is "just kinda wrong".
15591438
*/
1560
- cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)((span>1.0)?span:1)));
1439
+ cson_object_set(o,"procTimeUs", cson_value_new_integer((cson_int_t)span));
1440
+ span /= 1000/*for milliseconds */;
1441
+ cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)span));
15611442
}
15621443
if(g.json.warnings){
15631444
tmp = cson_array_value(g.json.warnings);
15641445
SET("warnings");
15651446
}
@@ -2334,11 +2215,10 @@
23342215
** This function dispatches them, and is the HTTP equivalent of
23352216
** json_cmd_top().
23362217
*/
23372218
void json_page_top(void){
23382219
char const * zCommand;
2339
- BEGIN_TIMER;
23402220
json_mode_bootstrap();
23412221
zCommand = json_command_arg(1);
23422222
if(!zCommand || !*zCommand){
23432223
json_dispatch_missing_args_err( JsonPageDefs,
23442224
"No command (sub-path) specified."
@@ -2392,11 +2272,10 @@
23922272
**
23932273
*/
23942274
void json_cmd_top(void){
23952275
char const * cmd = NULL;
23962276
int rc = 0;
2397
- BEGIN_TIMER;
23982277
memset( &g.perm, 0xff, sizeof(g.perm) )
23992278
/* In CLI mode fossil does not use permissions
24002279
and they all default to false. We enable them
24012280
here because (A) fossil doesn't use them in local
24022281
mode but (B) having them set gives us one less
24032282
--- src/json.c
+++ src/json.c
@@ -53,131 +53,10 @@
53 "resultText" /*resultText*/,
54 "timestamp" /*timestamp*/
55 };
56
57
58 /* Timer code taken from sqlite3's shell.c, modified slightly.
59 FIXME: move the timer into the fossil core API so that we can
60 start the timer early on in the app init phase. Right now we're
61 just timing the json ops themselves.
62 */
63 #if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
64 #include <sys/time.h>
65 #include <sys/resource.h>
66
67 /* Saved resource information for the beginning of an operation */
68 static struct rusage sBegin;
69
70 /*
71 ** Begin timing an operation
72 */
73 static void beginTimer(void){
74 getrusage(RUSAGE_SELF, &sBegin);
75 }
76
77 /* Return the difference of two time_structs in milliseconds */
78 static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
79 return ((pEnd->tv_usec - pStart->tv_usec)*0.001 +
80 (double)((pEnd->tv_sec - pStart->tv_sec)*1000.0));
81 }
82
83 /*
84 ** Print the timing results.
85 */
86 static double endTimer(void){
87 struct rusage sEnd;
88 getrusage(RUSAGE_SELF, &sEnd);
89 #if 0
90 printf("CPU Time: user %f sys %f\n",
91 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
92 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
93 #endif
94 return timeDiff(&sBegin.ru_utime, &sEnd.ru_utime)
95 + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime);
96 }
97
98 #define BEGIN_TIMER beginTimer()
99 #define END_TIMER endTimer()
100 #define HAS_TIMER 1
101
102 #elif (defined(_WIN32) || defined(WIN32))
103
104 #include <windows.h>
105
106 /* Saved resource information for the beginning of an operation */
107 static HANDLE hProcess;
108 static FILETIME ftKernelBegin;
109 static FILETIME ftUserBegin;
110 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
111 static GETPROCTIMES getProcessTimesAddr = NULL;
112
113 /*
114 ** Check to see if we have timer support. Return 1 if necessary
115 ** support found (or found previously).
116 */
117 static int hasTimer(void){
118 if( getProcessTimesAddr ){
119 return 1;
120 } else {
121 /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions.
122 ** See if the version we are running on has it, and if it does, save off
123 ** a pointer to it and the current process handle.
124 */
125 hProcess = GetCurrentProcess();
126 if( hProcess ){
127 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
128 if( NULL != hinstLib ){
129 getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
130 if( NULL != getProcessTimesAddr ){
131 return 1;
132 }
133 FreeLibrary(hinstLib);
134 }
135 }
136 }
137 return 0;
138 }
139
140 /*
141 ** Begin timing an operation
142 */
143 static void beginTimer(void){
144 if( getProcessTimesAddr ){
145 FILETIME ftCreation, ftExit;
146 getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin);
147 }
148 }
149
150 /* Return the difference of two FILETIME structs in milliseconds */
151 static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
152 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
153 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
154 return (double) ((i64End - i64Start) / 10000.0);
155 }
156
157 /*
158 ** Print the timing results.
159 */
160 static double endTimer(void){
161 if(getProcessTimesAddr){
162 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
163 getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);
164 return timeDiff(&ftUserBegin, &ftUserEnd) +
165 timeDiff(&ftKernelBegin, &ftKernelEnd);
166 }
167 return 0.0;
168 }
169
170 #define BEGIN_TIMER beginTimer()
171 #define END_TIMER endTimer()
172 #define HAS_TIMER hasTimer()
173
174 #else
175 #define BEGIN_TIMER
176 #define END_TIMER 0.0
177 #define HAS_TIMER 0
178 #endif
179
180 /*
181 ** Returns true (non-0) if fossil appears to be running in JSON mode.
182 */
183 char fossil_has_json(){
@@ -814,10 +693,11 @@
814 ** up. e.g. it must not use cgi_parameter() and friends because this
815 ** must be called before those data are initialized.
816 */
817 void json_main_bootstrap(){
818 cson_value * v;
 
819 assert( (NULL == g.json.gc.v) && "cgi_json_bootstrap() was called twice!" );
820
821 /* g.json.gc is our "garbage collector" - where we put JSON values
822 which need a long lifetime but don't have a logical parent to put
823 them in.
@@ -1544,22 +1424,23 @@
1544 cson_object_set( o, "cmd.offset", tmp );
1545 cson_object_set( o, "isCGI", cson_value_new_bool( g.isHTTP ) );
1546 }
1547 }
1548
1549 if(HAS_TIMER){
1550 /* This is, philosophically speaking, not quite the right place
1551 for ending the timer, but this is the one function which all of
1552 the JSON exit paths use (and they call it after processing,
1553 just before they end).
1554 */
1555 double span;
1556 span = END_TIMER;
1557 /* I'm actually seeing sub-ms runtimes in some tests, but a time of
1558 0 is "just wrong", so we'll bump that up to 1ms.
1559 */
1560 cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)((span>1.0)?span:1)));
 
 
1561 }
1562 if(g.json.warnings){
1563 tmp = cson_array_value(g.json.warnings);
1564 SET("warnings");
1565 }
@@ -2334,11 +2215,10 @@
2334 ** This function dispatches them, and is the HTTP equivalent of
2335 ** json_cmd_top().
2336 */
2337 void json_page_top(void){
2338 char const * zCommand;
2339 BEGIN_TIMER;
2340 json_mode_bootstrap();
2341 zCommand = json_command_arg(1);
2342 if(!zCommand || !*zCommand){
2343 json_dispatch_missing_args_err( JsonPageDefs,
2344 "No command (sub-path) specified."
@@ -2392,11 +2272,10 @@
2392 **
2393 */
2394 void json_cmd_top(void){
2395 char const * cmd = NULL;
2396 int rc = 0;
2397 BEGIN_TIMER;
2398 memset( &g.perm, 0xff, sizeof(g.perm) )
2399 /* In CLI mode fossil does not use permissions
2400 and they all default to false. We enable them
2401 here because (A) fossil doesn't use them in local
2402 mode but (B) having them set gives us one less
2403
--- src/json.c
+++ src/json.c
@@ -53,131 +53,10 @@
53 "resultText" /*resultText*/,
54 "timestamp" /*timestamp*/
55 };
56
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
59 /*
60 ** Returns true (non-0) if fossil appears to be running in JSON mode.
61 */
62 char fossil_has_json(){
@@ -814,10 +693,11 @@
693 ** up. e.g. it must not use cgi_parameter() and friends because this
694 ** must be called before those data are initialized.
695 */
696 void json_main_bootstrap(){
697 cson_value * v;
698 g.json.timerId = fossil_timer_start();
699 assert( (NULL == g.json.gc.v) && "cgi_json_bootstrap() was called twice!" );
700
701 /* g.json.gc is our "garbage collector" - where we put JSON values
702 which need a long lifetime but don't have a logical parent to put
703 them in.
@@ -1544,22 +1424,23 @@
1424 cson_object_set( o, "cmd.offset", tmp );
1425 cson_object_set( o, "isCGI", cson_value_new_bool( g.isHTTP ) );
1426 }
1427 }
1428
1429 if(fossil_has_timer()){
1430 /* This is, philosophically speaking, not quite the right place
1431 for ending the timer, but this is the one function which all of
1432 the JSON exit paths use (and they call it after processing,
1433 just before they end).
1434 */
1435 sqlite3_uint64 span = fossil_timer_fetch(g.json.timerId);
1436 /* I'm actually seeing sub-uSec runtimes in some tests, but a time of
1437 0 is "just kinda wrong".
 
1438 */
1439 cson_object_set(o,"procTimeUs", cson_value_new_integer((cson_int_t)span));
1440 span /= 1000/*for milliseconds */;
1441 cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)span));
1442 }
1443 if(g.json.warnings){
1444 tmp = cson_array_value(g.json.warnings);
1445 SET("warnings");
1446 }
@@ -2334,11 +2215,10 @@
2215 ** This function dispatches them, and is the HTTP equivalent of
2216 ** json_cmd_top().
2217 */
2218 void json_page_top(void){
2219 char const * zCommand;
 
2220 json_mode_bootstrap();
2221 zCommand = json_command_arg(1);
2222 if(!zCommand || !*zCommand){
2223 json_dispatch_missing_args_err( JsonPageDefs,
2224 "No command (sub-path) specified."
@@ -2392,11 +2272,10 @@
2272 **
2273 */
2274 void json_cmd_top(void){
2275 char const * cmd = NULL;
2276 int rc = 0;
 
2277 memset( &g.perm, 0xff, sizeof(g.perm) )
2278 /* In CLI mode fossil does not use permissions
2279 and they all default to false. We enable them
2280 here because (A) fossil doesn't use them in local
2281 mode but (B) having them set gives us one less
2282
+6 -1
--- src/main.c
+++ src/main.c
@@ -218,10 +218,11 @@
218218
const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
219219
int anAuxCols[MX_AUX]; /* Number of columns for option() values */
220220
221221
int allowSymlinks; /* Cached "allow-symlinks" option */
222222
223
+ int mainTimerId; /* Set to fossil_timer_start() */
223224
#ifdef FOSSIL_ENABLE_JSON
224225
struct FossilJsonBits {
225226
int isJsonMode; /* True if running in JSON mode, else
226227
false. This changes how errors are
227228
reported. In JSON mode we try to
@@ -266,10 +267,11 @@
266267
struct {
267268
cson_value * v;
268269
cson_object * o;
269270
} reqPayload; /* request payload object (if any) */
270271
cson_array * warnings; /* response warnings */
272
+ int timerId; /* fetched from fossil_timer_start() */
271273
} json;
272274
#endif /* FOSSIL_ENABLE_JSON */
273275
};
274276
275277
/*
@@ -511,11 +513,11 @@
511513
#endif
512514
{
513515
const char *zCmdName = "unknown";
514516
int idx;
515517
int rc;
516
-
518
+ int timerId;
517519
sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
518520
memset(&g, 0, sizeof(g));
519521
g.now = time(0);
520522
#ifdef FOSSIL_ENABLE_JSON
521523
#if defined(NDEBUG)
@@ -534,10 +536,13 @@
534536
#ifdef FOSSIL_ENABLE_TCL
535537
memset(&g.tcl, 0, sizeof(TclContext));
536538
g.tcl.argc = g.argc;
537539
g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
538540
#endif
541
+
542
+ g.mainTimerId = fossil_timer_start();
543
+
539544
if( fossil_getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
540545
zCmdName = "cgi";
541546
g.isHTTP = 1;
542547
}else if( g.argc<2 ){
543548
fossil_print(
544549
--- src/main.c
+++ src/main.c
@@ -218,10 +218,11 @@
218 const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
219 int anAuxCols[MX_AUX]; /* Number of columns for option() values */
220
221 int allowSymlinks; /* Cached "allow-symlinks" option */
222
 
223 #ifdef FOSSIL_ENABLE_JSON
224 struct FossilJsonBits {
225 int isJsonMode; /* True if running in JSON mode, else
226 false. This changes how errors are
227 reported. In JSON mode we try to
@@ -266,10 +267,11 @@
266 struct {
267 cson_value * v;
268 cson_object * o;
269 } reqPayload; /* request payload object (if any) */
270 cson_array * warnings; /* response warnings */
 
271 } json;
272 #endif /* FOSSIL_ENABLE_JSON */
273 };
274
275 /*
@@ -511,11 +513,11 @@
511 #endif
512 {
513 const char *zCmdName = "unknown";
514 int idx;
515 int rc;
516
517 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
518 memset(&g, 0, sizeof(g));
519 g.now = time(0);
520 #ifdef FOSSIL_ENABLE_JSON
521 #if defined(NDEBUG)
@@ -534,10 +536,13 @@
534 #ifdef FOSSIL_ENABLE_TCL
535 memset(&g.tcl, 0, sizeof(TclContext));
536 g.tcl.argc = g.argc;
537 g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
538 #endif
 
 
 
539 if( fossil_getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
540 zCmdName = "cgi";
541 g.isHTTP = 1;
542 }else if( g.argc<2 ){
543 fossil_print(
544
--- src/main.c
+++ src/main.c
@@ -218,10 +218,11 @@
218 const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
219 int anAuxCols[MX_AUX]; /* Number of columns for option() values */
220
221 int allowSymlinks; /* Cached "allow-symlinks" option */
222
223 int mainTimerId; /* Set to fossil_timer_start() */
224 #ifdef FOSSIL_ENABLE_JSON
225 struct FossilJsonBits {
226 int isJsonMode; /* True if running in JSON mode, else
227 false. This changes how errors are
228 reported. In JSON mode we try to
@@ -266,10 +267,11 @@
267 struct {
268 cson_value * v;
269 cson_object * o;
270 } reqPayload; /* request payload object (if any) */
271 cson_array * warnings; /* response warnings */
272 int timerId; /* fetched from fossil_timer_start() */
273 } json;
274 #endif /* FOSSIL_ENABLE_JSON */
275 };
276
277 /*
@@ -511,11 +513,11 @@
513 #endif
514 {
515 const char *zCmdName = "unknown";
516 int idx;
517 int rc;
518 int timerId;
519 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
520 memset(&g, 0, sizeof(g));
521 g.now = time(0);
522 #ifdef FOSSIL_ENABLE_JSON
523 #if defined(NDEBUG)
@@ -534,10 +536,13 @@
536 #ifdef FOSSIL_ENABLE_TCL
537 memset(&g.tcl, 0, sizeof(TclContext));
538 g.tcl.argc = g.argc;
539 g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
540 #endif
541
542 g.mainTimerId = fossil_timer_start();
543
544 if( fossil_getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
545 zCmdName = "cgi";
546 g.isHTTP = 1;
547 }else if( g.argc<2 ){
548 fossil_print(
549
+156
--- src/util.c
+++ src/util.c
@@ -17,10 +17,21 @@
1717
**
1818
** This file contains code for miscellaneous utility routines.
1919
*/
2020
#include "config.h"
2121
#include "util.h"
22
+
23
+/*
24
+** For the fossil_timer_xxx() family of functions...
25
+*/
26
+#ifdef _WIN32
27
+# include <windows.h>
28
+#else
29
+# include <sys/time.h>
30
+# include <sys/resource.h>
31
+#endif
32
+
2233
2334
/*
2435
** Exit. Take care to close the database first.
2536
*/
2637
NORETURN void fossil_exit(int rc){
@@ -134,5 +145,150 @@
134145
nByte = strlen(zB);
135146
rc = sqlite3_strnicmp(zA, zB, nByte);
136147
if( rc==0 && zA[nByte] ) rc = 1;
137148
return rc;
138149
}
150
+
151
+/*
152
+** Get user and kernel times in microseconds.
153
+*/
154
+void fossil_cpu_times(sqlite3_uint64 *piUser, sqlite3_uint64 *piKernel){
155
+#ifdef _WIN32
156
+ FILETIME not_used;
157
+ FILETIME kernel_time;
158
+ FILETIME user_time;
159
+ GetProcessTimes(GetCurrentProcess(), &not_used, &not_used,
160
+ &kernel_time, &user_time);
161
+ if( piUser ){
162
+ *piUser = ((((sqlite3_uint64)user_time.dwHighDateTime)<<32) +
163
+ (sqlite3_uint64)user_time.dwLowDateTime + 5)/10;
164
+ }
165
+ if( piKernel ){
166
+ *piKernel = ((((sqlite3_uint64)kernel_time.dwHighDateTime)<<32) +
167
+ (sqlite3_uint64)kernel_time.dwLowDateTime + 5)/10;
168
+ }
169
+#else
170
+ struct rusage s;
171
+ getrusage(RUSAGE_SELF, &s);
172
+ if( piUser ){
173
+ *piUser = ((sqlite3_uint64)s.ru_utime.tv_sec)*1000000 + s.ru_utime.tv_usec;
174
+ }
175
+ if( piKernel ){
176
+ *piKernel =
177
+ ((sqlite3_uint64)s.ru_stime.tv_sec)*1000000 + s.ru_stime.tv_usec;
178
+ }
179
+#endif
180
+}
181
+
182
+/*
183
+** Internal helper type for fossil_timer_xxx().
184
+ */
185
+static struct FossilTimer {
186
+ sqlite3_uint64 u; /* "User" CPU times */
187
+ sqlite3_uint64 s; /* "System" CPU times */
188
+ char used; /* 1 if timer is allocated, else 0. */
189
+} fossilTimer = { 0U, 0U, 0 };
190
+enum FossilTimerEnum {
191
+ FOSSIL_TIMER_COUNT = 10 /* Number of timers we can stack. */
192
+};
193
+static struct FossilTimer fossilTimerList[FOSSIL_TIMER_COUNT] = {{0,0,0}};
194
+
195
+/*
196
+** Stores the current CPU times into the shared timer list
197
+** and returns that timer's internal ID. Pass that ID to
198
+** fossil_timer_fetch() to get the elapsed time for that
199
+** timer.
200
+**
201
+** The system has a fixed number of timers, and they can be
202
+** "deallocated" by passing this function's return value to
203
+** fossil_timer_stop() Adjust FOSSIL_TIMER_COUNT to set the number of
204
+** available timers.
205
+**
206
+** Returns -1 on error (no more timers available), with 0 or greater
207
+** being valid timer IDs.
208
+*/
209
+int fossil_timer_start(){
210
+ int i;
211
+ static char once = 0;
212
+ if(!once){
213
+ memset(&fossilTimerList, 0,
214
+ sizeof(fossilTimerList)/sizeof(fossilTimerList[0]));
215
+ }
216
+ for( i = 0; i < FOSSIL_TIMER_COUNT; ++i ){
217
+ struct FossilTimer * ft = &fossilTimerList[i];
218
+ if(ft->used) continue;
219
+ ft->used = 1;
220
+ fossil_cpu_times( &ft->u, &ft->s );
221
+ break;
222
+ }
223
+ return (i<FOSSIL_TIMER_COUNT) ? i : -1;
224
+}
225
+
226
+/*
227
+** Returns the difference in CPU times in microseconds since
228
+** fossil_timer_start() was called and returned the given timer ID (or
229
+** since it was last reset). Returns 0 if timerId is out of range.
230
+*/
231
+sqlite3_uint64 fossil_timer_fetch(int timerId){
232
+ if(timerId<0 || timerId>=FOSSIL_TIMER_COUNT){
233
+ return 0;
234
+ }else{
235
+ struct FossilTimer * start = &fossilTimerList[timerId];
236
+ if( ! start->used ){
237
+ fossil_fatal("Invalid call to reset a non-allocated "
238
+ "timer (#%d)", timerId);
239
+ /*NOTREACHED*/
240
+ }else{
241
+ sqlite3_uint64 eu = 0, es = 0;
242
+ fossil_cpu_times( &eu, &es );
243
+ return (eu - start->u) + (es - start->s);
244
+ }
245
+ }
246
+}
247
+
248
+/*
249
+** Resets the timer associated with the given ID, as obtained via
250
+** fossil_timer_start(), to the current CPU time values.
251
+*/
252
+sqlite3_uint64 fossil_timer_reset(int timerId){
253
+ if(timerId<0 || timerId>=FOSSIL_TIMER_COUNT){
254
+ return 0;
255
+ }else{
256
+ struct FossilTimer * start = &fossilTimerList[timerId];
257
+ if( ! start->used ){
258
+ fossil_fatal("Invalid call to reset a non-allocated "
259
+ "timer (#%d)", timerId);
260
+ /*NOTREACHED*/
261
+ }else{
262
+ sqlite3_uint64 const rc = fossil_timer_fetch(timerId);
263
+ fossil_cpu_times( &start->u, &start->s );
264
+ return rc;
265
+ }
266
+ }
267
+}
268
+
269
+/**
270
+ "Deallocates" the fossil timer identified by the given timer ID.
271
+ returns the difference (in uSec) between the last time that timer
272
+ was started or reset. Returns 0 if timerId is out of range. It is
273
+ not legal to re-use the passed-in timerId after calling this
274
+ until/unless it is re-initialized using fossil_timer_start() (NOT
275
+ fossil_timer_reset()).
276
+*/
277
+sqlite3_uint64 fossil_timer_stop(int timerId){
278
+ if(timerId<0 || timerId>=FOSSIL_TIMER_COUNT){
279
+ return 0;
280
+ }else{
281
+ sqlite3_uint64 const rc = fossil_timer_fetch(timerId);
282
+ struct FossilTimer * t = &fossilTimerList[timerId];
283
+ t->used = 0;
284
+ t->u = t->s = 0U;
285
+ return rc;
286
+ }
287
+}
288
+
289
+/*
290
+** Returns 1 if fossil has timer capabilities.
291
+*/
292
+int fossil_has_timer(){
293
+ return 1;
294
+}
139295
--- src/util.c
+++ src/util.c
@@ -17,10 +17,21 @@
17 **
18 ** This file contains code for miscellaneous utility routines.
19 */
20 #include "config.h"
21 #include "util.h"
 
 
 
 
 
 
 
 
 
 
 
22
23 /*
24 ** Exit. Take care to close the database first.
25 */
26 NORETURN void fossil_exit(int rc){
@@ -134,5 +145,150 @@
134 nByte = strlen(zB);
135 rc = sqlite3_strnicmp(zA, zB, nByte);
136 if( rc==0 && zA[nByte] ) rc = 1;
137 return rc;
138 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
--- src/util.c
+++ src/util.c
@@ -17,10 +17,21 @@
17 **
18 ** This file contains code for miscellaneous utility routines.
19 */
20 #include "config.h"
21 #include "util.h"
22
23 /*
24 ** For the fossil_timer_xxx() family of functions...
25 */
26 #ifdef _WIN32
27 # include <windows.h>
28 #else
29 # include <sys/time.h>
30 # include <sys/resource.h>
31 #endif
32
33
34 /*
35 ** Exit. Take care to close the database first.
36 */
37 NORETURN void fossil_exit(int rc){
@@ -134,5 +145,150 @@
145 nByte = strlen(zB);
146 rc = sqlite3_strnicmp(zA, zB, nByte);
147 if( rc==0 && zA[nByte] ) rc = 1;
148 return rc;
149 }
150
151 /*
152 ** Get user and kernel times in microseconds.
153 */
154 void fossil_cpu_times(sqlite3_uint64 *piUser, sqlite3_uint64 *piKernel){
155 #ifdef _WIN32
156 FILETIME not_used;
157 FILETIME kernel_time;
158 FILETIME user_time;
159 GetProcessTimes(GetCurrentProcess(), &not_used, &not_used,
160 &kernel_time, &user_time);
161 if( piUser ){
162 *piUser = ((((sqlite3_uint64)user_time.dwHighDateTime)<<32) +
163 (sqlite3_uint64)user_time.dwLowDateTime + 5)/10;
164 }
165 if( piKernel ){
166 *piKernel = ((((sqlite3_uint64)kernel_time.dwHighDateTime)<<32) +
167 (sqlite3_uint64)kernel_time.dwLowDateTime + 5)/10;
168 }
169 #else
170 struct rusage s;
171 getrusage(RUSAGE_SELF, &s);
172 if( piUser ){
173 *piUser = ((sqlite3_uint64)s.ru_utime.tv_sec)*1000000 + s.ru_utime.tv_usec;
174 }
175 if( piKernel ){
176 *piKernel =
177 ((sqlite3_uint64)s.ru_stime.tv_sec)*1000000 + s.ru_stime.tv_usec;
178 }
179 #endif
180 }
181
182 /*
183 ** Internal helper type for fossil_timer_xxx().
184 */
185 static struct FossilTimer {
186 sqlite3_uint64 u; /* "User" CPU times */
187 sqlite3_uint64 s; /* "System" CPU times */
188 char used; /* 1 if timer is allocated, else 0. */
189 } fossilTimer = { 0U, 0U, 0 };
190 enum FossilTimerEnum {
191 FOSSIL_TIMER_COUNT = 10 /* Number of timers we can stack. */
192 };
193 static struct FossilTimer fossilTimerList[FOSSIL_TIMER_COUNT] = {{0,0,0}};
194
195 /*
196 ** Stores the current CPU times into the shared timer list
197 ** and returns that timer's internal ID. Pass that ID to
198 ** fossil_timer_fetch() to get the elapsed time for that
199 ** timer.
200 **
201 ** The system has a fixed number of timers, and they can be
202 ** "deallocated" by passing this function's return value to
203 ** fossil_timer_stop() Adjust FOSSIL_TIMER_COUNT to set the number of
204 ** available timers.
205 **
206 ** Returns -1 on error (no more timers available), with 0 or greater
207 ** being valid timer IDs.
208 */
209 int fossil_timer_start(){
210 int i;
211 static char once = 0;
212 if(!once){
213 memset(&fossilTimerList, 0,
214 sizeof(fossilTimerList)/sizeof(fossilTimerList[0]));
215 }
216 for( i = 0; i < FOSSIL_TIMER_COUNT; ++i ){
217 struct FossilTimer * ft = &fossilTimerList[i];
218 if(ft->used) continue;
219 ft->used = 1;
220 fossil_cpu_times( &ft->u, &ft->s );
221 break;
222 }
223 return (i<FOSSIL_TIMER_COUNT) ? i : -1;
224 }
225
226 /*
227 ** Returns the difference in CPU times in microseconds since
228 ** fossil_timer_start() was called and returned the given timer ID (or
229 ** since it was last reset). Returns 0 if timerId is out of range.
230 */
231 sqlite3_uint64 fossil_timer_fetch(int timerId){
232 if(timerId<0 || timerId>=FOSSIL_TIMER_COUNT){
233 return 0;
234 }else{
235 struct FossilTimer * start = &fossilTimerList[timerId];
236 if( ! start->used ){
237 fossil_fatal("Invalid call to reset a non-allocated "
238 "timer (#%d)", timerId);
239 /*NOTREACHED*/
240 }else{
241 sqlite3_uint64 eu = 0, es = 0;
242 fossil_cpu_times( &eu, &es );
243 return (eu - start->u) + (es - start->s);
244 }
245 }
246 }
247
248 /*
249 ** Resets the timer associated with the given ID, as obtained via
250 ** fossil_timer_start(), to the current CPU time values.
251 */
252 sqlite3_uint64 fossil_timer_reset(int timerId){
253 if(timerId<0 || timerId>=FOSSIL_TIMER_COUNT){
254 return 0;
255 }else{
256 struct FossilTimer * start = &fossilTimerList[timerId];
257 if( ! start->used ){
258 fossil_fatal("Invalid call to reset a non-allocated "
259 "timer (#%d)", timerId);
260 /*NOTREACHED*/
261 }else{
262 sqlite3_uint64 const rc = fossil_timer_fetch(timerId);
263 fossil_cpu_times( &start->u, &start->s );
264 return rc;
265 }
266 }
267 }
268
269 /**
270 "Deallocates" the fossil timer identified by the given timer ID.
271 returns the difference (in uSec) between the last time that timer
272 was started or reset. Returns 0 if timerId is out of range. It is
273 not legal to re-use the passed-in timerId after calling this
274 until/unless it is re-initialized using fossil_timer_start() (NOT
275 fossil_timer_reset()).
276 */
277 sqlite3_uint64 fossil_timer_stop(int timerId){
278 if(timerId<0 || timerId>=FOSSIL_TIMER_COUNT){
279 return 0;
280 }else{
281 sqlite3_uint64 const rc = fossil_timer_fetch(timerId);
282 struct FossilTimer * t = &fossilTimerList[timerId];
283 t->used = 0;
284 t->u = t->s = 0U;
285 return rc;
286 }
287 }
288
289 /*
290 ** Returns 1 if fossil has timer capabilities.
291 */
292 int fossil_has_timer(){
293 return 1;
294 }
295

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button