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

为何Python异步文件写入比同步写入慢?如何优化异步IO效率?

异步文件写入为何比同步慢?如何正确发挥asyncio优势?

问题描述

我在学习Python的asyncio机制,尝试用aiofiles的异步文件写入提升速度,写了同步和异步两个版本:

同步写入函数:

def sync_writer():
    with open("file.txt", "w") as f:
        for i in range(500000):
            f.write(f"line#{i}\n")

多协程异步实现:

import asyncio
import aiofiles

async def write_fun(file, writer_n, n_writers):
    for i in range(writer_n, 500000, n_writers):
        await file.write(f"line#{i}\n")

async def async_writer(n_writers):
    async with aiofiles.open("file.txt", "w") as f:
        await asyncio.gather(*[write_fun(f, i, n_writers) for i in range(n_writers)])

测试后发现,异步版本用10个协程耗时36秒,同步版本仅0.33秒。我以为磁盘IO是密集型任务,异步应该更快,结果相反。请问原因是什么?怎么正确用asyncio和相关库发挥优势?


原因分析

1. 磁盘IO特性不支持单文件多协程并行

异步IO的核心优势是等待IO时不阻塞线程,让线程处理其他任务,但本地磁盘单文件写入无法真正并行:

  • 机械硬盘依赖物理磁头寻址,同一时间只能处理一个写入请求;SSD虽并行度更高,但单文件写入受文件系统锁约束,依然是串行执行。
  • 同步写入时,操作系统文件缓存会自动将大量小写入合并成大块批量写入磁盘,效率极高;多协程异步写入会把连续写入拆成零散交替请求,破坏缓存批量合并机制,频繁的IO提交和上下文切换开销远大于异步收益。

2. aiofiles的底层实现放大了开销

aiofiles并非原生异步磁盘IO(操作系统无通用异步磁盘IO接口),而是用线程池模拟异步操作:

  • 每次await file.write都会把写入任务提交到线程池,协程挂起等待结果;多协程同时写入同一文件时,线程池内的线程会竞争文件锁,加上频繁线程切换,额外开销巨大。

3. 异步写法存在逻辑问题

多个协程同时写入同一文件,相当于把连续写入拆分成零散的交替小写入,不仅无并行优势,反而因频繁调度和锁竞争拖慢整体速度。


正确使用姿势

1. 选对适用场景

asyncio的异步IO优势主要体现在网络IO密集型任务(比如同时处理上千个HTTP请求、TCP连接),或需要同时等待多个不同IO资源的场景(比如同时读多个文件+请求网络)。本地磁盘单文件写入是典型的不适合异步的场景。

2. 异步处理文件的正确方式

单协程异步写入

如果需要在写入文件的同时处理其他异步任务(比如监听网络请求),用单个协程完成文件写入,效率接近同步写入,还能利用异步非阻塞特性处理其他任务:

import asyncio
import aiofiles

async def single_coroutine_writer():
    async with aiofiles.open("file.txt", "w") as f:
        for i in range(500000):
            await f.write(f"line#{i}\n")

多文件并行写入

如果需要同时写入多个不同文件,用异步多协程并行处理,避免等待一个文件写入完成再处理下一个,真正发挥异步优势:

import asyncio
import aiofiles

async def write_single_file(filename):
    async with aiofiles.open(filename, "w") as f:
        for i in range(500000):
            await f.write(f"line#{i}\n")

async def async_multi_file_writer():
    files = [f"file_{i}.txt" for i in range(10)]
    await asyncio.gather(*[write_single_file(f) for f in files])

批量异步写入

把多个小写入合并成一个大字符串,减少await write的调用次数,降低调度开销:

import asyncio
import aiofiles

async def batch_async_writer():
    content = "\n".join([f"line#{i}" for i in range(500000)]) + "\n"
    async with aiofiles.open("file.txt", "w") as f:
        await f.write(content)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:05:24