如何在 Python 中解释 Dill 的酸洗跟踪输出? (分析(非)酸洗/(反)序列化瓶颈)

Posted

技术标签:

【中文标题】如何在 Python 中解释 Dill 的酸洗跟踪输出? (分析(非)酸洗/(反)序列化瓶颈)【英文标题】:How to interpret Dill's pickling trace output in Python? (Profiling (un)pickling / (de)serialization bottlenecks) 【发布时间】:2021-06-19 15:56:49 【问题描述】:

我正在尝试使用 dills 的 dill.detect.trace(True) 功能(在酸洗过程中打印跟踪)来找出我的解酸过程如此缓慢的原因。我还没有找到一种方法来输出 unpickling 的跟踪,但我假设这或多或少是酸洗的 1 对 1 反向过程,因此检查酸洗跟踪应该揭示也适用于 unpickling 的瓶颈。

但是,我不知道如何解释它的输出。例如:

T4: <class 'foo_package.base.model.BarModel'>
# T4
D2: <dict object at 0x7f7de3832800>
T4: <class 'pathlib.PosixPath'>
# T4
T4: <class 'foo_package.some_module.Bar'>
# T4
D2: <dict object at 0x7f7d206273c0>
T4: <class 'some_package.some_module.Bar.options.SessionOptions'>
# T4
D2: <dict object at 0x7f7d20384040>
T4: <enum 'ModelType'>
# T4
T4: <enum 'SomeOtherEnum'>
# T4
# D2
D2: <dict object at 0x7f7d206b9ac0>
# D2
T4: <class 'some_package.some_other_module.XyzzyObject'>
# T4
D2: <dict object at 0x7f7d206cb100>
###... and so on...

应该如何解释D2T4# 前缀是什么意思?是否可以找到关于增加(反)序列化时间的循环引用/深度嵌套结构存在的提示?

关于 trace 函数的 Dills 文档仅说明:

跟踪(布尔值)

print a trace through the stack when pickling; useful for debugging

更多背景: (降低 XY 问题的风险)

我正在使用 dill 存储 python 程序实例的部分状态,以保存分析模型。

(Un)pickling 随着时间的推移变得非常缓慢,我正在尝试找出原因。

对于包含大量数据的对象,我已经将具有专用序列化方法(例如 numpy/pyarrow/pandas 对象)的对象存储委托给使用 __getstate____setstate__ 的其他序列化方法。这有点帮助,但反序列化仍然需要 1 到 2 分钟,这会大大减慢调试过程。

【问题讨论】:

【参考方案1】:

我是莳萝作者。 这是从 GitHub 和 PyPI 上的 README 复制而来的...

为了帮助调试酸洗问题,请使用 dill.detect,它提供 像泡菜追踪这样的工具::

>>> import dill.detect
>>> dill.detect.trace(True)
>>> f = dumps(squared)
F1: <function <lambda> at 0x108899e18>
F2: <function _create_function at 0x108db7488>
# F2
Co: <code object <lambda> at 0x10866a270, file "<stdin>", line 1>
F2: <function _create_code at 0x108db7510>
# F2
# Co
D1: <dict object at 0x10862b3f0>
# D1
D2: <dict object at 0x108e42ee8>
# D2
# F1
>>> dill.detect.trace(False)

通过跟踪,我们可以看到 dill 是如何存储 lambda (F1) 的,方法是先存储 _create_function,底层代码对​​象(Co)和_create_code (用于处理代码对象),然后我们处理对的引用 全局字典 (D2)。 # 标记对象的实际存储时间。

【讨论】:

见:github.com/uqfoundation/dill/blob/master/README.md 谢谢。将此信息也添加到此功能的文档中可能是值得的。我希望文档包含比 README 更详细的信息(尽管我的 google fu 没有找到它,但我可能在其他地方的文档中遗漏了一个位置)。在不相关的说明上;我也感谢开发这个包;你帮助了很多人。 你是对的。自述文件是文档中唯一包含它的地方。

以上是关于如何在 Python 中解释 Dill 的酸洗跟踪输出? (分析(非)酸洗/(反)序列化瓶颈)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Dill 加载对象的 Python TypeError

更改模块目录后的 Python 酸洗

如何获取 Python 解释器堆栈的当前深度?

如何获取 python 函数的酸洗依赖项?

如何使用 python 多线程并行化来自另一个模块的函数而不进行酸洗?

在装饰器中使用 ProcessPoolExecutor 酸洗 Python 函数失败