gpt4 book ai didi

Python和压缩算法性能

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:53:03 26 4
gpt4 key购买 nike

我对这种压缩算法很感兴趣(查看链接)

https://github.com/bright-tools/varints

特别的问题是 Python 中 bytearray 对象的内存开销对压缩毫无用处。有没有只考虑编码大小而不考虑数据结构大小的解决方案?例如:

>>> import sys
>>> list = []
>>> sys.getsizeof(list)
64

但我会得到类似“0”而不是 64 的东西

如何避免内存开销?请来一些?

最佳答案

如果您尝试创建微型数据结构,Python 不是您想要使用的语言。作为您链接注释的项目的自述文件,如果您可以将大量数据打包到单个字节数组中,则可以使用字节数组(而不是列表)来减少存储开销。但即使是字节数组(如字符串)也是有代价的:64 位 CPython 安装——也就是说,你将获得 x86 Linux 安装的标准 python——每个字节数组至少使用 33 字节的开销。 (我说“至少”是因为 Python 无法测量内存分配开销。)如果需要的话,还有将字节流反序列化为原始对象的计算成本。

由于链接页面生成较小的对象,我断定它的测试一定是在 32 位 Python 安装上完成的,可能是在 Windows 上。因此,这是您可以减少存储使用量的一种方式。

如果你有Python3.3或更高版本(如果没有,就安装它:-)),那么你可以使用array模块,这可能比一个字节更方便数组,部分原因是您可以创建一个数组,其元素是您需要的大小。参见 the Python manual了解详情。如果您使用 bB 类型修饰符构建一个 array.array,它将为每个值仅使用一个字节。如果使用 hH,则可以存储 16 位整数(有符号或无符号),每个整数为两个字节。 array.array 的开销是 64 字节,就像列表一样,但实际元素要紧凑得多。

就个人而言,我不会为这样的东西烦恼,但我想它有它的用途。事实上,引用 README 页面低估了 Python 整数列表的存储消耗,因为它没有考虑整数本身的大小,这是相当大的。

sys.getsizeof 显示的列表大小只是列表本身的大小。它不包括列表中的对象,仅包括对对象的引用(标准 Linux Python 安装中每个对象八个字节)。它还包括列表的对象描述所使用的内存,在相同的标准 Python 安装中为 64 字节。 (这是您的测试中显示的 64 个字节。)

最后,它可能在末尾包含一些额外的空间,以便允许将项目附加到列表而无需重新分配和复制列表。此类额外对象的数量取决于很多因素,包括构建列表的精确方式,但似乎可以通过使用切片复制列表来将此特定开销减少到零:a[:].

在 Python 中,整数是成熟的对象,它们占用的空间量惊人。或者,当您认为 Python 整数是大数字时,这并不奇怪,因此它们没有人为的大小限制。根据getsizeof,绝对值小于230的整数占用28个字节,每增加30位(或部分)占用另外4个字节。 (实际上,您可以将一个由小整数组成的大向量位打包成一个大数,利用左移和右移操作相当快的事实,从而从每个列表中减少几个字节。但是array.array 几乎肯定更容易。)


getsizeof的一些实验,供引用:

>>> from sys import getsizeof
>>> # Strings occupy 48 bytes plus the length of the string plus one byte (presumably for a NUL)
>>> getsizeof("") # 48 + 0 + 1
49
>>> getsizeof("a") # 48 + 1 + 1
50
>>> getsizeof("abcdefghijklmnopqrstuvwxyz") # 48 + 26 + 1
75
>>> getsizeof("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") # 48 + 52 + 1
101
>>> But that's not counted in the size of a list. All the lists are the same size:
>>> getsizeof([""])
72
>>> getsizeof(["a"])
72
>>> getsizeof(["abcdefghijklmnopqrstuvwxyz"])
72
>>> getsizeof(["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"])
72
>>> # Same for a list containing a single number
>>> getsizeof([0])
72
>>> # Lists need 64 bytes plus 8 bytes per element (a pointer to the element):
>>> getsizeof([0,1])
80
>>> getsizeof([0,1,2])
88
>>> getsizeof([0,1,2,3])
96
>>> # When you append to a list, Python leaves some extra space for the next appends
>>> a = [0,1,2,3]
>>> getsizeof(a)
96
>>> # As above, 64 + 4 * 8 bytes. But when we add a single element,
>>> # we get enough room for four elements, so the next three appends
>>> # don't require more space:
>>> a.append(4)
>>> getsizeof(a)
128
>>> a.append(5)
>>> getsizeof(a)
128
>>> a.append(6)
>>> getsizeof(a)
128
>>> a.append(7)
>>> getsizeof(a)
128
>>> # When we append the 9th element, we get room for another four
>>> a.append(8)
>>> getsizeof(a)
192

您可以通过使用元组而不是列表来节省几个字节:元组与字节数组一样是不可变的,但如果您可以忍受无法修改对象,则可以通过使用元组来节省 16 个字节列表的:

>>> getsizeof( (1,2,3) )
72
>>> getsizeof( [1,2,3] )
88

关于Python和压缩算法性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53872699/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com