V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
paparika
V2EX  ›  Linux

client 用 poll 方式收发消息,会不会比同步阻塞方式功耗更大

  •  
  •   paparika · 2018-08-09 18:15:15 +08:00 · 2588 次点击
    这是一个创建于 2298 天前的主题,其中的信息可能已经有所发展或是发生改变。

    client 用 poll 机制发消息,如果 poll 的轮询间隔太久话,消息最坏要等一个间隔时间才发送,但是轮询间隔设在百毫秒级,有点担心是不是浪费 cpu 资源。cpu 占用跟同步阻塞方式比呢?

    15 条回复    2018-08-10 10:10:54 +08:00
    MeteorCat
        1
    MeteorCat  
       2018-08-09 18:22:50 +08:00 via Android
    poll 轮询是在有 POLLIN 之后触发 pollfds 轮询的吧,POLLIN 之后一直没有拿他处理
    MeteorCat
        2
    MeteorCat  
       2018-08-09 18:23:43 +08:00 via Android
    @MeteorCat 除非接收到 POLLIN 事件一直不做处理
    paparika
        3
    paparika  
    OP
       2018-08-09 18:27:25 +08:00
    @MeteorCat 具体细节记不清了,回头再查下。先问下”如果 poll 的轮询间隔太久话,消息最坏要等一个间隔时间才发送“,这个结论正确吗,有办法消息能几乎立即发送吗
    MeteorCat
        4
    MeteorCat  
       2018-08-09 18:31:31 +08:00 via Android
    @paparika 这个分情况来看,如果你 client 只连接一个服务器,那轮询也只是对一个轮询,到达肯定是立即到达的;如果你 client 是和多个服务器连接的,poll 循环间隔会随着你连接服务端数量增加[前提是不使用线程进程,全部在主线程跑]
    paparika
        5
    paparika  
    OP
       2018-08-09 18:39:52 +08:00
    @MeteorCat 刚才我描述的可能有问题,现在是这样,我在一个线程里循环 poll,间隔是 10s,然后另外一个线程发起连接服务器,发现要基本过了 10s 才真正有发起连接的动作
    MeteorCat
        6
    MeteorCat  
       2018-08-09 18:44:30 +08:00 via Android
    @paparika 必然的,你 poll 的 timeout 设定为 10s ?他会阻塞整个系统 10s 的,另外线程也会影响
    paparika
        7
    paparika  
    OP
       2018-08-09 18:44:36 +08:00
    基本上就是要等过了一个间隔时间后,才真正有连接动作。这里想问,这个是不是正常的,另外就是除了调小时间间隔,有其他办法吗
    MeteorCat
        8
    MeteorCat  
       2018-08-09 18:46:45 +08:00 via Android
    @paparika 算了你还是上代码吧,免得其他人猜半天
    paparika
        9
    paparika  
    OP
       2018-08-09 18:48:42 +08:00
    @MeteorCat 感觉设为百毫秒级别的话,频繁唤醒 cpu,应该是比同步阻塞方式功耗多不少吧
    paparika
        10
    paparika  
    OP
       2018-08-09 18:51:49 +08:00
    @MeteorCat 代码是用的一个库 mongoose,我先上下看个大概吧

    在一个独立线程里 poll
    void* Foobar::init_thread(void *arg){

    pthread_detach(pthread_self());

    while(loop){
    mg_mgr_poll(mgr, 10000);
    }

    return NULL;
    }

    在其它线程发起连接
    mg_connect_ws(&mgr, ev_handler, url,  WS_PROTOCOL, HEADER);
    MeteorCat
        11
    MeteorCat  
       2018-08-09 18:59:30 +08:00 via Android
    @paparika 你 timeout 设 10000 ?— —
    MeteorCat
        12
    MeteorCat  
       2018-08-09 19:03:36 +08:00 via Android
    @paparika https://linux.die.net/man/2/poll 如果我记得每次,poll 最后参数是设定内核事件检查的间隔
    paparika
        13
    paparika  
    OP
       2018-08-10 09:31:35 +08:00
    @MeteorCat 调试而已,设多少无所谓的。这个是库自己的 poll,不是标准函数。poll 机制不是来事件就退出阻塞态吗,连接应该也算事件,为啥会第二次进入 poll 才响应
    wwqgtxx
        14
    wwqgtxx  
       2018-08-10 09:53:54 +08:00
    “消息最坏要等一个间隔时间才发送”这个问题不难解决吧,linux 的 poll 是支持任意文件描述符的,你随便开一个空的文件描述符(比如 cpython 的做法,开一个 socketpair, https://github.com/python/cpython/blob/3.7/Lib/socket.py#L499 ),然后在你需要唤醒的时候往这个文件描述符对应的文件 write 一下不就可以退出 poll 的阻塞了,没必要“轮询间隔设在百毫秒级”吧
    paparika
        15
    paparika  
    OP
       2018-08-10 10:10:54 +08:00
    @wwqgtxx 多谢这个思路,不过我这个是现成的库,没具体看源码,可能需要改造下。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2686 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 03:44 · PVG 11:44 · LAX 19:44 · JFK 22:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.