日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

cpython效率_PyPy 和 CPython 的性能比较测试

發布時間:2024/3/24 python 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cpython效率_PyPy 和 CPython 的性能比较测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近我在維基百科上完成了一些數據挖掘方面的任務。它由這些部分組成:

解析enwiki-pages-articles.xml的維基百科轉儲;

把類別和頁存儲到MongoDB里面;

對類別名稱進行重新分門別類。

我對CPython 2.7.3和PyPy 2b的實際任務性能進行了測試。我使用的庫是:

redis 2.7.2

pymongo 2.4.2

此外CPython是由以下庫支持的:

hiredis

pymongo c-extensions

測試主要包含數據庫解析,所以我沒預料到會從PyPy得到多大好處(何況CPython的數據庫驅動是C寫的)。

下面我會描述一些有趣的結果。

抽取維基頁名

我需要在所有維基百科的類別中建立維基頁名到page.id的聯接并存儲重新分配好的它們。最簡單的解決方案應該是導入enwiki-page.sql(定義了一個RDB表)到MySQL里面,然后傳輸數據、進行重分配。但我不想增加MySQL需求(有骨氣!XD)所以我用純Python寫了一個簡單的SQL插入語句解析器,然后直接從enwiki-page.sql導入數據,進行重分配。

這個任務對CPU依賴更大,所以我再次看好PyPy。

/ time

PyPy 169.00s 用戶態 8.52s 系統態 90% CPU

CPython 1287.13s 用戶態 8.10s 系統態 96% CPU

我也給page.id->類別做了類似的聯接(我筆記本的內存太小了,不能保存供我測試的信息了)。

從enwiki.xml中篩選類別

為了方便工作,我需要從enwiki-pages-articles.xml中過濾類別,并將它們存儲相同的XML格式的類別。因此我選用了SAX解析器,在PyPy和CPython中都適用的包裝器解析。對外的原生編譯包(同事在PyPy和CPython 中) 。

代碼非常簡單:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96class WikiCategoryHandler(handler.ContentHandler):

"""Class which detecs category pages and stores them separately

"""

ignored= set(('contributor','comment','meta'))

def __init__(self, f_out):

handler.ContentHandler.__init__(self)

self.f_out= f_out

self.curr_page= None

self.curr_tag= ''

self.curr_elem= Element('root', {})

self.root= self.curr_elem

self.stack= Stack()

self.stack.push(self.curr_elem)

self.skip= 0

def startElement(self, name, attrs):

if self.skip>0 or namein self.ignored:

self.skip+= 1

return

self.curr_tag= name

elem= Element(name, attrs)

if name== 'page':

elem.ns= -1

self.curr_page= elem

else:# we don't want to keep old pages in memory

self.curr_elem.append(elem)

self.stack.push(elem)

self.curr_elem= elem

def endElement(self, name):

if self.skip>0:

self.skip-= 1

return

if name== 'page':

self.task()

self.curr_page= None

self.stack.pop()

self.curr_elem= self.stack.top()

self.curr_tag= self.curr_elem.tag

def characters(self, content):

if content.isspace():return

if self.skip== 0:

self.curr_elem.append(TextElement(content))

if self.curr_tag== 'ns':

self.curr_page.ns= int(content)

def startDocument(self):

self.f_out.write("\n")

def endDocument(self):

self.f_out.write("\n")

print("FINISH PROCESSING WIKIPEDIA")

def task(self):

if self.curr_page.ns== 14:

self.f_out.write(self.curr_page.render())

class Element(object):

def __init__(self, tag, attrs):

self.tag= tag

self.attrs= attrs

self.childrens= []

self.append= self.childrens.append

def __repr__(self):

return "Element {}".format(self.tag)

def render(self, margin=0):

if not self.childrens:

return u"{0}".format(

" "*margin,

self.tag,

"".join([' {}="{}"'.format(k,v)for k,vin {}.iteritems()]))

if isinstance(self.childrens[0], TextElement)and len(self.childrens)==1:

return u"{0}{3}{1}>".format(

" "*margin,

self.tag,

"".join([u' {}="{}"'.format(k,v)for k,vin {}.iteritems()]),

self.childrens[0].render())

return u"{0}\n{3}\n{0}{1}>".format(

" "*margin,

self.tag,

"".join([u' {}="{}"'.format(k,v)for k,vin {}.iteritems()]),

"\n".join((c.render(margin+2)for cin self.childrens)))

class TextElement(object):

def __init__(self, content):

self.content= content

def __repr__(self):

return "TextElement" def render(self, margin=0):

return self.content

Element和TextElement元素包換tag和body信息,同時提供了一個方法來渲染它。

下面是我想要的PyPy和CPython比較結果。

/ time

PyPy 2169.90s

CPython 4494.69s

我很對PyPy的結果很吃驚。

計算有趣的類別集合

我曾經想要計算一個有趣的類別集合——在我的一個應用背景下,以Computing類別衍生的一些類別為開始進行計算。為此我需要構建一個提供類的類圖——子類關系圖。

結構類——子類關系圖

這個任務使用MongoDB作為數據來源,并對結構進行重新分配。算法是:1

2

3

4

5for each category.id in redis_categories (it holds*category.id -> category title mapping*) do:

title= redis_categories.get(category.id)

parent_categories= mongodb get categoriesfor title

for each parent_catin parent categories do:

redis_tree.sadd(parent_cat, title)# add to parent_cat set title

抱歉寫這樣的偽碼,但我想這樣看起來更加緊湊些。

所以說這個任務僅把數據從一個數據庫拷貝到另一個。這里的結果是MongoDB預熱完畢后得出的(不預熱的話數據會有偏差——這個Python任務只耗費約10%的CPU)。計時如下:

/ time

PyPy 175.11s 用戶態 66.11s 系統態 64% CPU

CPython 457.92s 用戶態 72.86s 系統態 81% CPU

遍歷redis_tree(再分配過的樹)

如果我們有redis_tree數據庫,僅剩的問題就是遍歷Computing類別下所有可實現的結點了。為避免循環遍歷,我們需要記錄已訪問過的結點。自從我想測試Python的數據庫性能,我就用再分配集合列來解決這個問題。

/ time

PyPy 14.79s 用戶態 6.22s 系統態 69% CPU 30.322 總計

CPython 44.20s 用戶態 13.86s 系統態 71% CPU 1:20.91 總計

說實話,這個任務也需要構建一些tabu list(禁止列表)——來避免進入不需要的類別。但那不是本文的重點。

結論

進行的測試僅僅是我最終工作的一個簡介。它需要一個知識體系,一個我從抽取維基百科中適當的內容中得到的知識體系。

PyPy相比CPython,在我這個簡單的數據庫操作中,提高了2-3倍的性能。(我這里沒有算上SQL解析器,大約8倍)

多虧了PyPy,我的工作更加愉悅了——我沒有改寫算法就使Python有了效率,而且PyPy沒有像CPython一樣把我的CPU弄掛了,以至于一段時間內我沒法正常的使用我的筆記本了(看看CPU時間占的百分比吧)。

任務幾乎都是數據庫操作,而CPython有一些加速的亂七八糟的C語言模塊。PyPy不使用這些,但結果卻更快!

我的全部工作需要大量的周期,所以我真高興能用PyPy。

總結

以上是生活随笔為你收集整理的cpython效率_PyPy 和 CPython 的性能比较测试的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。