美文网首页
Disruptor-03 Ringbuffer的高性能设计

Disruptor-03 Ringbuffer的高性能设计

作者: rock_fish | 来源:发表于2020-09-10 10:25 被阅读0次

    Ringbuffer数据结构

    • 一维数组 构成 逻辑环
    image.png

    初步解读:

    1. 数组是连续的内存空间,连续内存空间的读写效率较高
    2. 仅申请一次空间,逻辑上构成环形结构,复用内存空间.大大减少了内存空间的申请和释放动作.
    3. FIFO,读取数据时,可以实现非常好的批处理.

    生产者线程 和 消费者线程之间通信的桥梁(共享变量)

    作为临界区资源,必然会有共享变量,为了保证线程安全所需要解决的问题:

    • 变量修改的可见性
    • 变量修改的互斥性

    通常的操作是:

    1. 原子性修改.(循环+CAS) ,性能高
    2. 修改动作串行化, 性能低

    知道怎么操作后,还需要进一步思考以下几个问题:

    • 串行化,可见性的粒度怎样
    • 原子性的修改,改的是什么?
    • 可见性是什么可见?

    线程安全问题的关键也在于"变",对于这个队列来说变得部分需要我们必须关注的是:

    1. 生产者:消息待放置的位置
    2. 消费者:可消费的消息的位置.

    特别要留意: ringbuffer数组大小是固定的,没有变化.

    ringbuffer中的循环+cas操作

    对上边变的部分,从源码中看可以知道,是通过循环+cas操作来保证数据的安全性的

    变更可见性以及隔离控制(缓存行填充 难度中)

    生产者往某个元素中放置了数据后,消费者要能知道(可见),
    消费者消费完了某个位置的元素后,生产者要能知道(可见),

    以面向对象的思想来考虑,我们将这些信息作为属性放置到RingBuffer这个对象中,生产者,消费者在不同线程中,通过RingBuffer这个对象的相关属性获取这些位置信息

    那么这个RingBuffer对象的内存,在线程间共享,其属性变量(内存中的数据)的修改要保证线程间可见.

    这个线程间到底是什么样的线程之间??? 运行在不同cpu核的线程之间?不仅仅是这样,这里的关键是要梳理一下计算机组成原理以及操作系统的一些知识.

    思考一个问题:Netty里设置线程池中线程数目的时候,通常设置为多少,有么有一个参考基数? 答案里有一个CPU核数.那么CPU核与线程之间什么关系呢?

    CPU的线程数概念仅仅只针对Intel的CPU才有用,因为它是通过Intel超线程技术来实现的,最早应用在Pentium4上。如果没有超线程技术,一个CPU核心对应一个线程。所以,对于AMD的CPU来说,只有核心数的概念,没有线程数的概念。

    在没有超线程这种情况下,CPU的核数也就是并行运行的线程数.

    CPU怎么操作内存中的数据?

    为了弥补CPU和内存两者之间的速度差异,充分使用把CPU的高性能,而不是让它在那儿空转等待,现代CPU架构中引入了高速缓存,分为L1 cache,L2 cache和L3 cache

    image.png

    内存中的指令、数据,会被加载到高速缓存,在95%的情况下,CPU都只需要访问L1-L3 Cache,而不是直接 由CPU访问内存去拿。

    image.png

    MESI

    缓存一致性问题,操作系统通过MESI这么个协议,达到一个最终一致性,可是对应用程序来说在时效性上没有保证.

    内存屏障

    为了在时效性上有保证,我们在程序中明确的要求时效性,通过给屏障指令.

    感谢你们


    001-CPU多级缓存架构

    http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html

    相关文章

      网友评论

          本文标题:Disruptor-03 Ringbuffer的高性能设计

          本文链接:https://www.haomeiwen.com/subject/rfqyzhtx.html