Ctypes实现“C重构”

现阶段很多网站都是基于非编译的语言,例如Php,Python语言完成。这样做的效果是开发效率很高,同时开发人员也很容易就位。当网站访问量达到一个数量级之后,就会遇到传说中的C10K问题,借助解释型语言的性能劣势,整个网站会到达一种“无处修改,无处优化,无处升级”的怪圈。这时候往往就会需要采用更加底层的C去重构部分或整个项目,“C重构”由此而来。当然,技术的进化也很迅速,FaceBook开源了hiphop这个PHP2C的工具,可以部分自动化的实现“C重构”。

一直把Python当成胶水语言来用,这次就接着这个话题,说个Python C重构的例子:

首先是python原码:(很眼熟吗?)

#!/usr/bin/env python

import time

lGoal = {}

def main(i):
#    if lGoal.has_key(i):
#        return lGoal[i]

    if i < 1:
        return long (0)
    elif i < 2:
        return long(1)
    return main(i-1) + main(i-2) - main(i-5)

def getList(iMax):
    for i in range(1, iMax+1):
        iGoal = main(i)
        lGoal[i] = iGoal

    return lGoal

#i = int(raw_input())
i = 30
timeStart = time.time()
getList(i)

print "Cost: %s" % (time.time() - timeStart)

看看它的耗时:
Cost: 21.9739699364

首先对于这种多重循环和调用,绝对是C的强项,理论上Python 2 C 之后会有很大的提升空间。重构的思路是用Python的ctypes模块调用基于C的lib库,这样可以在保留大部分Python代码的基础上完成重构,而且重构之后的程序仍然还是Python的。
开始C重构vi LoadTest.c:

#include <stdio.h>
/*
int main()
{
    int i, goal;
    for (i=1; i <= 30; i++)
    {
        goal = C_Time_Cost(i);
        printf ("%d, %d \n", i, goal);

    }

   return 0;
}
*/
int C_Time_Cost(int a)
{
    if (a < 1)
    {
        return 0;
    }
    if (a < 2 )
    {
        return 1;
    }

    return C_Time_Cost( a - 1 ) + C_Time_Cost( a - 2 ) - C_Time_Cost( a - 5 ) ;
}

编译到.o文件:
gcc -c LoadTest.c -fPIC

编译成为Lib
gcc –shared -o libLoadTest.so LoadTest.o
cp libLoadTest.so /lib64 && ldconfig //这一点很重要,否则会报找不到lib文件。

修改python:

#!/usr/bin/env python

import time
from ctypes import *
lGoal = {}

def main(i):
    cdll.LoadLibrary("libLoadTest.so")
    libc = CDLL("libLoadTest.so")
    goal = libc.C_Time_Cost(c_int(i))
    return goal

def getList(iMax):
    for i in range(1, iMax+1):
        iGoal = main(i)
        lGoal[i] = iGoal

    return lGoal

#i = int(raw_input())
i = 30
timeStart = time.time()
getList(i)

print "Cost: %s" % (time.time() - timeStart)

执行时间:
Cost: 0.280420064926

对比之前的21.9739699364 性能提升78倍!不过需要注意,ctypes模块的加载本身很耗资源,使用不当会起到反效果,例如将i=30改为i=10的情况下,python: 0.000591039657593,而Ctypes则需要0.00165605545044,反而落后3倍的时间。

推荐阅读:
深入读了读python的官方文
正值毕业季,这些天一直忙于面试
尽管现在有了wheel这类更为

“Ctypes实现“C重构””的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

请补全下列算式: *

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据