【问题标题】:Python async co-routine execution timePython异步协程执行时间
【发布时间】:2018-02-10 18:50:07
【问题描述】:

我正在尝试测量 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

休息代码:

@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)

开始时间其实是例行任务加入队列的时间,但是我需要发送PUT请求的时间。

欢迎提出任何建议。

【问题讨论】:

    标签: python-3.x async-await python-asyncio measurement aiohttp


    【解决方案1】:

    几乎不可能精确测量异步网络中的延迟(AFAIK,希望被证明是错误的)。

    create_connection 的文档中暗示了该问题:

    ...这个方法是一个协程,它会尝试在后台建立连接...

    因为这是 aiohttp 使用的基本构建块,并且它是一个协程,您可以礼貌地要求事件循环在它准备好时执行,而不是立即调用;实际上不可能获得建立连接的确切时间,因此请求已被占用。 (另外,从技术上讲,还有一个问题是您所谓的“发送”时间,是包括建立连接所花费的时间,还是建立连接后传输数据所花费的时间?您是否在连接时间中包括名称解析?)

    但是,您可以比上面的代码做得更好,例如上面用timer 测量的时间将包括等待会话连接池中可用连接的任何时间。

    这里有一些代码可以让你两次:

    • 连接开始的大概时间(create_connection 协程安排之前的时间)
    • 和(可能)更准确地建立连接的时间,例如。调用传输的connection_made 的时间。

    这些时间都不是完美的,但除非您的事件循环非常繁忙,否则它们可能足够准确,可以进行任何合理的测量。

    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())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      相关资源
      最近更新 更多