Chinaunix首页 | 论坛 | 博客
  • 博客访问: 178869
  • 博文数量: 13
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 832
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-16 22:43
个人简介

最近关注Python,Linux,LLVM

文章分类

全部博文(13)

文章存档

2014年(13)

分类: Python/Ruby

2014-03-10 13:29:53

浏览Python文档时,突然想测试下Python字符串拼接效率,有以下三种常用的方式:
1. '+'或'+=',运算符拼接。
2. 'str.join',str的join函数拼接。
3. 'io.StringIO',内存字符串IO拼接。

测试环境:Mac OS X 10.9, Python 3.3
测试文件:GNU C Library完整的一个HTML文档,大小4.9MB,行数95605
开始前猜想:#1应该效率最低,#2和#3不相伯仲

完整源码:

点击(此处)折叠或打开(test_main.py)

  1. import argparse
  2. import io
  3. import os
  4. import sys

  5. def run_case1(fp):
  6.     """基准"""
  7.     filesize = 0
  8.     for line in fp:
  9.         filesize += len(line)

  10. def run_case2(fp):
  11.     """字符串相加"""
  12.     src = ''
  13.     for line in fp:
  14.         src += line

  15. def run_case3(fp):
  16.     """字符串join"""
  17.     src = ''.join(line for line in fp)

  18. def run_case4(fp):
  19.     """字符串内存IO"""
  20.     output = io.StringIO()
  21.     for line in fp:
  22.         output.write(line)
  23.     src = output.getvalue()

  24. def collect_rusage(fp, count, proc):
  25.     for i in range(count):
  26.         fp.seek(0)
  27.         if os.fork() == 0:
  28.             proc(fp)
  29.             os._exit(os.EX_OK)
  30.         pid, status, rusage = os.wait3(os.WEXITED)
  31.         yield rusage.ru_utime, rusage.ru_stime, rusage.ru_maxrss

  32. def main():
  33.     parser = argparse.ArgumentParser(description='Python str')
  34.     parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
  35.                         default='-', help='text source [default: sys.stdin]')
  36.     parser.add_argument('-c', '--count', type=int, default=10,
  37.                         help='loop count for each case')
  38.     args = parser.parse_args()

  39.     # main logic begins
  40.     testcases = [run_case1, run_case2, run_case3, run_case4]
  41.     for case in testcases:
  42.         total = list(collect_rusage(args.infile, args.count, case))
  43.         avg_utime = sum(e[0] for e in total)/len(total)
  44.         avg_stime = sum(e[1] for e in total)/len(total)
  45.         avg_maxrss = sum(e[2] for e in total)/len(total)
  46.         print('{} utime: {:.06f}, stime: {:.06f}, maxrss: {}'.format(
  47.                case.__doc__, avg_utime, avg_stime, int(avg_maxrss)))

  48. if __name__ == '__main__':
  49.     main()

脚本执行三次,每次运行中,每个case执行100次并取平均值,输出:
  1. bash-3.2 $python test_main.py The\ GNU\ C\ Library.html --count 100
  2. 基准 utime: 0.019205, stime: 0.001823, maxrss: 1407590
  3. 字符串相加 utime: 0.027731, stime: 0.005384, maxrss: 12171386
  4. 字符串join utime: 0.025856, stime: 0.007648, maxrss: 22402129
  5. 字符串内存IO utime: 0.029018, stime: 0.007745, maxrss: 22345195

  6. bash-3.2 $python test_main.py The\ GNU\ C\ Library.html --count 100
  7. 基准 utime: 0.018908, stime: 0.001806, maxrss: 1397063
  8. 字符串相加 utime: 0.027610, stime: 0.005370, maxrss: 12161966
  9. 字符串join utime: 0.026054, stime: 0.007611, maxrss: 22383452
  10. 字符串内存IO utime: 0.029314, stime: 0.007732, maxrss: 22340034

  11. bash-3.2 $python test_main.py The\ GNU\ C\ Library.html --count 100
  12. 基准 utime: 0.019428, stime: 0.001793, maxrss: 1395957
  13. 字符串相加 utime: 0.027489, stime: 0.005308, maxrss: 12176220
  14. 字符串join utime: 0.025874, stime: 0.007610, maxrss: 22412247
  15. 字符串内存IO utime: 0.028902, stime: 0.007883, maxrss: 22341509

  16. bash-3.2 $wc -l The\ GNU\ C\ Library.html
  17. 95605 The GNU C Library.html
  18. bash-3.2 $ls -l The\ GNU\ C\ Library.html
  19. -rw-r--r--@ 1 Guorui staff 5123001 3 10 10:50 The GNU C Library.html

最终结果颇有回味之处:
1. ‘+’效率低得令人发指,以至于我上面的代码没有包含它,在电脑边等不出结果。。。这与文档的描述一致,平时千万不要用。
2. ‘+=’竟然是效率最高的方式,CPU和RAM的占用最少,颇感意外,没在文档中找到说明,看来得抽空研究下源码。
3. ‘io.StringIO’比‘str.join’稍逊,但不太明显,实践中可以忽略这一点性能差异,按照实际需要选用。

阅读(5330) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~