字符串性能 - Windows 10 下的 Python 2.7 与 Python 3.4 对比 Ubuntu

2024-03-15

Use case
一个简单的函数,用于检查特定字符串是否在另一个字符串中的位置为 3 的倍数(请参阅此处现实世界的例子 https://en.wikipedia.org/wiki/Stop_codon,在 DNA 序列中寻找终止密码子)。

功能
sliding_window:取长度为 3 的字符串与搜索字符串进行比较,如果相同则向前移动 3 个字符。
incremental_start:尝试查找搜索字符串,如果找到的位置不是3的倍数,则尝试查找找到的位置之后的下一个位置。

请注意:示例数据只是为了确保每个函数都必须遍历完整的字符串,性能与真实数据或随机数据类似。

Results

  • Python 2.7: 最初的sliding_window使用该函数可以将函数提高约 39 倍incremental_startWindows 10 上的 Python2.7 中。Ubuntu 上的性能改进略有下降,约 34 倍、约 37 倍、约 18 倍(VM、AWS、本机),但仍在同一范围内。
  • Python 3.4: sliding_window比 Python2.7 慢(在 Windows 上为 1.8 倍,在所有 Ubuntu 上为 1.4 倍或 1.5 倍),但是incremental_start在所有 Ubuntu 上性能下降了 4、5、1.7 倍(VM、AWS、本机),而在 Windows 上几乎没有变化。
  • Windows 与 Ubuntu
    Python2.7:虚拟化的 Ubuntu 实现这两个功能所需的时间更少(约 20-30%),原生 Ubuntu 的速度慢了大约 25%incremental_start, while sliding_window速度提高了 40%。
    Python3: the sliding_window函数完成所需的时间更少 (~50%),而incremental_start速度变慢约 2-3 倍。

问题

  • 是什么导致 Python 2 与 Python 3 在 Linux 和 Windows 上的性能差异?
  • 如何预测这种行为并调整代码以获得最佳性能?

Code

import timeit

text = 'ATG' * 10**6
word = 'TAG'

def sliding_window(text, word):
    for pos in range(0, len(text), 3):
        if text[pos:pos + 3] == word:
            return False
    return True

def incremental_start(text, word):
    start = 0
    while start != -1:
        start = text.find(word, start + 1)
        if start % 3 == 0:
            return False
    return True

#sliding window
time = timeit.Timer(lambda: sliding_window(text, word), setup='from __main__ import text, word').timeit(number=10)
print('%3.3f' % time)

#incremental start
time = timeit.Timer(lambda: incremental_start(text, word), setup='from __main__ import text, word').timeit(number=500)
print('%3.3f' % time)

Tables

Ubuntu vs Windows    VM     AWS    Native   
Python2.7-Increment  79%    73%    126% 
Python2.7-Sliding    70%    70%    60%                  
Python3.4-Increment  307%   346%   201% 
Python3.4-Sliding    54%    59%    48%  

Py2 vs 3    Windows    VM    AWS    Native
Increment   105%       409%  501%   168%
Sliding     184%       143%  155%   147%

Absolute times in seconds
                 Win10   Ubuntu  AWS     Native
Py2.7-Increment  1.759   1.391   1.279   2.215 
Py2.7-Sliding    1.361   0.955   0.958   0.823 

Py3.4-Increment  1.853   5.692   6.406   3.722 
Py3.4-Sliding    2.507   1.365   1.482   1.214 

Details
Windows 10:本机 Windows、32 位 Python 3.4.3 或 2.7.9、i5-2500、16GB RAM
Ubuntu虚拟机:14.04,运行在Windows主机上,64位Python 3.4.3,Python 2.7.6,4核,4GB RAM
AWS:14.04、AWS 微实例、64 位 Python 3.4.3、Python 2.7.6
原生 Ubuntu:14.04、64 位 Python 3.4.3、Python 2.7.6、i5-2500、16GB 内存 [与 Win10 机器相同]


Update

正如英加兹所建议的xrange and bytes使用Python3.4后,性能略有提高,但在Ubuntu上性能仍然大幅下降。罪魁祸首似乎是find当 Ubuntu 和 Py3.4 组合时,速度要慢得多(与从源代码编译的 Py3.5 相同)。这似乎与 Linux 风格相关,在 Debian 上 Py2.7 和 Py3.4 表现相同,在 RedHat 上 Py2.7 比 Py3.4 快得多。
为了更好的比较,Py3.4现在在Windows10和Ubuntu上的64位中使用。 Win10上仍然使用Py27。

import timeit, sys

if sys.version_info >= (3,0):
    from builtins import range as xrange

def sliding_window(text, word):
    for pos in range(0, len(text), 3):
        if text[pos:pos + 3] == word:
            return False
    return True

def xsliding_window(text, word):
    for pos in xrange(0, len(text), 3):
        if text[pos:pos + 3] == word:
            return False
    return True

def incremental_start(text, word):
    start = 0
    while start != -1:
        start = text.find(word, start + 1)
        if start % 3 == 0:
            return False
    return True

text = 'aaa' * 10**6
word = 'aaA'
byte_text = b'aaa' * 10**6
byte_word = b'aaA'

time = timeit.Timer(lambda: sliding_window(text, word), setup='from __main__ import text, word').timeit(number=10)
print('Sliding, regular:      %3.3f' % time)

time = timeit.Timer(lambda: incremental_start(text, word), setup='from __main__ import text, word').timeit(number=500)
print('Incremental, regular:  %3.3f' % time)

time = timeit.Timer(lambda: sliding_window(byte_text, byte_word), setup='from __main__ import byte_text, byte_word').timeit(number=10)
print('Sliding, byte string:  %3.3f' % time)

time = timeit.Timer(lambda: incremental_start(byte_text, byte_word), setup='from __main__ import byte_text, byte_word').timeit(number=500)
print('Incremental, bytes:    %3.3f' % time)

time = timeit.Timer(lambda: xsliding_window(byte_text, byte_word), setup='from __main__ import byte_text, byte_word').timeit(number=10)
print('Sliding, xrange&bytes: %3.3f' % time)

time = timeit.Timer(lambda: text.find(word), setup='from __main__ import text, word').timeit(number=1000)
print('simple find in string: %3.3f' % time)


Win10-py27  Wi10-py35   VM-py27  VM-py34
1.440       2.674       0.993    1.368 
1.864       1.425       1.436    5.711 
1.439       2.388       1.048    1.219 
1.887       1.405       1.429    5.750 
1.332       2.356       0.772    1.224 
3.756       2.811       2.818    11.361 

尽管您正在测量相同代码的速度,但代码中的结构是不同的。

A. range2.7 中是type 'list',3.4 中的范围是class 'range'

B. 'ATG' * 10**6 在 2.7 中是字节字符串,在 3.4 中是 unicode 字符串

如果满足以下条件,您可以尝试生成更兼容的结果:a) 对 2.7 变体使用 xrange,b) 使用bytes两个示例中的字符串:b'ATG'或两个示例中的 unicode 字符串。

