You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程生成测试数据超百万条后性能骤降排查求助

优化高量测试数据生成中fake_workers创建的性能瓶颈

一、核心瓶颈定位

1. 内存过载

5000万条对象全塞进列表,会占用巨量内存(假设每个对象占100字节,就是5GB),一旦超出物理内存,系统触发页交换(Swap),速度直接跌到磁盘IO级别,这就是tqdm迭代速度骤降的核心原因。

2. 序列化/IPC开销

如果用multiprocessing异步池时,你是先在主进程创建全量fake_workers再传给子进程,会触发大量对象的pickle序列化/反序列化,IPC开销随数据量指数级上升。

3. 对象创建冗余

比如每次生成fake_worker都重复初始化Faker(如果用了这个库),或者重复生成相同基础数据,没有复用资源。


二、针对性优化方案

1. 用生成器+分块处理替代全量列表

别一次性把所有对象存进内存,改用生成器按需创建,分块交给子进程处理:

from multiprocessing import Pool
from faker import Faker
import tqdm

def create_fake_worker(_):
    # 子进程内只初始化一次Faker,避免重复开销
    fake = Faker()
    return {
        "id": fake.uuid4(),
        "name": fake.name(),
        "email": fake.email(),
        # 其他字段按需添加
    }

def generate_workers(total_count, chunk_size=10000):
    with Pool() as pool:
        # 用生成器迭代,内存只存当前chunk的数据
        for chunk in tqdm.tqdm(
            (pool.map(create_fake_worker, range(chunk_size)) for _ in range(total_count // chunk_size)),
            total=total_count//chunk_size
        ):
            yield from chunk
        # 处理剩余不足chunk_size的部分
        remaining = total_count % chunk_size
        if remaining > 0:
            yield from pool.map(create_fake_worker, range(remaining))

# 使用时直接迭代生成器,不用存全量数据
for worker in generate_workers(50000000):
    # 写入文件/数据库等操作
    pass
  • 优势:内存占用始终控制在chunk_size级别,彻底避免页交换;子进程内部复用Faker资源。

2. 全局复用Faker实例

通过进程池的初始化函数,让每个子进程只初始化一次Faker,避免重复加载本地化数据:

# 子进程全局变量,初始化一次复用
fake = None
def init_worker():
    global fake
    fake = Faker()

def create_fake_worker(_):
    return {
        "id": fake.uuid4(),
        "name": fake.name(),
        "email": fake.email(),
    }

def generate_workers(total_count, chunk_size=10000):
    with Pool(initializer=init_worker) as pool:
        # 分块处理逻辑同上
        ...

3. 避免不必要的类封装

如果fake_workers只是生成结构化数据,直接用字典甚至元组,不要用自定义类——自定义类的pickle开销和内存占用都远高于基础数据类型。

4. 改用进程内批量生成

如果CPU不是瓶颈,单个进程内批量生成数据可以减少IPC开销:

def batch_create_workers(batch_size):
    fake = Faker()
    return [{"id": fake.uuid4(), "name": fake.name()} for _ in range(batch_size)]

# 批量生成+处理,减少进程通信次数
for _ in tqdm.tqdm(range(50000000 // 10000)):
    batch = batch_create_workers(10000)
    # 写入文件/数据库等操作

5. 用元组降内存

如果生成的数据不需要修改,用元组代替字典,能减少约30%的内存占用:

def create_fake_worker(_):
    return (fake.uuid4(), fake.name(), fake.email())

三、效果验证

先测1000万条数据,用htop或psutil看内存占用,稳定在几百MB级别说明内存瓶颈解决;再看tqdm迭代速度,应该能回到接近100万条时的水平,甚至更快(减少了GC开销)。

内容的提问来源于stack exchange,提问作者greenpotlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 09:05:17