字节阵列和替代方案的性能



我正在为通过TCP工作的协议编写解析器。

有些消息在多个数据包之间拆分,因此我需要能够"窥视"我的流,并有可能返回并在末尾附加传入数据。另一方面,我希望能够丢弃我成功解析的数据包的内容。

  • bytes的问题在于追加需要复制(不是在CPython中,但也不可能删除不可变对象中的第一个字节)。
  • bytearray的问题在于刷新已经看到的字节也需要复制(或者我认为,见下文)
  • collections.deque的问题在于巨大的内存需求。与list相同。

但是,我用bytearray做了一些测试,似乎pop(0)操作比列表高效得多:

from time import time
n = 100000
for container in [bytearray, list]:
print(container)
a = container(b'a'*n)
t = time()
for i in range(n):
del a[0]
print('del a[0]', time() - t)
a = container(b'a'*n)
t = time()
for i in range(n):
del a[-1]
print('del a[-1]', time() - t)
a = container(b'a'*n)
t = time()
for i in range(n-1):
del a[1]
print('del a[1]', time() - t)
a = container(b'a'*n)
t = time()
for i in range(n-1):
del a[-2]
print('del a[-2]', time() - t)
print()

似乎del a[0]del a[-1]在cpython2,cpython3和pypy3中对bytearray具有大致相同的复杂性。

我想知道:

  1. 这怎么可能?有没有比del a[:k]更有效的方法来删除前k个字节?

  2. 有没有比bytearray更有效的数据结构?(可能使用arraymemoryviewctypes)

Python 故意牺牲代码性能来换取程序员的性能。

使用最方便使用的任何内容。

当您有一个正常工作的实现并且性能被证明不足时,仅将关键位(如分析所示)替换为更快的等效位。有关详细信息,请参阅 https://wiki.python.org/moin/PythonSpeed/PerformanceTips#Overview:_Optimize_what_needs_optimizing。


也就是说,您描述的用例的主要候选者是"分块缓冲区",它将从一系列缓冲区透明地返回切片。

从中提取数据仍然需要复制(因为所有标准 Python 类型都拥有自己的内存),如果您在纯 Python 中实现该类型,您将有解释器开销。因此,要获得任何重大改进,您可能必须进入Cython/C或其他东西。这就是为什么首先获得正确的通用设计如此重要的原因 - 在纯Python中,改变事物要容易得多。

最新更新