0

有没有办法使用 pypy3 加快将字符串流转换为 json/字典的速度?我知道 python3 中的 ujson 可能比 python3 的 json 快,但它并没有真正比 pypy3 快json.loads()

关于我所拥有的更多信息,我有一个程序从子进程读取 json 字符串流并使用json.loads(). 如果我注释掉 json 加载执行行(基本上只是从子进程中读取标准输出,它只需要大约 60% 的总执行。

所以我在考虑使用进程池或线程池可以改进它(可能至少高达 80% 的执行时间),并并行执行转换。不幸的是,它什么也没做。使用多线程具有相同的结果,并且多进程花费的时间超过 1 个单个进程(可能主要是由于开销和序列化)。是否有任何其他更改可以提高 pypy3 的性能?

作为参考,这是一个快速的代码示例(只是从某个文件中读取):

import json
import timeit
from multiprocessing.pool import ThreadPool
from multiprocessing import Pool


def get_stdout():
    with open("input.txt", "r") as f:
        for line in f:
            yield line


def convert(line):
    d = json.loads(line)
    return d


def multi_thread():
    mt_pool = ThreadPool(3)
    for dict in mt_pool.imap(convert, get_stdout()):
        pass


def multi_process():
    with Pool(3) as mp_pool:
        for dict in mp_pool.imap(convert, get_stdout()):
            pass


def regular():
    for line in get_stdout():
        d = convert(line)


print("regular: ", timeit.repeat("regular()", setup="from __main__ import regular", number=1, repeat=5))
print("multi_thread: ", timeit.repeat("multi_thread()", setup="from __main__ import multi_thread", number=1, repeat=5))
print("multi_process: ", timeit.repeat("multi_process()", setup="from __main__ import multi_process", number=1, repeat=5))

输出:

regular: [5.191860154001915, 5.045155504994909, 4.980729935996351, 5.253822096994554, 5.9532385260026786]
multi_thread: [5.08890142099699, 5.088432839998859, 5.156651658995543, 5.781010364997201, 5.082046301999071]
multi_process: [26.595598744999734, 30.841693959999247, 29.383782051001617, 27.83700947300531, 21.377069750000373]
4

1 回答 1

1

当前代码的问题在于,由于进程间通信,从进程返回 Python 对象的成本imap非常昂贵。将输入字符串发送到工作进程也可能会降低性能。当前代码不应受限于输入解析,而应受限于创建 CPython 对象和进程之间的对象传输。线程版本没有用,因为代码可能不受 IO 限制,并且 Python全局解释器锁(即 GIL)目前阻止了多线程的任何性能改进。通过不发回结果可以使多处理版本更快:您需要在工作进程中处理 json 文档将最少量的信息发送回主进程。如果需要,您可以使用共享内存区域从工作人员到主进程有效地检索基本Numpy 数组。最后,只要您不需要解码所有文档,使用Simdjson可以更快。

PyPy 有一个可扩展的事务内存机制,可能对实现更快的多线程 json 解析实现很有用。但是,AFAIK 目前没有使用它的模块,也没有开发 pypy-stm。

如果您真的想将(大/很多)Json 文档处理成一堆异构对象,并且您需要快速计算所有这些对象(不使用多个独立进程),那么 Python 可能不是正确的工具。

于 2021-11-19T18:00:43.587 回答