Created
March 20, 2009 17:35
-
-
Save willb/82463 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Simple timing test of exec-ing versus embedding python interpreter. | |
Note that to embed python programs with dynamically loaded extension | |
modules, you'll need to do some special linking tricks: | |
http://www.python.org/doc/2.5.2/ext/link-reqs.html | |
Compile this file with something like: | |
gcc pytest.c -I/usr/include/python2.5 -L/usr/lib64/python2.5 -lpython2.5 -o pytest | |
And then run like this (be sure to redirect stdout to the bit bucket): | |
./pytest 10000 > /dev/null | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <sys/time.h> | |
#include <limits.h> | |
#include <Python.h> | |
const char* noop_program = "import sys; print 'foo'; sys.exit(0)\n"; | |
const char* noop_program_noexit = "import sys; print 'foo'\n"; | |
const char* noop_program_name = "noop_program_XXXXXX"; | |
/* This test just checks to see how quickly we can fork a child | |
process and wait for that child to exit */ | |
void forkTest(int times, int do_wait) { | |
int i; | |
for (i = 0; i < times; i++) { | |
if (fork()) { | |
if (do_wait) { | |
wait(NULL); | |
} | |
} else { | |
exit(0); | |
} | |
} | |
} | |
/* This test repeatedly forks and execs the python interpreter in | |
order to run a trivial program. */ | |
void execPythonInterpreter(int times, int do_wait) { | |
int i; | |
char *scriptname = strdup(noop_program_name); | |
int fd = mkstemp(scriptname); | |
write(fd, noop_program, strlen(noop_program)); | |
fsync(fd); | |
close(fd); | |
for (i = 0; i < times; i++) { | |
if (fork()) { | |
if (do_wait) { | |
wait(NULL); | |
} | |
} else { | |
execlp("python", "-c", scriptname, NULL); | |
exit(0); | |
} | |
} | |
} | |
/* This test repeatedly forks child processes that run the embedded | |
python interpreter */ | |
void runEmbeddedInterpreter(int times, int do_wait) { | |
int i; | |
Py_Initialize(); | |
for (i = 0; i < times; i++) { | |
if (fork()) { | |
if (do_wait) { | |
wait(NULL); | |
} | |
} else { | |
PyRun_SimpleString(noop_program); | |
} | |
} | |
Py_Finalize(); | |
} | |
/* This test repeatedly runs the embedded python interpreter (NB: the | |
script cannot exit or else the test will terminate! */ | |
void runEmbeddedInterpreterNoFork(int times, int do_wait) { | |
int i; | |
Py_Initialize(); | |
for (i = 0; i < times; i++) { | |
PyRun_SimpleString(noop_program_noexit); | |
} | |
Py_Finalize(); | |
} | |
double tv2sec(struct timeval *tv) { | |
return (tv->tv_sec) + ((double)(tv->tv_usec) / 1000000); | |
} | |
typedef void (*trial_t)(int, int); | |
void try_and_report(trial_t t, const char* name, int reps) { | |
struct timeval before, after; | |
double duration; | |
gettimeofday(&before, NULL); | |
t(reps, 1); | |
gettimeofday(&after, NULL); | |
duration = (tv2sec(&after) - tv2sec(&before)); | |
fprintf(stderr, "%12s: %d reps in %g sec; %g reps/sec\n", | |
name, reps, duration, reps/duration); | |
} | |
int main(int c, char *v[]) { | |
int reps = 1000; | |
if (c > 1) { | |
long ureps = strtol(v[1], NULL, 10); | |
if(ureps > 0 && ureps < INT_MAX) { | |
reps = (int)ureps; | |
} | |
} | |
try_and_report(forkTest, "fork-only", reps); | |
try_and_report(execPythonInterpreter, "exec-python", reps); | |
try_and_report(runEmbeddedInterpreter, "embed", reps); | |
try_and_report(runEmbeddedInterpreterNoFork, "emb/nofork", reps); | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment