Olj*_*jko 5 measurement python-3.x async-await python-asyncio aiohttp
我正在尝试测量 python 异步函数执行时间。但是我遇到了问题,因为函数启动的实际点是未知的。
测量功能代码:
def timer(func):
async def process(func, *args, **params):
if asyncio.iscoroutinefunction(func):
print('this function is a coroutine: {}'.format(func.__name__))
return await func(*args, **params)
else:
print('this is not a coroutine')
return func(*args, **params)
async def helper(*args, **params):
print('{}.time'.format(func.__name__))
start = datetime.datetime.now()
print(start)
result = await process(func, *args, **params)
finish = datetime.datetime.now()
print('>>> calculated - ', finish - start, 'start-', start, 'finish-', finish)
return result
return helper
Run Code Online (Sandbox Code Playgroud)
休息代码:
@timer
async def fetch(name, session):
url = 'http://localhost:8808/'
payload = {}
async with session.put(url, headers=HEADERS, json=payload) as response:
session.get_connection_count()
response_data = await response.read()
result = {'response_code': response.status,
'response_data': response_data}
return result
def on_data_received(future):
# pass
response_obj = json.loads(future.result()['response_data'])
response_code = future.result()['response_code']
device_id = response_obj.get('clientDeviceID')
async def run(r):
connector = DecoratedTCPConnector(limit_per_host=10000, limit=20000)
with TimedClientSession(connector=connector) as client:
for i in range(r):
id = ''.join([random.choice('01234') for x in range(16)])
task = asyncio.ensure_future(fetch(id, client))
task.add_done_callback(on_data_received)
tasks.append(task)
return await asyncio.gather(*tasks)
Run Code Online (Sandbox Code Playgroud)
开始时间实际上是例行任务加入队列的时间,但我需要发送PUT请求的时间。
欢迎任何建议。
实际上不可能对异步网络中的延迟进行精确测量(AFAIK,希望被证明是错误的)。
create_connection的文档中暗示了该问题:
...这个方法是一个协程,它将尝试在后台建立连接...
因为这是 aiohttp 使用的基本构建块,并且它是一个协程,您可以礼貌地要求事件循环在准备就绪时执行,而不是立即调用;实际上不可能获得连接建立的确切时间以及请求所花费的时间。(另外,从技术上讲,还有一个问题,即您所谓的“发送”时间,是包括建立连接所花费的时间,还是建立连接后传输数据所花费的时间?您是否在连接时间中包括名称解析?)
但是,您可以做得比上面的代码更好,例如上面测量的时间timer将包括等待会话连接池中可用连接的任何时间。
这是一些可以让你两次的代码:
create_connection)这两个时间都不是完美的,但除非您的事件循环非常繁忙,否则它们对于任何合理的测量来说可能都足够准确。
import asyncio
import functools
from time import time
import aiohttp
from aiohttp.client_proto import ResponseHandler
async def main():
connection_started_time = None
connection_made_time = None
class TimedResponseHandler(ResponseHandler):
def connection_made(self, transport):
nonlocal connection_made_time
connection_made_time = time()
return super().connection_made(transport)
class TimedTCPConnector(aiohttp.TCPConnector):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._factory = functools.partial(TimedResponseHandler, loop=loop)
async def _create_connection(self, req):
nonlocal connection_started_time
connection_started_time = time()
return await super()._create_connection(req)
async with aiohttp.ClientSession(connector=TimedTCPConnector(loop=loop)) as session:
async with session.get('https://www.google.com') as response:
await response.text()
print(f'>>> time taken including connection time: {time() - connection_started_time:0.3f}s')
print(f'>>> time taken once connection made: {time() - connection_made_time:0.3f}s')
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5524 次 |
| 最近记录: |