bytearray 和替代品的性能

Lab*_*abo 8 python arrays data-structures

我正在为通过 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()
Run Code Online (Sandbox Code Playgroud)

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

我想知道:

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

  2. 有没有比 更高效的数据结构bytearray?(也许使用array,memoryviewctypes

iva*_*eev 7

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

使用最方便使用的任何东西。

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


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

从中提取数据仍然需要复制(因为所有标准 Python 类型都拥有自己的内存),并且如果您在纯 Python 中实现该类型,则会产生解释器开销。因此,要获得任何显着的改进,您可能必须使用 Cython/C 或其他东西。这就是为什么首先正确地进行总体设计是如此重要——在纯 Python 中,更改事物要容易得多。

  • @Labo `bytearray` 是用 C 实现的,就是这样。它是 `char[]` 的一个薄包装。即使涉及复制,“memcpy”处理 100kB 数组的块也很快。 (3认同)