我正在为通过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
具有大致相同的复杂性。
我想知道:
这怎么可能?有没有比
del a[:k]
更有效的方法来删除前k
个字节?有没有比
bytearray
更有效的数据结构?(可能使用array
,memoryview
或ctypes
)
Python 故意牺牲代码性能来换取程序员的性能。
使用最方便使用的任何内容。
当您有一个正常工作的实现并且性能被证明不足时,仅将关键位(如分析所示)替换为更快的等效位。有关详细信息,请参阅 https://wiki.python.org/moin/PythonSpeed/PerformanceTips#Overview:_Optimize_what_needs_optimizing。
也就是说,您描述的用例的主要候选者是"分块缓冲区",它将从一系列缓冲区透明地返回切片。
从中提取数据仍然需要复制(因为所有标准 Python 类型都拥有自己的内存),如果您在纯 Python 中实现该类型,您将有解释器开销。因此,要获得任何重大改进,您可能必须进入Cython/C或其他东西。这就是为什么首先获得正确的通用设计如此重要的原因 - 在纯Python中,改变事物要容易得多。