誰說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。當實際用到某項技術時候,在更加廣泛的研究他的方方面面,

這是我的經驗,不敢別人也贊同:-)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM