最近我在维基百科上完成了一些数据挖掘方面的任务。它由这些部分组成:

解析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 的性能比较测试相关推荐

  1. cpython pypy_PyPy4.0比Cpython更快的Python编译器

    对Python语言还不甚了解的朋友们一定会问,CPython和PyPy是什么?和Python有着什么样的关系?在介绍PyPy4.0之前,先给大家简单的普及下CPython和PyPy. CPython和 ...

  2. e5 2630v4 php性能,至强E5 V4性能表现测试

    至强E5 V4性能表现测试 在测试方面,CPU性能上采用CineBench 15.SiSoftware Sandra测试软件. CineBench 15测试 CineBench 15新版本最为显着的改 ...

  3. web测试软件act,使用ACT对Web程序进行性能容量测试.doc

    使用ACT对Web程序进行性能容量测试 使用ACT对Web程序进行性能容量测试 测试中心 刘艳会 通过对WAS使用文档的阅读,我们已经知道了压力测试的必要性,并且我们也已经可以使用WAS来对Web应用 ...

  4. 至强服务器性能视频,至强E5 V4性能表现测试

    至强E5 V4性能表现测试 在测试方面,CPU性能上采用CineBench 15.SiSoftware Sandra测试软件. CineBench 15新版本最为显着的改变就是其仅支持64位操作系统, ...

  5. 【40-系统性能压力测试基本概念-相关性能指标HPSTPSQPSRT-安装Jmeter教程-JMeter测试流程-线程组-取样器-监视器-测试商城首页-JMeter Address 占用的问题】

    一.知识回顾 [0.三高商城系统的专题专栏都帮你整理好了,请点击这里!] [1-系统架构演进过程] [2-微服务系统架构需求] [3-高性能.高并发.高可用的三高商城系统项目介绍] [4-Linux云 ...

  6. 至强服务器性能视频,至强E5 V3性能表现测试_戴尔服务器_服务器评测与技术-中关村在线...

    至强E5 V3性能表现测试 在测试方面,CPU性能上采用CineBench R15.SiSoftware Sandra测试软件.其中CineBench R15新版本最为显着的改变就是其仅支持64位操作 ...

  7. APP客户端性能专项测试手册

    APP客户端性能专项测试手册 一.前言 1.1文档目的 通过对本文档的学习,对APP客户端性能专项测试的理论知识,测试工具,测试方法,缺陷分析思路等能有一定程度的了解,并能快速投入到专项测试工作中去. ...

  8. MySQL中MyISAM引擎与InnoDB引擎性能简单测试[转]

    MySQL中MyISAM引擎与InnoDB引擎性能简单测试 [硬件配置] CPU : AMD2500+ (1.8G) 内存: 1G/现代 硬盘: 80G/IDE [软件配置] OS : Windows ...

  9. Mycat+Mysql分布式架构改造和性能压力测试

    架构实现 Mycat作为数据库高可用中间件具备很多的功能,如负载均衡,分库分表,读写分离,故障迁移等.结合项目的实际情况,分库分表功能对于关联查询有很高的要求,需要从业务角度考虑分库分表后的关联查询S ...

最新文章

  1. 关于react diff 算法(译文)
  2. js使用ajax发送post json,javascript-如何用ajaxpost复杂json数据
  3. 径向基函数插值(4)三维数据的插值
  4. 如何在SAP Spartacus的scss里引入全局变量
  5. NTFS MFT元文件碎片分析
  6. 图片变色_一张图看懂手机CMF史,附带手机渐变色工艺解析
  7. java8 新特性实践
  8. 感性电路电流计算_电流、电压、电阻的关系和单位换算表
  9. Servlet 实现上传附件(支持多附件)
  10. 49个excel常用技巧(三)
  11. CentOS7常用工具包安装
  12. Mac finder 文件剪切方法 怎么剪切/移动 剪切快捷键
  13. 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛题解
  14. Python绘制美国队长盾牌
  15. 安卓之父带来一款超长“带鱼”手机
  16. 2018远景能源笔试
  17. android handler的机制和原理_Android完整知识体系路线(菜鸟-资深-大牛必进之路)
  18. jmeter性能测试1-录制脚本
  19. 【AAAI 2021】全部接受论文列表(五)
  20. 计算机照片打印设置方法,详解设置打印机纸张添加7寸照片尺寸在win7电脑中的操作的步骤...

热门文章

  1. 上海交大证实“汉芯”造假
  2. word公式怎么居中
  3. QT制作一个图片播放器
  4. MacBook安装Git三种方式
  5. Everything@阿里云:只有大象才能奔跑!
  6. AMQ7064: Log path not valid or inaccessible.
  7. uni-app学习二
  8. 老戚的黑科技之gdb与gdbServer的使用
  9. android_真机调试_安装包解析失败
  10. VirtualBox安装Mac系统