Update

我怀疑性能差异源于主要因素:a) 32 位与 64 位,b) C 编译器。

所以,我做了测试:

  1. ActiveState Python 2.7.10 32位
  2. ActiveState Python 2.7.10 64位
  3. 官方发行版Python 2.7.11 32位
  4. 官方发行版Python 2.7.11 64位
  5. Python 2.7.6 64位上Windows 10 上的 Ubuntu https://blogs.windows.com/buildingapps/2016/03/30/run-bash-on-ubuntu-on-windows/
  6. pypy-5.1.1-win32

我所期望的

我期望:

  • 64位版本会比较慢
  • ActiveState会快一点
  • PyPy 速度更快
  • Windows 10 上的 Ubuntu - ???

Results

Test                    as32b   as64b   off32b   off64b  ubw64b  pypy5.1.1
Sliding, regular:       1.232   1.230   1.281    1.136   0.951   0.099  
Incremental, regular:   1.744   1.690   2.219    1.647   1.472   2.772
Sliding, byte string:   1.223   1.207   1.280    1.127   0.926   0.101
Incremental, bytes:     1.720   1.701   2.206    1.646   1.568   2.774
Sliding, xrange&bytes:  1.117   1.102   1.162    0.962   0.779   0.109
simple find in string:  3.443   3.412   4.607    3.300   2.487   0.289

Windows 10 上的获胜者是……由 GCC 4.8.2 为 Linux 编译的 Ubuntu Python!

这个结果完全出乎我的意料。

32 vs 64:变得无关紧要。

PyPy:一如既往的超快,除非不是这样。

我无法解释这个结果,OP问题变得不像看起来那么简单。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串性能 - Windows 10 下的 Python 2.7 与 Python 3.4 对比 Ubuntu 的相关文章

