在Python 3中,
然而,在Python 2中似乎并非如此:
我可以将字符串转换为
通过实证比较发现,在 Python 2 中使用
如果将
有没有一种方法可以在Python 2中避免这个问题,同时仍然拥有
re
模块可以与memoryview
一起使用:~$ python3
Python 3.2.3 (default, Feb 20 2013, 14:44:27)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = b"abc"
>>> import re
>>> re.search(b"b", memoryview(x))
<_sre.SRE_Match object at 0x7f14b5fb8988>
然而,在Python 2中似乎并非如此:
~$ python
Python 2.7.3 (default, Mar 13 2014, 11:03:55)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = "abc"
>>> import re
>>> re.search(b"b", memoryview(x))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/re.py", line 142, in search
return _compile(pattern, flags).search(string)
TypeError: expected string or buffer
我可以将字符串转换为
buffer
,但是查看缓冲区文档,它没有详细说明 buffer
如何与 memoryview
相比工作。通过实证比较发现,在 Python 2 中使用
buffer
对象并不能像在 Python 3 中使用 memoryview
那样提供性能优势。playground$ cat speed-test.py
import timeit
import sys
print(timeit.timeit("regex.search(mv[10:])", setup='''
import re
regex = re.compile(b"ABC")
PYTHON_3 = sys.version_info >= (3, )
if PYTHON_3:
mv = memoryview(b"Can you count to three or sing 'ABC?'" * 1024)
else:
mv = buffer(b"Can you count to three or sing 'ABC?'" * 1024)
'''))
playground$ python2.7 speed-test.py
2.33041596413
playground$ python2.7 speed-test.py
2.3322429657
playground$ python3.2 speed-test.py
0.381270170211792
playground$ python3.2 speed-test.py
0.3775448799133301
playground$
如果将
regex.search
参数从mv[10:]
更改为mv
,Python 2的性能与Python 3的性能大致相同,但在我编写的代码中,存在大量重复的字符串切片。有没有一种方法可以在Python 2中避免这个问题,同时仍然拥有
memoryview
的零拷贝性能优势?
Memoryview
在Python 2中支持缓冲协议。我认为最根本的区别在于re
如何获取 Python 2 和 Python 3 之间的缓存指针。这个更改有一个专门的 PEP -- 可以看一下 PEP 3118。 - Seyeong Jeongre.search
中使用memoryview
呢?我不认为你会从中获得任何性能上的好处。~ » python3 -m timeit 'import re; x = b"abc"; re.search(b"b", memoryview(x))' 100000 次循环,3 次取最佳结果:每个循环耗时 2.25 微秒
~ » python3 -m timeit 'import re; x = b"abc"; re.search(b"b", x)' 1000000 次循环,3 次取最佳结果:每个循环耗时 1.79 微秒
- Seyeong Jeonga_string[offset:]
,Python每次都会创建一个新的字符串,但是使用a_memoryview[offset:]
,Python会重复使用现有的缓冲区,尽管最终用户请求了一个切片。 - Eric Pruitt