快速解码 Python 中的大量 "JSON-like" 数据
Decode big amount of "JSON-like" data in Python quickly
假设有许多(大约 300,000 个)JSON 文件需要很长时间(大约 30 分钟)才能加载到 Python 个对象的列表中。分析表明,实际上占用大部分时间的不是文件访问,而是解码。有没有我可以将这些文件转换成的格式,可以更快地将其加载到 python 对象列表中?
我的尝试: 我将文件转换为 ProtoBuf(又名 Google 的 Protocol Buffers) 但即使我得到的文件非常小(减少到原始大小的 20% 左右),加载它们的时间并没有显着改善(加载它们仍然需要 20 多分钟)。
您可能正在寻找错误的转换方向,因为它可能不会像您希望的那样减少加载时间。如果解码花费大量时间,假设 JSON 解码器编写得不是很糟糕,那么其他格式也可能需要相当长的时间。我假设标准库函数有不错的实现,并且 JSON 在数据存储速度方面并不是一种糟糕的格式。
您可以尝试使用 运行 您的程序 PyPy 而不是我假设您正在使用的默认 CPython 实现。 PyPy 可以极大地减少执行时间。它有一个更快的 JSON 模块并使用 JIT,这可能会加速你的程序 很多。
如果您使用的是 Python 3,您也可以尝试使用 ProcessPoolExecutor to run the file loading and data deserialization / decoding concurrently. You will have to experiment with the degree of concurrency, but a good starting point is the number of your CPU cores, which you can halve or double. If your program waits for I/O a lot, you should run a higher degree of concurrency, if the degree of I/O is smaller you can try and reduce the concurrency. If you write each executor so that they load the data into Python objects and simply return them, you should be able to cut your loading times significantly. Note that you must use a process-driven approach, using threads will not work with the GIL。
您还可以使用 faster JSON library,在最佳情况下,它可以将执行时间加快两到三倍。在现实世界的用例中,加速可能会更小。 请注意,这些可能不适用于 PyPy,因为它使用替代的 CFFI 实现并且不适用于 CPython 程序,而且 PyPy 有一个很好的 JSON 模块。
试试ujson
,速度会快很多。
"Decoding takes most of the time"可以看成"building the Python objects takes all the time"。你真的需要所有这些东西作为 RAM 中的 Python 对象吗?一定不少。
我会考虑使用合适的数据库,例如查询这样大小的数据。
如果您需要不同类型的批量处理,例如统计或矩阵处理,我会看一下 pandas
.
假设有许多(大约 300,000 个)JSON 文件需要很长时间(大约 30 分钟)才能加载到 Python 个对象的列表中。分析表明,实际上占用大部分时间的不是文件访问,而是解码。有没有我可以将这些文件转换成的格式,可以更快地将其加载到 python 对象列表中?
我的尝试: 我将文件转换为 ProtoBuf(又名 Google 的 Protocol Buffers) 但即使我得到的文件非常小(减少到原始大小的 20% 左右),加载它们的时间并没有显着改善(加载它们仍然需要 20 多分钟)。
您可能正在寻找错误的转换方向,因为它可能不会像您希望的那样减少加载时间。如果解码花费大量时间,假设 JSON 解码器编写得不是很糟糕,那么其他格式也可能需要相当长的时间。我假设标准库函数有不错的实现,并且 JSON 在数据存储速度方面并不是一种糟糕的格式。
您可以尝试使用 运行 您的程序 PyPy 而不是我假设您正在使用的默认 CPython 实现。 PyPy 可以极大地减少执行时间。它有一个更快的 JSON 模块并使用 JIT,这可能会加速你的程序 很多。
如果您使用的是 Python 3,您也可以尝试使用 ProcessPoolExecutor to run the file loading and data deserialization / decoding concurrently. You will have to experiment with the degree of concurrency, but a good starting point is the number of your CPU cores, which you can halve or double. If your program waits for I/O a lot, you should run a higher degree of concurrency, if the degree of I/O is smaller you can try and reduce the concurrency. If you write each executor so that they load the data into Python objects and simply return them, you should be able to cut your loading times significantly. Note that you must use a process-driven approach, using threads will not work with the GIL。
您还可以使用 faster JSON library,在最佳情况下,它可以将执行时间加快两到三倍。在现实世界的用例中,加速可能会更小。 请注意,这些可能不适用于 PyPy,因为它使用替代的 CFFI 实现并且不适用于 CPython 程序,而且 PyPy 有一个很好的 JSON 模块。
试试ujson
,速度会快很多。
"Decoding takes most of the time"可以看成"building the Python objects takes all the time"。你真的需要所有这些东西作为 RAM 中的 Python 对象吗?一定不少。
我会考虑使用合适的数据库,例如查询这样大小的数据。
如果您需要不同类型的批量处理,例如统计或矩阵处理,我会看一下 pandas
.