谁说Python性能差的?-- 让python比awk快 (3)

在(2)中,提到了python字符串慢在了split函数。那既然已经知道这个bottleneck,现在就优化下。

初步思路是用C来定制一个提取第n列数的模块,然后替换我们的Python版本(1)中的split函数。

下面是一个简单代码(示例下而已,不够好,:-)),用cython。

目录下有两个文件,一个是tst.pyx, 一个是setup.py(cython要求的)。

tst.pyx代码:

from libc.stdlib cimport atol



cdef long field2number(char *arr, int index):

        cdef int cnt

        cdef int i

        cdef int start

        cdef int end



        cnt = 0

        i = 0



        while True:

                if arr[i] == ' ':

                        cnt += 1

                        if cnt == index - 1:

                                start = i

                                break

                i += 1



        i = i + 1

        while arr[i] != '\n' and arr[i] != ' ':

                i += 1

        end = i



        arr[end] = '\0'

        return atol(arr+start)



def getnumber(line,index):

        cdef char *p

        cdef int i

        p = line

        i = index

        return field2number(p,i)

setup.py代码:

from distutils.core import setup

from distutils.extension import Extension

from Cython.Distutils import build_ext



ext_modules=[

    Extension("tst",

              ["tst.pyx"],

              libraries=["m"]) # Unix-like specific

]



setup(

  name = "tst",

  cmdclass = {"build_ext": build_ext},

  ext_modules = ext_modules

)

编译模块:

$ python setup.py build_ext -i

running build_ext

skipping 'tst.c' Cython extension (up-to-date)

building 'tst' extension

gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c tst.c -o build/temp.linux-x86_64-2.7/tst.o

gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro build/temp.linux-x86_64-2.7/tst.o -lm -o /home/dog/dev/test/tst.so

修改的Python版本(1):

import sys

from tst import getnumber



def data_sum():

        datasum = 0

        for line in sys.stdin:

                datasum += getnumber(line, 3)

        print datasum



if __name__ == "__main__":

        data_sum()

看看效果,数据还是(2)中的比较复杂一点的样本。

优化后的python:

$ time cat datas.txt |python datasumo.py
49976509700800

real 0m2.486s
user 0m2.400s
sys 0m0.196s

awk呢?

$ time cat datas.txt | awk '{ SUM += $3} END { print SUM }'
49976509700800

real 0m3.595s
user 0m3.496s
sys 0m0.276s

Python比awk还快,有木有?

当然上面的优化,在现实情况意义可能不是很大,毕竟有很多其他方面(维护,兼容等)的考虑。 

其实,做系统,关键要学会tradeoff,就是平衡各项要求和指标。交付周期,性能,bug数目不可能样样好。

所以,我一向喜欢开发速度快的工具,做到整个系统的快速迭代,不断演进。另外,我认为学习要深入,不要居于表面的各种

技巧。把原理搞通,算法扎实,整个计算机运行过程有个big picture。当实际用到某项技术时候,在更加广泛的研究他的方方面面,

这是我的经验,不敢别人也赞同:-)。

 

你可能感兴趣的:(python)