📄 _hotshot.c
字号:
static char profiler_object__doc__[] =
"High-performance profiler object.\n"
"\n"
"Methods:\n"
"\n"
"close(): Stop the profiler and close the log files.\n"
"runcall(): Run a single function call with profiling enabled.\n"
"runcode(): Execute a code object with profiling enabled.\n"
"start(): Install the profiler and return.\n"
"stop(): Remove the profiler.\n"
"\n"
"Attributes (read-only):\n"
"\n"
"closed: True if the profiler has already been closed.\n"
"frametimings: True if ENTER/EXIT events collect timing information.\n"
"lineevents: True if SET_LINENO events are reported to the profiler.\n"
"linetimings: True if SET_LINENO events collect timing information.";
static PyTypeObject ProfilerType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"_hotshot.ProfilerType", /* tp_name */
(int) sizeof(ProfilerObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)profiler_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)profiler_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
profiler_object__doc__, /* tp_doc */
};
static PyMethodDef logreader_methods[] = {
{"close", (PyCFunction)logreader_close, METH_VARARGS,
logreader_close__doc__},
{"next", (PyCFunction)logreader_next, METH_VARARGS,
next__doc__},
{NULL, NULL}
};
static PyObject *
logreader_getattr(LogReaderObject *self, char *name)
{
if (strcmp(name, "info") == 0) {
Py_INCREF(self->info);
return self->info;
}
return Py_FindMethod(logreader_methods, (PyObject *)self, name);
}
static char logreader__doc__[] = "\
logreader(filename) --> log-iterator\n\
Create a log-reader for the timing information file.";
static PySequenceMethods logreader_as_sequence = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
(intargfunc)logreader_sq_item, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
0, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
static PyTypeObject LogReaderType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"_hotshot.LogReaderType", /* tp_name */
(int) sizeof(LogReaderObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)logreader_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)logreader_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
&logreader_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
logreader__doc__, /* tp_doc */
#if Py_TPFLAGS_HAVE_ITER
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)logreader_tp_iter, /* tp_iter */
(iternextfunc)logreader_tp_iternext,/* tp_iternext */
#endif
};
static PyObject *
hotshot_logreader(PyObject *unused, PyObject *args)
{
LogReaderObject *self = NULL;
char *filename;
int c;
int err = 0;
if (PyArg_ParseTuple(args, "s:logreader", &filename)) {
self = PyObject_New(LogReaderObject, &LogReaderType);
if (self != NULL) {
self->frametimings = 1;
self->linetimings = 0;
self->info = NULL;
self->logfp = fopen(filename, "rb");
if (self->logfp == NULL) {
PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
Py_DECREF(self);
self = NULL;
goto finally;
}
self->info = PyDict_New();
if (self->info == NULL) {
Py_DECREF(self);
goto finally;
}
/* read initial info */
for (;;) {
if ((c = fgetc(self->logfp)) == EOF) {
eof_error();
break;
}
if (c != WHAT_ADD_INFO) {
ungetc(c, self->logfp);
break;
}
err = unpack_add_info(self);
if (err) {
if (err == ERR_EOF)
eof_error();
else
PyErr_SetString(PyExc_RuntimeError,
"unexpected error");
break;
}
}
}
}
finally:
return (PyObject *) self;
}
/* Return a Python string that represents the version number without the
* extra cruft added by revision control, even if the right options were
* given to the "cvs export" command to make it not include the extra
* cruft.
*/
static char *
get_version_string(void)
{
static char *rcsid = "$Revision: 1.1 $";
char *rev = rcsid;
char *buffer;
int i = 0;
while (*rev && !isdigit(*rev))
++rev;
while (rev[i] != ' ' && rev[i] != '\0')
++i;
buffer = malloc(i + 1);
if (buffer != NULL) {
memmove(buffer, rev, i);
buffer[i] = '\0';
}
return buffer;
}
/* Write out a RFC 822-style header with various useful bits of
* information to make the output easier to manage.
*/
static int
write_header(ProfilerObject *self)
{
char *buffer;
char cwdbuffer[PATH_MAX];
PyObject *temp;
int i, len;
buffer = get_version_string();
if (buffer == NULL) {
PyErr_NoMemory();
return -1;
}
pack_add_info(self, "hotshot-version", buffer);
pack_add_info(self, "requested-frame-timings",
(self->frametimings ? "yes" : "no"));
pack_add_info(self, "requested-line-events",
(self->lineevents ? "yes" : "no"));
pack_add_info(self, "requested-line-timings",
(self->linetimings ? "yes" : "no"));
pack_add_info(self, "platform", Py_GetPlatform());
pack_add_info(self, "executable", Py_GetProgramFullPath());
free(buffer);
buffer = (char *) Py_GetVersion();
if (buffer == NULL)
PyErr_Clear();
else
pack_add_info(self, "executable-version", buffer);
#ifdef MS_WIN32
PyOS_snprintf(cwdbuffer, sizeof(cwdbuffer), "%I64d", frequency.QuadPart);
pack_add_info(self, "reported-performance-frequency", cwdbuffer);
#else
PyOS_snprintf(cwdbuffer, sizeof(cwdbuffer), "%lu", rusage_diff);
pack_add_info(self, "observed-interval-getrusage", cwdbuffer);
PyOS_snprintf(cwdbuffer, sizeof(cwdbuffer), "%lu", timeofday_diff);
pack_add_info(self, "observed-interval-gettimeofday", cwdbuffer);
#endif
pack_add_info(self, "current-directory",
getcwd(cwdbuffer, sizeof cwdbuffer));
temp = PySys_GetObject("path");
len = PyList_GET_SIZE(temp);
for (i = 0; i < len; ++i) {
PyObject *item = PyList_GET_ITEM(temp, i);
buffer = PyString_AsString(item);
if (buffer == NULL)
return -1;
pack_add_info(self, "sys-path-entry", buffer);
}
pack_frame_times(self);
pack_line_times(self);
return 0;
}
static char profiler__doc__[] = "\
profiler(logfilename[, lineevents[, linetimes]]) -> profiler\n\
Create a new profiler object.";
static PyObject *
hotshot_profiler(PyObject *unused, PyObject *args)
{
char *logfilename;
ProfilerObject *self = NULL;
int lineevents = 0;
int linetimings = 1;
if (PyArg_ParseTuple(args, "s|ii:profiler", &logfilename,
&lineevents, &linetimings)) {
self = PyObject_New(ProfilerObject, &ProfilerType);
if (self == NULL)
return NULL;
self->frametimings = 1;
self->lineevents = lineevents ? 1 : 0;
self->linetimings = (lineevents && linetimings) ? 1 : 0;
self->index = 0;
self->active = 0;
self->next_fileno = 0;
self->logfp = NULL;
self->logfilename = PyTuple_GET_ITEM(args, 0);
Py_INCREF(self->logfilename);
self->filemap = PyDict_New();
if (self->filemap == NULL) {
Py_DECREF(self);
return NULL;
}
self->logfp = fopen(logfilename, "wb");
if (self->logfp == NULL) {
Py_DECREF(self);
PyErr_SetFromErrnoWithFilename(PyExc_IOError, logfilename);
return NULL;
}
if (timeofday_diff == 0) {
/* Run this several times since sometimes the first
* doesn't give the lowest values, and we're really trying
* to determine the lowest.
*/
calibrate();
calibrate();
calibrate();
}
if (write_header(self))
/* some error occurred, exception has been set */
self = NULL;
}
return (PyObject *) self;
}
static char coverage__doc__[] = "\
coverage(logfilename) -> profiler\n\
Returns a profiler that doesn't collect any timing information, which is\n\
useful in building a coverage analysis tool.";
static PyObject *
hotshot_coverage(PyObject *unused, PyObject *args)
{
char *logfilename;
PyObject *result = NULL;
if (PyArg_ParseTuple(args, "s:coverage", &logfilename)) {
result = hotshot_profiler(unused, args);
if (result != NULL) {
ProfilerObject *self = (ProfilerObject *) result;
self->frametimings = 0;
self->linetimings = 0;
self->lineevents = 1;
}
}
return result;
}
static char resolution__doc__[] =
#ifdef MS_WIN32
"resolution() -> (performance-counter-ticks, update-frequency)\n"
"Return the resolution of the timer provided by the QueryPerformanceCounter()\n"
"function. The first value is the smallest observed change, and the second\n"
"is the result of QueryPerformanceFrequency().";
#else
"resolution() -> (gettimeofday-usecs, getrusage-usecs)\n"
"Return the resolution of the timers provided by the gettimeofday() and\n"
"getrusage() system calls, or -1 if the call is not supported.";
#endif
static PyObject *
hotshot_resolution(PyObject *unused, PyObject *args)
{
PyObject *result = NULL;
if (PyArg_ParseTuple(args, ":resolution")) {
if (timeofday_diff == 0) {
calibrate();
calibrate();
calibrate();
}
#ifdef MS_WIN32
result = Py_BuildValue("ii", timeofday_diff, frequency.LowPart);
#else
result = Py_BuildValue("ii", timeofday_diff, rusage_diff);
#endif
}
return result;
}
static PyMethodDef functions[] = {
{"coverage", hotshot_coverage, METH_VARARGS, coverage__doc__},
{"profiler", hotshot_profiler, METH_VARARGS, profiler__doc__},
{"logreader", hotshot_logreader, METH_VARARGS, logreader__doc__},
{"resolution", hotshot_resolution, METH_VARARGS, resolution__doc__},
{NULL, NULL}
};
void
init_hotshot(void)
{
PyObject *module;
LogReaderType.ob_type = &PyType_Type;
ProfilerType.ob_type = &PyType_Type;
module = Py_InitModule("_hotshot", functions);
if (module != NULL) {
char *s = get_version_string();
PyModule_AddStringConstant(module, "__version__", s);
free(s);
Py_INCREF(&LogReaderType);
PyModule_AddObject(module, "LogReaderType",
(PyObject *)&LogReaderType);
Py_INCREF(&ProfilerType);
PyModule_AddObject(module, "ProfilerType",
(PyObject *)&ProfilerType);
if (ProfilerError == NULL)
ProfilerError = PyErr_NewException("hotshot.ProfilerError",
NULL, NULL);
if (ProfilerError != NULL) {
Py_INCREF(ProfilerError);
PyModule_AddObject(module, "ProfilerError", ProfilerError);
}
PyModule_AddIntConstant(module, "WHAT_ENTER", WHAT_ENTER);
PyModule_AddIntConstant(module, "WHAT_EXIT", WHAT_EXIT);
PyModule_AddIntConstant(module, "WHAT_LINENO", WHAT_LINENO);
PyModule_AddIntConstant(module, "WHAT_OTHER", WHAT_OTHER);
PyModule_AddIntConstant(module, "WHAT_ADD_INFO", WHAT_ADD_INFO);
PyModule_AddIntConstant(module, "WHAT_DEFINE_FILE", WHAT_DEFINE_FILE);
PyModule_AddIntConstant(module, "WHAT_DEFINE_FUNC", WHAT_DEFINE_FUNC);
PyModule_AddIntConstant(module, "WHAT_LINE_TIMES", WHAT_LINE_TIMES);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -