cython 也可以优化 python 字典内存和查找速度吗?

Can cython optimize python dictionary memory and lookup speed as well?

我有一个 class 主要包含三个字典:

class KB(object):

  def __init__(self):

    # key:str value: list of str
    linear_patterns = defaultdict(list)

    # key:str value: list of str        
    nonlinear_patterns = defaultdict(list)

    # key: str value: dict
    pattern_meta_info = {}
    ...
    self.__initialize()

def __initialize(self):
    # the 3 dicts are populated 
    ...

3 个字典的大小如下:

linear_patterns: 100,000
non_linear_patterns: 900,000
pattern_meta_info: 700,000

程序运行完成后,释放内存大约需要15秒。当我在初始化时通过加载较少的数据来减少上面的dict sizes的数量时,内存释放更快,所以我判断是由于这些dict sizes导致内存释放变慢。整个程序大约需要8G内存。另外,dicts构建后,所有操作都是查找,没有修改。

有没有办法用cython来优化上面的3种数据结构,尤其是在内存占用方面?是否有类似的 cython 字典可以替代 python 字典?

不同的字典或对象类型似乎不太可能发生太大变化。析构函数的性能由内存分配器决定。除非您切换到不同的 malloc 实现,否则这将大致相同。

如果这只是关于在程序结束时销毁对象,大多数语言(但 Python 除外)将允许您使用调用 exit,同时保持 KB 对象处于活动状态。 OS 将在进程终止时更快地释放内存。那么为什么要打扰呢?不幸的是,这不适用于 Python 的 sys.exit(),因为这只会引发异常。

其他一切都依赖于更改数据结构或算法。您的字符串是否高度冗余?也许您可以通过实习来重用字符串对象。将它们保存在一个共享集中,以便在多个地方使用相同的字符串。对 string = sys.intern(string) 的简单调用就足够了。与 Python 的早期版本不同,这不会使字符串对象在其使用之外保持活动状态,因此您不会 运行 在 long-running 进程中泄漏内存的风险。

您还可以将字符串集中在一个大的分配中。如果访问相对较少,您可以将 class 更改为其包含的字符串使用一个大的 io.StringIO 对象,所有字典只处理 (offset, length) 元组到该缓冲区。

这仍然留下许多元组和整数对象,但那些使用可能更快的专用分配器。此外,长度整数将来自小整数的公共池,并且不会分配新对象。

最后一个想法:8 GB 的字符串数据。您确定不需要小型 sqlite 或 dbm 数据库吗?可能是一个临时文件