V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mason961125
V2EX  ›  C

异步 I/O 与线程池

  •  
  •   mason961125 · 2016-08-20 23:47:15 +08:00 · 2862 次点击
    这是一个创建于 3001 天前的主题,其中的信息可能已经有所发展或是发生改变。

    貌似 nginx 早期一直使用的是多进程+异步 I/O 的模式,后来(据说,个人未求证,只是在某技术博客里看到)使用了线程池技术。

    但是,既然已经使用了异步 I/O ,线程池还有存在的必要吗?如果有,为什么?

    18 条回复    2016-08-22 08:52:21 +08:00
    denghongcai
        1
    denghongcai  
       2016-08-20 23:54:58 +08:00
    http://www.infoq.com/cn/articles/thread-pools-boost-performance-9x

    性能提升也是在特定场景下,具体情况具体分析
    fcicq
        2
    fcicq  
       2016-08-20 23:59:08 +08:00   ❤️ 1
    FreeBSD 不需要楼上所说的这个优化, 这个优化仅限 Linux 才有意义.
    wevsty
        3
    wevsty  
       2016-08-21 00:55:40 +08:00
    异步 I/O 最大只能使用单核心,对于多核心的处理器来说并不能达到最大处理能力。多进程或者多线程可以使用多个处理器核心。既然要使用多进程或者多线程,那么进程池或者线程池就是有必要的。
    czz19891012
        4
    czz19891012  
       2016-08-21 01:18:33 +08:00   ❤️ 2
    你这个是 concurrency 的问题吧. 其实多线程, 你说的异步 IO(其实是 IO 多路复用) 都是实现 concurrency 的两个方式
    比如像 redis 单线程基于 epoll 这种模型, node.js 这种模型都可以归结为 Event-base Concurrency, 那么这种模型和 multi-thread 对比有什么区别呢?

    从这个角度来看 multi-thread 是 kernel 来决定下一个要调度处理的 thread 是哪一个, 线程数据多了无论是资源还是调度都会有点问题

    event-base 是所有的事件都放在一个 thread 上, 然后由这个 thread 来决定下一个要执行的 event 是谁?

    因为 multi-thread 会考虑到每一个 thread 的优先级等等, 而且如果 thread 数目过多那么肯定会影响到具体的调度. 对比 event-base, 切换线程需要切换上下文, 因此肯定会有性能的损耗. 而在 event-base 里面, 所有的 event 的优先级都是一样的, 然后在处理 event 的 handler 里面决定先处理哪一个 event. 但是同样有一个问题就是如果这个 event-base 里面 event 比较多, 那么性能肯定也会下来.而且 event-base 的另一个缺点就是没办法使用到多线程

    所以一般都是采用多线程 + 事件的方式来写网络编程了现在.
    nginx 是, lighttpd 是, 我们开源的 pika( https://github.com/Qihoo360/pika )也是

    我们还实现了这种模型的库 https://github.com/Qihoo360/pink
    UnisandK
        5
    UnisandK  
       2016-08-21 01:33:39 +08:00
    不知道你要的是不是这个,转

    不要让内核做所有繁重的工作。将数据包处理,内存管理和线程调度等从内核中移出来,放到应用程序里,使其处理得更加高效。让 Linux 内核处理控制面,应用程序处理数据面。

    这样,系统在处理上千万的并发连接时, 200 个时钟周期用于数据包处理, 1400 个时钟周期用于程序逻辑。由于内存访问要使用 300 个时钟周期,使用减少代码和减少 cache 丢失的方法进行设计也是关键所在。

    内核中两个基本问题:
    1 ) 连接数 = 线程数 / 进程数。一个数据包进来,内核要遍历所有 10,000 个进程找到处理这个数据包的进程。
    2 ) 连接数 = select 数 / poll 数。同样的可扩展问题,每一个数据包都要遍历 sockets 列表。

    解决方法:为内核打上补丁,使其查找时间为常数。
    1 ) 现在无论线程数量多少,线程的切换时间是常数。
    2 ) 使用 epoll()/IOCompeltionPort 可扩展的系统调用能够在常数时间查找 socket 。
    线程调度仍不能够扩展,所以服务器使用 epoll 的异步编程模型,在 Node 和 Nginx 中都体现了。即使一台较慢的服务器,增加连接数时性能不会急剧下降。
    FrankHB
        6
    FrankHB  
       2016-08-21 04:14:54 +08:00
    @UnisandK 转也留个出处吧……虽然不难找。

    倒是巧合,刚在看 dpdk 的代码。

    不过这个说到底也是根据场景优化的了。而且大概年代的关系看样子挖掘的还不够,比如提到 cache 也没管 cache allocation 什么的新型黑科技……
    UnisandK
        7
    UnisandK  
       2016-08-21 09:58:46 +08:00
    @FrankHB 直接记在笔记软件里的,偷懒没再去专门找出处
    hitmanx
        8
    hitmanx  
       2016-08-21 12:55:47 +08:00 via iPhone
    你是想问异步 io vs 多线程,还是随用随创建线程 vs 线程池?
    kingoldlucky
        9
    kingoldlucky  
       2016-08-21 13:19:36 +08:00
    异步也需要多线程的支持的 所以需要线程池
    SlipStupig
        10
    SlipStupig  
       2016-08-21 16:19:23 +08:00
    @kingoldlucky JS 表示为什么同样是异步,我却没有多线程
    tinyproxy
        11
    tinyproxy  
       2016-08-21 16:45:12 +08:00
    @SlipStupig 我想你说的应该是 nodejs 吧, nodejs 的事件驱动用的是 libuv ,贴个链接好了 https://github.com/libuv/libuv/blob/b12624c13693c4d29ca84b3556eadc9e9c0936a4/src/unix/fsevents.c#L46

    文件异步 IO 一般两种实现方式,最简单的就是线程池,另一种方式请移步 stackoverflow ,我只记得跟系统有关,具体怎么做的忘了。
    qiukun
        12
    qiukun  
       2016-08-21 17:02:32 +08:00
    @fcicq 结果这楼没人理你(
    kingoldlucky
        13
    kingoldlucky  
       2016-08-21 17:18:20 +08:00
    @SlipStupig 只不过把多线程这块交给浏览器去做了而已
    owt5008137
        14
    owt5008137  
       2016-08-21 17:31:27 +08:00 via Android
    @denghongcai 贴的那篇文章已经解释得相当好了。其实这里用线程池也就是扮演一个简单通用的减少阻塞的方案。否则的话针对特定系统,用特定的方法也是可以的。最不济多开几个进程嘛。不过进程数太多会有一定的内存浪费和 CPU 浪费就是了。
    fcicq
        15
    fcicq  
       2016-08-21 17:37:51 +08:00
    @qiukun 没关系. Solaris 系理论也不需要. 只会用 Linux 的人太多.
    pubby
        16
    pubby  
       2016-08-21 18:42:38 +08:00
    @fcicq FreeBSD 还是不错的, zfs 上开 jail 也各种方便。就是基金会有点穷,今年已经去捐了两次了 -_-
    fcicq
        17
    fcicq  
       2016-08-21 19:20:53 +08:00
    @pubby 但是 jail 和 zones 差太远了, 而且 ZFS 的主场当然是 Solaris ... 但是 joyent 被三星收购之后情况也看不清了.
    henglinli
        18
    henglinli  
       2016-08-22 08:52:21 +08:00 via iPhone
    1024cores.net 有讲怎么并行并发等设计的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2726 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 12:25 · PVG 20:25 · LAX 04:25 · JFK 07:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.