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

为何在多文件处理场景下Threading比Asyncio快得多?

大量文件处理场景下asyncio、threading、multiprocessing性能差异分析

测试场景与代码

我正在测试Python的asyncio、threading与multiprocessing,以确定大量文件处理场景下的最优并发机制。实验内容为读取文件,在每行末尾追加字符后写回,测试代码如下:

import asyncio
import threading
from multiprocessing import Process

async def process_files(filenames):
    for filename in filenames:
        await process_file(filename)

async def process_file(filename):
    i = 0
    #await asyncio.sleep(0.1)
    with open(filename, 'r+') as f:
        lines = f.readlines()
        for line in lines:
            line += f"{i}\n"
            f.write(line)
            i += 1

def regular_process_file(filename):
    i = 0
    with open(filename, 'r+') as f:
        lines = f.readlines()
        for line in lines:
            line += f"{i}\n"
            f.write(line)
            i += 1

# asyncio调用
asyncio.run(process_files(filenames))

# 多线程调用
threads = []
for file in filenames:
    t = threading.Thread(target=regular_process_file, args=(file,))
    t.start()
    threads.append(t)
for t in threads:
    t.join()

# 多进程调用
processes = []
for file in filenames:
    proc = Process(target=regular_process_file, args=(file,))
    processes.append(proc)
    proc.start()

for p in processes:
    p.join()

测试结果与疑问

对三种机制计时后发现:asyncio耗时与multiprocessing接近,threading耗时约为前两者的2/3。我原本的预期是:受GIL限制,asyncio与threading效率应相近;若threading能利用多处理器,性能则应与multiprocessing接近,实际结果与预期不符,对此存在疑问。

核心原因解析

1. 你的asyncio代码并非真正异步执行

当前代码中的文件读写使用的是Python原生的同步IO接口(open、readlines、write),这些操作会阻塞asyncio的事件循环。在执行await process_file(filename)时,事件循环会被完全阻塞,直到该文件处理完成才会切换到下一个任务——本质上是串行处理所有文件,而非并发。这也是asyncio耗时与multiprocessing接近的原因:multiprocessing是并行处理但存在进程创建/切换的额外开销,而asyncio是串行处理无额外开销,两者耗时因此拉平。

2. threading在IO密集场景下的优势

Python的GIL(全局解释器锁)确实会限制同一时间只有一个线程执行CPU密集型任务,但在执行阻塞式系统调用(如文件IO)时,线程会主动释放GIL,让其他线程可以获取GIL并执行。因此在文件处理这种IO密集场景下,多线程可以同时等待不同文件的IO操作,实现高效并发。同时,线程的创建与切换开销远小于进程,这也是threading耗时比multiprocessing短的核心原因。

3. multiprocessing的开销问题

multiprocessing通过创建独立的Python解释器进程绕过GIL,实现真正的并行执行,但进程的创建、内存复制、进程间通信都存在显著开销。在IO密集的文件处理场景下,这些开销抵消了并行带来的收益,导致其耗时不如threading。

优化建议

让asyncio实现真正异步

要让asyncio发挥出IO密集场景的优势,需要使用异步文件IO库(如aiofiles)替代同步IO接口,同时使用asyncio.gather并发执行所有文件处理任务,示例代码如下:

import asyncio
import aiofiles

async def process_file(filename):
    i = 0
    async with aiofiles.open(filename, 'r+') as f:
        lines = await f.readlines()
        for line in lines:
            line += f"{i}\n"
            await f.write(line)
            i += 1

async def process_files(filenames):
    await asyncio.gather(*[process_file(filename) for filename in filenames])

asyncio.run(process_files(filenames))

修改后,asyncio的事件循环可以在等待文件IO时切换到其他任务,实现低开销的并发处理,性能会接近甚至超过threading。

三种机制的适用场景总结

  • threading:适合IO密集型任务,线程开销小,IO操作时自动释放GIL,能高效并发。
  • multiprocessing:适合CPU密集型任务,绕过GIL实现真正并行,但进程开销大。
  • asyncio:适合高并发的IO密集型任务(如网络请求、大量文件处理),任务切换开销极小,但需配套使用异步IO接口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:57:10