异步版本运行速度比非异步版本慢
async version runs slower than the non async version
我的程序执行以下操作:
- 获取 .txt 文件的文件夹
每个文件:
2.1。读取文件
2.2 将内容排序为列表并将列表推送到主列表
我这样做时没有任何 async/await 这些是时间统计数据
real 0m0.036s
user 0m0.018s
sys 0m0.009s
使用下面的 async/await 代码我得到
real 0m0.144s
user 0m0.116s
sys 0m0.029s
给出的用例表明我错误地使用了 aysncio。
有人知道我做错了什么吗?
import asyncio
import aiofiles
import os
directory = "/tmp"
listOfLists = list()
async def sortingFiles(numbersInList):
numbersInList.sort()
async def awaitProcessFiles(filename,numbersInList):
await readFromFile(filename,numbersInList)
await sortingFiles(numbersInList)
await appendToList(numbersInList)
async def readFromFile(filename,numbersInList):
async with aiofiles.open(directory+"/"+filename, 'r') as fin:
async for line in fin:
return numbersInList.append(int(line.strip("\n"),10))
fin.close()
async def appendToList(numbersInList):
listOfLists.append(numbersInList)
async def main():
tasks=[]
for filename in os.listdir(directory):
if filename.endswith(".txt"):
numbersInList =list()
task=asyncio.ensure_future(awaitProcessFiles(filename,numbersInList))
tasks.append(task)
await asyncio.gather(*tasks)
if __name__== "__main__":
asyncio.run(main())
分析信息:
151822 function calls (151048 primitive calls) in 0.239 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
11 0.050 0.005 0.050 0.005 {built-in method _imp.create_dynamic}
57 0.022 0.000 0.022 0.000 {method 'read' of '_io.BufferedReader' objects}
57 0.018 0.000 0.018 0.000 {built-in method io.open_code}
267 0.012 0.000 0.012 0.000 {method 'control' of 'select.kqueue' objects}
57 0.009 0.000 0.009 0.000 {built-in method marshal.loads}
273 0.009 0.000 0.009 0.000 {method 'recv' of '_socket.socket' objects}
265 0.005 0.000 0.098 0.000 base_events.py:1780(_run_once)
313 0.004 0.000 0.004 0.000 {built-in method posix.stat}
122 0.004 0.000 0.004 0.000 {method 'acquire' of '_thread.lock' objects}
203/202 0.003 0.000 0.011 0.000 {built-in method builtins.__build_class__}
1030 0.003 0.000 0.015 0.000 thread.py:158(submit)
1030 0.003 0.000 0.009 0.000 futures.py:338(_chain_future)
7473 0.003 0.000 0.003 0.000 {built-in method builtins.hasattr}
1030 0.002 0.000 0.017 0.000 futures.py:318(_copy_future_state)
36 0.002 0.000 0.002 0.000 {built-in method posix.getcwd}
3218 0.002 0.000 0.077 0.000 {method 'run' of 'Context' objects}
6196 0.002 0.000 0.003 0.000 threading.py:246(__enter__)
3218 0.002 0.000 0.078 0.000 events.py:79(_run)
6192 0.002 0.000 0.004 0.000 base_futures.py:13(isfuture)
1047 0.002 0.000 0.002 0.000 threading.py:222(__init__)
制作一些测试文件...
import random, os
path = <directory name here>
nlines = range(1000)
nfiles = range(1,101)
for n in nfiles:
fname = f'{n}.txt'
with open(os.path.join(path,fname),'w') as f:
for _ in nlines:
q = f.write(f'{random.randrange(1,10000)}\n')
asyncio 对本地文件没什么意义。这就是原因,即使 python 标准库也没有它们。
async for line in fin:
考虑上面一行。事件循环会为读取的每一行暂停协程并执行其他协程。这意味着 cpu 缓存中文件的以下行将被丢弃,以便为下一个协程制作 space。 (尽管它们仍会在 RAM 中)。
什么时候应该使用aio文件?
考虑到您已经在程序中使用了异步代码,并且偶尔需要进行一些文件处理。如果文件处理是在同一个事件循环中完成的,那么所有其他协同例程都将被阻塞。在那种情况下,您可以使用 aiofiles 或在不同的执行程序中进行处理。
如果程序所做的只是从文件中读取。按顺序执行它们会更快,以便充分利用缓存。从一个文件跳转到另一个文件就像线程上下文切换,应该会变慢。
我的程序执行以下操作:
- 获取 .txt 文件的文件夹
每个文件:
2.1。读取文件
2.2 将内容排序为列表并将列表推送到主列表
我这样做时没有任何 async/await 这些是时间统计数据
real 0m0.036s
user 0m0.018s
sys 0m0.009s
使用下面的 async/await 代码我得到
real 0m0.144s
user 0m0.116s
sys 0m0.029s
给出的用例表明我错误地使用了 aysncio。
有人知道我做错了什么吗?
import asyncio
import aiofiles
import os
directory = "/tmp"
listOfLists = list()
async def sortingFiles(numbersInList):
numbersInList.sort()
async def awaitProcessFiles(filename,numbersInList):
await readFromFile(filename,numbersInList)
await sortingFiles(numbersInList)
await appendToList(numbersInList)
async def readFromFile(filename,numbersInList):
async with aiofiles.open(directory+"/"+filename, 'r') as fin:
async for line in fin:
return numbersInList.append(int(line.strip("\n"),10))
fin.close()
async def appendToList(numbersInList):
listOfLists.append(numbersInList)
async def main():
tasks=[]
for filename in os.listdir(directory):
if filename.endswith(".txt"):
numbersInList =list()
task=asyncio.ensure_future(awaitProcessFiles(filename,numbersInList))
tasks.append(task)
await asyncio.gather(*tasks)
if __name__== "__main__":
asyncio.run(main())
分析信息:
151822 function calls (151048 primitive calls) in 0.239 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
11 0.050 0.005 0.050 0.005 {built-in method _imp.create_dynamic}
57 0.022 0.000 0.022 0.000 {method 'read' of '_io.BufferedReader' objects}
57 0.018 0.000 0.018 0.000 {built-in method io.open_code}
267 0.012 0.000 0.012 0.000 {method 'control' of 'select.kqueue' objects}
57 0.009 0.000 0.009 0.000 {built-in method marshal.loads}
273 0.009 0.000 0.009 0.000 {method 'recv' of '_socket.socket' objects}
265 0.005 0.000 0.098 0.000 base_events.py:1780(_run_once)
313 0.004 0.000 0.004 0.000 {built-in method posix.stat}
122 0.004 0.000 0.004 0.000 {method 'acquire' of '_thread.lock' objects}
203/202 0.003 0.000 0.011 0.000 {built-in method builtins.__build_class__}
1030 0.003 0.000 0.015 0.000 thread.py:158(submit)
1030 0.003 0.000 0.009 0.000 futures.py:338(_chain_future)
7473 0.003 0.000 0.003 0.000 {built-in method builtins.hasattr}
1030 0.002 0.000 0.017 0.000 futures.py:318(_copy_future_state)
36 0.002 0.000 0.002 0.000 {built-in method posix.getcwd}
3218 0.002 0.000 0.077 0.000 {method 'run' of 'Context' objects}
6196 0.002 0.000 0.003 0.000 threading.py:246(__enter__)
3218 0.002 0.000 0.078 0.000 events.py:79(_run)
6192 0.002 0.000 0.004 0.000 base_futures.py:13(isfuture)
1047 0.002 0.000 0.002 0.000 threading.py:222(__init__)
制作一些测试文件...
import random, os
path = <directory name here>
nlines = range(1000)
nfiles = range(1,101)
for n in nfiles:
fname = f'{n}.txt'
with open(os.path.join(path,fname),'w') as f:
for _ in nlines:
q = f.write(f'{random.randrange(1,10000)}\n')
asyncio 对本地文件没什么意义。这就是原因,即使 python 标准库也没有它们。
async for line in fin:
考虑上面一行。事件循环会为读取的每一行暂停协程并执行其他协程。这意味着 cpu 缓存中文件的以下行将被丢弃,以便为下一个协程制作 space。 (尽管它们仍会在 RAM 中)。
什么时候应该使用aio文件?
考虑到您已经在程序中使用了异步代码,并且偶尔需要进行一些文件处理。如果文件处理是在同一个事件循环中完成的,那么所有其他协同例程都将被阻塞。在那种情况下,您可以使用 aiofiles 或在不同的执行程序中进行处理。
如果程序所做的只是从文件中读取。按顺序执行它们会更快,以便充分利用缓存。从一个文件跳转到另一个文件就像线程上下文切换,应该会变慢。