内存压缩seldomd

2024-04-27 04:34:56 发布

您现在位置:Python中文网/ 问答频道 /正文


背景

我正在开发一个项目(版本2.7),它在很长的时间内(即几天到几周)生成大量数据。一周内生成的数据量大致可以是50MB2GB的数据量。运行这个项目的嵌入式系统有相当数量的RAM(即64GB),但没有持久性存储(数据在网络上以随机间隔卸载),我希望将这个项目使用的内存量保持在最小,同时尽可能长地保留内存中的数据。你知道吗


问题

这个程序保存了大量的内存字符串数据列表,我需要降低内存使用率。这些数据不是经常准备好的(即每天一次),而是经常更新的(即以随机间隔添加1MB的数据)。我正在考虑将其压缩到内存中,因为它只是一堆人类可读的ASCII格式文本字符串,并且可以在删除“最早”的条目之前保留较长时间的数据。你知道吗


问题

有没有一种方法,使用标准/内置的Python功能(即不允许第三方模块)来:

  • 创建一个内存中的压缩列表(以减少大量字符串列表的内存大小)。你知道吗
  • 允许按需从列表中提取单个列表条目。你知道吗
  • 允许删除单个条目(即,如果压缩内存列表过大,则删除“最旧”条目)。你知道吗

工作至今


Tags: ofto数据项目方法内存字符串版本
1条回答
网友
1楼 · 发布于 2024-04-27 04:34:56

假设你有一个庞大的小字符串列表,没有什么是现成的,但它不是太难建立一些东西,将做你想要的。你知道吗

zlib不适合压缩单个短字符串。但是如果你把所有东西压缩到一个巨大的zlib流中,你就不会得到随机访问。你知道吗

那么,如果不被zlib河掩盖,你能做什么?你知道吗

把你的字符串分成中等大小的块,大到可以压缩,小到可以动态解压。每个块的字符串数是一个可调参数,您需要使用不同的值对其进行基准测试。你知道吗

想法是这样的(未经测试,接近伪代码):

class CompressedStringList(collections.abc.Sequence):
    def __init__(self, iterable, chunksize):
        self.chunksize = chunksize
        self.length = 0
        self.chunks = []
        for group in grouper(iterable, chunksize):
            chunk = '\0'.join(group)
            self.chunks.append(zlib.compress(chunk))
            self.length += len(group)
    def __len__(self):
        return self.length
    def __getitem__(self, index):
        # add handling for negative indices and slices
        chunk, offset = index % self.chunksize
        group = zlib.decompress(self.chunks[chunk])
        return group.split('\0')[offset]

根据您希望如何使用它,您可能希望在zlib.decompress位周围包装一个小的LRU缓存(甚至maxsize为1或2)。这样,如果您尝试迭代列表或对其进行切片,您将反复使用相同的解压缩块,而不是反复解压缩。但是,如果你真的只是随机访问,缓存将是一个小开销没有任何好处。你知道吗

要删除值,将其扩展到MutableSequence并不是一件简单的事情,因为您不想重新压缩和解压缩所有内容。你知道吗

但是如果你只是从左边删除(正如你提到的抛出最旧的值所暗示的那样),你需要做的是存储一个偏移量,一个删除项目的计数(mod the chunksize)。当您删除最左边的元素时,只需增加偏移量,而不是实际删除;如果偏移量达到chunksize,则del self.chunks[0]。然后,在getattr中,if not chunk: offset += self.offset。您还可以考虑使用collections.deque来代替块的列表。你知道吗

如果您需要使用随机访问进行删除,那么每个块都可以保留一个删除计数,这样您只需要解压缩和压缩一个块,但是您不能再使用%来获取块;您需要保留每个块的计数索引,这样您就可以对分以找到任何索引的正确块。你知道吗

相关问题 更多 >