分析回调到 Python 的 C 扩展

Posted

技术标签:

【中文标题】分析回调到 Python 的 C 扩展【英文标题】:Profiling C extension which calls back into Python 【发布时间】:2018-05-28 09:11:44 【问题描述】:

假设出于讨论的目的,我有一个这样的函数:

PyObject* tuple_from_dict(PyObject* ftype, PyObject* factory, PyObject* values) 
    PyObject* ttype = PyTuple_GetItem(factory, 1);
    PyObject* fmapping = PyTuple_GetItem(factory, 2);
    PyObject* key;
    PyObject* value;
    Py_ssize_t pos = 0;
    Py_ssize_t arg_len = 0;
    Py_ssize_t field;
    PyObject* result;

    if (PyDict_Size(fmapping) == 0) 
        result = PyObject_Call(ttype, PyTuple_New(0), NULL);
        Py_INCREF(result);
        return result;
    

    while (PyDict_Next(fmapping, &pos, &key, &value)) 
        field = PyLong_AsSsize_t(value);
        if (field > arg_len) 
            arg_len = field;
        
    
    PyObject* args = PyTuple_New(arg_len + 1);

    pos = 0;
    while (pos < arg_len + 1) 
        Py_INCREF(Py_None);
        PyTuple_SetItem(args, pos, Py_None);
        pos++;
    

    pos = 0;
    while (PyDict_Next(values, &pos, &key, &value)) 
        field = PyLong_AsSsize_t(PyDict_GetItem(fmapping, key));
        PyTuple_SetItem(args, field, value);
    
    result = PyObject_Call(ttype, args, NULL);
    if (result) 
        Py_INCREF(result);
    
    return result;

它到底做了什么并不重要,重要的是它调用PyObject_Call(...),我怀疑它很慢。但是,我们正在谈论的缓慢在每次调用的基础上并不明显(代码整体确实每 1/100 秒有数千次调用)。所以...我需要一个聚合,或者某种以非常高的精度测量时间的方法(所以,clock_t 似乎不是一个很好的精度水平)。

如果该解决方案仅适用于 Linux,那也没关系。如果我能以某种方式减慢一切速度,但对所讨论的时间进行更精确的测量,那也没关系。

【问题讨论】:

【参考方案1】:

clock_gettime() 有用吗?它是高分辨率计时器的 POSIX 接口。 This post 提供此示例用法。

#include <iostream>
#include <time.h>
using namespace std;

timespec diff(timespec start, timespec end);

int main()

    timespec time1, time2;
    int temp;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
    for (int i = 0; i< 242000000; i++)
        temp+=temp;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
    cout<<diff(time1,time2).tv_sec<<":"<<diff(time1,time2).tv_nsec<<endl;
    return 0;


timespec diff(timespec start, timespec end)

    timespec temp;
    if ((end.tv_nsec-start.tv_nsec)<0) 
        temp.tv_sec = end.tv_sec-start.tv_sec-1;
        temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
     else 
        temp.tv_sec = end.tv_sec-start.tv_sec;
        temp.tv_nsec = end.tv_nsec-start.tv_nsec;
    
    return temp;

【讨论】:

好像是这样。这需要一些时间来实现,我会看看它是如何进行的。谢谢!

以上是关于分析回调到 Python 的 C 扩展的主要内容,如果未能解决你的问题,请参考以下文章

调试/分析python扩展[关闭]

JUC线程池扩展可回调的Future

libevent源码分析-介绍安装使用

010-Spring Boot 扩展分析

Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

java是做数据分析最好的方法吗