V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
misaka19000
V2EX  ›  Python

Python 程序的大量时间消耗在了 lock.acquire 和 time.sleep 上面了,有办法优化吗

  •  
  •   misaka19000 ·
    RitterHou · 2018-06-29 11:04:29 +08:00 · 5291 次点击
    这是一个创建于 2330 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在执行 Profile 的时候发现大量的时间消耗在了这两个方法上,个人认为主要原因在于如下的代码:

    event = threading.Event()
    
    socket.write(data)
    while request_id not in results:
        event.clear()
        event.wait()
    result = results[request_id]
    print result
    
    result = socket.read()
    results[request_id] = result
    event.set()
    

    上面代码的目的是为了把异步的网络请求转为同步请求,客户端在请求发出去之后就进入阻塞状态,直到服务端的响应返回值后,我在读取数据到 results 之后唤醒请求线程,之后请求线程继续执行。

    我有两个问题想请问下各位大佬:

    1. 上面的代码是产生图片中方法时间消耗的原因吗?
    2. 上面的代码会对性能产生影响吗,影响有多大?
    3. Python 有没有什么更好的方式来实现异步的通信转为同步呢?

    谢谢大家!!!😋

    18 条回复    2018-06-30 10:28:13 +08:00
    dbow
        1
    dbow  
       2018-06-29 11:16:20 +08:00
    用 coroutine
    ```python
    async def hello():
    print("Hello world!")
    r = await asyncio.sleep(1)
    print("Hello again!")
    ```
    NoAnyLove
        2
    NoAnyLove  
       2018-06-29 11:20:26 +08:00
    游泳健身,了。。。。。。哦不是,asyncio 了解一下
    lieh222
        3
    lieh222  
       2018-06-29 11:23:57 +08:00
    啤酒饮料矿泉,水。。。。。。哦不是,asyncio 需要吗
    lfzyx
        4
    lfzyx  
       2018-06-29 11:28:11 +08:00   ❤️ 4
    这个图片是用什么工具生成的
    locoz
        5
    locoz  
       2018-06-29 13:06:00 +08:00 via Android
    @lfzyx pycharm 的功能吧
    wwqgtxx
        6
    wwqgtxx  
       2018-06-29 13:19:19 +08:00 via iPhone
    这种异步转同步有大量锁的等待很正常呀,Event 本来就是用 lock 实现的,对性能影响不大,要是真的那么在乎这一点性能,用 asyncio 或者 gevent
    misaka19000
        7
    misaka19000  
    OP
       2018-06-29 13:31:11 +08:00
    @dbow #1
    @NoAnyLove #2
    @lieh222 #3
    @wwqgtxx #6
    python2 不支持 asyncio 呀。。。
    misaka19000
        8
    misaka19000  
    OP
       2018-06-29 13:32:36 +08:00   ❤️ 2
    @lfzyx #4 PyCharm 在 run 的时候有一个 Profile 选项,用那个选项来运行就行了
    tonic
        9
    tonic  
       2018-06-29 18:24:01 +08:00
    那么 eventlet / gevent 了解一下...
    tonic
        10
    tonic  
       2018-06-29 18:24:36 +08:00
    等下我看反了... 你要异步变同步... = =!
    aaronzjw
        11
    aaronzjw  
       2018-06-29 18:27:16 +08:00 via iPhone
    用协程
    misaka19000
        12
    misaka19000  
    OP
       2018-06-29 18:35:31 +08:00
    @aaronzjw #11 大佬能不能再详细的介绍介绍啊,萌新不太理解啊。。。
    lolizeppelin
        13
    lolizeppelin  
       2018-06-29 20:15:38 +08:00 via Android
    你要干啥 如果是 socket 收数据
    收好的数据塞队列里
    然后另外一个线程从队列里取就完了

    不要没事就加锁
    misaka19000
        14
    misaka19000  
    OP
       2018-06-29 21:16:23 +08:00
    @lolizeppelin #13 但是请求是同步的,我得在前端知道数据是否已经获取到了啊。。。
    ryd994
        15
    ryd994  
       2018-06-29 23:36:49 +08:00 via Android
    要性能的话可以自己实现协程
    做个等待表
    有结果回来的话就查表唤醒等到中的线程不就好了么?
    再进一步,加上回调函数,有结果的话调用回调

    我怎么觉得比你写这一套还要简单点?
    misaka19000
        16
    misaka19000  
    OP
       2018-06-29 23:48:33 +08:00
    @ryd994 #15 谢谢,我再琢磨琢磨,有不懂的再向您请教😋
    NoAnyLove
        17
    NoAnyLove  
       2018-06-30 10:16:08 +08:00
    eventlet 了解一下,另外,你是所有线程共享同一个 event ?
    misaka19000
        18
    misaka19000  
    OP
       2018-06-30 10:28:13 +08:00
    @NoAnyLove #17 是的,是所有的线程共享一个 event
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5953 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:03 · PVG 10:03 · LAX 18:03 · JFK 21:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.