V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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 · Jun 29, 2018 · 5732 views
    This topic created in 2871 days ago, the information mentioned may be changed or developed.

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

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

    我怎么觉得比你写这一套还要简单点?
    misaka19000
        16
    misaka19000  
    OP
       Jun 29, 2018
    @ryd994 #15 谢谢,我再琢磨琢磨,有不懂的再向您请教😋
    NoAnyLove
        17
    NoAnyLove  
       Jun 30, 2018
    eventlet 了解一下,另外,你是所有线程共享同一个 event ?
    misaka19000
        18
    misaka19000  
    OP
       Jun 30, 2018
    @NoAnyLove #17 是的,是所有的线程共享一个 event
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1091 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 54ms · UTC 23:30 · PVG 07:30 · LAX 16:30 · JFK 19:30
    ♥ Do have faith in what you're doing.