I'm trying to measure python async function execution time. But I faced with problem because actual point when the function is starting is unknown.
Measurement function code:
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
Rest code:
@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)
The start time actually is the time when the routine task is added to queue, but I need the time when PUT request is sent.
Any suggestions are welcome.
It's virtually impossible to make exact measurements of latency in asyncio networking (AFAIK, would love to be prooved wrong).
The problem is hinted at in the documentation for create_connection:
Since that's the fundamental building block aiohttp uses and it's a coroutine which you can politely ask the event loop to execute when it's ready, rather than CALL RIGHT NOW; it's not really possible to get the exact time the connection is made and therefore request took. (also, technically there's a question of what you call "sent" time, is that including time taken to make the connection, or the time taken to transfer data once the connection is made? do you include name resolution in connection time?)
However, you can do a lot better than the code above, for example the time measured above with
timer
will include any time waiting for a connection to be available in the session's connection pool.Here's some code which gets you two times:
create_connection
coroutine is scheduled)Neither of these times will be perfect but unless your event loop is extremely busy they'll probably be accurate enough for any reasonable measurement.