Skip to content

Instantly share code, notes, and snippets.

@willb
Created March 20, 2009 17:35
Show Gist options
  • Save willb/82463 to your computer and use it in GitHub Desktop.
Save willb/82463 to your computer and use it in GitHub Desktop.
/*
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