随机推荐

  • 如何使用Javascript触发CSS“悬停状态”? [复制]

    这个问题在这里已经有答案了 当用户将鼠标悬停在元素上时 CSS 悬停状态 将触发 我们如何使用 Javascript 将元素设置为 悬停状态 是否可以 如果您可以接受使用 focus您可以使用以下命令来代替悬停 var links docu
  • 如何根据条件应用Spring消息转换器?

    我有一个控制器 其响应是驼峰式 json 值 现在我们正在用新版本重写代码 所需的响应位于snake case中 我添加了一个消息转换器并修改了对象映射器来设置setPropertyNamingStrategy PropertyNaming
  • 有没有集成CouchDb和Solr的项目?

    我希望能够使用 Solr 搜索 CouchDB 数据库 有没有提供这样的集成的项目 我还知道 CouchDB Lucene 有没有办法让 Solr 融入其中 Thanks 考虑到它是多么容易 自己推出会更有意义 首先 您需要决定使用哪种 S
  • $.mobile.silentScroll 在 worklight 应用程序中不起作用

    我正在使用 IBM 的 worklight 框架开发一个应用程序 其中我使用 jquery 移动库进行编码 不幸的是 当我使用 mobile silentScroll滚动 它没有效果 它不起作用 有人遇到过这个问题吗 在其他工作中 如何在w
  • PowerShell安装NuGet,显示无法访问互联网,但实际上可以

    我按照中提到的步骤进行操作在代理后面使用 PowerShell http woshub com using powershell behind a proxy 配置我的代理服务器 netsh winhttp set proxy IP Por
  • Pygame 或 Python 中的透明窗口

    我正在尝试为我的游戏制作一个透明窗口作为启动屏幕 图像具有透明度 但我无法使窗口透明 例如在其后面看到屏幕 桌面等 我发现的所有内容都不能使用 pygame 我可以从中提取任何外部库来实现这一点吗 顺便提一句 这完全是一个Linux项目 所
  • Django FileField 在上传后移动文件

    围绕这一主题有几个问题 但我发现没有一个适合我想做的事情 我希望能够将文件上传到模型 并使用 pk 等模型实例属性将该文件保存在一个合适的位置 我知道这些东西会在之后设置model save 所以我需要编写一个自定义保存来执行此操作 但我无
  • 如何配置 docker 文件以像 perl 一样运行 cgi 脚本

    我有这个文件 索引 php Dockerfile conf myawesomesite conf cgi bin helloworld pl 在 conf myawesomesite conf 中
  • PHP 页面加载/刷新到准确位置

    我想做的是通过 href 链接将用户传递到 php 脚本 然后将他们传回与单击链接之前完全相同的位置 就像页面尚未刷新一样 有谁知道这是否或如何可能 谢谢 使用 HTML 您可以得到以下内容 p a href script php Send
  • 如何在 MongoDB 中处理小于 1970 的日期

    我有一个包含 生日 字段的文档 该字段的值也可能低于 01 01 1970 我该如何处理这个问题 例如 birthday gt newMongoDate strtotime 31 10 1968 这将创建一个 生日 值 1 1 1970 1
  • Tomcat 上的 SSL 证书 - 别名无法识别密钥

    想知道是否有人可以告诉我我在哪里搞砸了 我有一个 keytool 创建的密钥库 一个来自 Thawte 的主证书 辅助证书和 ssl 证书 我最初使用 openssl 创建了 CSR 然后使用记录的过程将私钥转换为 PKCS12 以导入到密
  • 将一行复制一定次数,然后每次将 30 分钟添加到时间戳(就像序列一样)

    样本数据 ID Location Type Trip End Number of periods 1298 Residential 02 01 2022 05 30 48 1298 Residential 03 01 2022 05 30
  • 可以在 PHP 中测试变量是否是静态的吗?

    PHP 中是否可以测试变量是否是静态的 我正在尝试创建一个神奇的方法 get它还查看静态变量 我发现property exists 当变量也是静态时返回 true 但我需要使用 代替 gt 我会期待吗 可以通过反射测试变量是否是静态的 cl
  • 构建多部分响应

    考虑到多个 HTTP 请求的响应 我必须从中构建一个多部分响应 我面临的问题是如何在最终的多部分响应中设置单个响应的响应标头 为了 例如 HttpClient client new HttpClient HttpRequestMessage
  • 带标头的 Alamofire POST 请求

    我正在尝试在 Swift 中使用 Alamofire 发出带有标头的发布请求 然而 我不断得到方法调用中的额外参数错误 我正在使用 Alamofire 4 5 版本 我无法找出错误 请查找附件中的代码 let headers Authori
  • 流星中的 Bootstrap 3 模态未显示

    我试图让 bootstrap 3 模态弹出流星应用程序 但没有成功 一切似乎都已就位 我已经在这里和其他地方搜索过 但它根本行不通 HTML 是
  • 如何使用 xml 设置颜色可绘制的圆角半径?

    在android网站上 有一个关于颜色绘图的部分 http developer android com guide topics resources available resources html colordrawableresourc
  • 计算成员中的 WHERE 子句

    我面临一些通过比较维度值来计算值的问题 我有 3 个维度 数据类型 客户 产品 和一个度量 GrossSales 如果我想要 ProductID 1 2 3 且 Dataype 4 5 6 的 GrossSales MDX 查询是什么 这里
  • 在数据库中存储年份[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 年份数据的最佳 PostgreSQL 数据类型是什么 例如 2006 年或 1847 年 TEXT SMALLINT DATE 理想情况下
  • 字符串性能 - Windows 10 下的 Python 2.7 与 Python 3.4 对比 Ubuntu

    Use case一个简单的函数 用于检查特定字符串是否在另一个字符串中的位置为 3 的倍数 请参阅此处现实世界的例子 https en wikipedia org wiki Stop codon 在 DNA 序列中寻找终止密码子 功能 sl