深入理解SPDK 之二: 消息和无锁队列

并发理论

期望: 随着硬件的线性增加,性能也线性增加;

  • 传统 锁 的优点:

    1. 无锁 到有锁 扩展的方便;
    2. 锁直接加在共享数据的前面;
  • 缺点:
    随着系统内线程的增加,数据和临界段的竞争越来越激烈,而且多个线程可能处于不同物理core,频繁竞争导致剧烈的L1 cache 失效。
  • SPDK的做法:各管各妈;你看我娃

** 各管各妈

SPDK takes a different approach altogether. Instead of placing shared data in a global location that all threads access after acquiring a lock, SPDK will often assign that data to a single thread.

** 你看我娃
When other threads want to access the data, they pass a message to the owning thread to perform the operation on their behalf.

消息传递架构

  • libspdk_thread.a: SPDK‘s thread abstraction, located in;
  • spdk_thread: 线程执行的抽象
  • spdk_poller: 执行的线程内被周期执行的函数的抽象
  • spdk_allocate_thread() :分配spdk 线程
    参数是三个函数指针: 給其他线程提供的为即将创建的线程传递参数的函数指针;給其他线程提供的启动当前线程poller的函数接口; 停止当前线程poller的函数接口

    spdk_io_device: 之前的含义是 支持无锁多队列IO请求的设备,后来泛指is any pointer, whose uniqueness is predicated only on its memory address

    spdk_io_channel: 之前的含义是指 給特别为上面IO设备分配的线程;现在是指和某个spdk_io_device绑定的per-thread的上下文context.

spdk 事件框架

现在直接调用 spdk_app_start() 为你打理所有下面的准备工作:

  • spawning one thread per core,
  • pinning each thread to a unique core,
  • allocating lockless rings between the threads for message passing

原文地址:http://blog.51cto.com/xiamachao/2350007

时间: 2024-10-09 20:00:51

深入理解SPDK 之二: 消息和无锁队列的相关文章

并发无锁队列学习之二【单生产者单消费者】

1.前言 最近工作比较忙,加班较多,每天晚上回到家10点多了.我不知道自己还能坚持多久,既然选择了就要做到最好.写博客的少了.总觉得少了点什么,需要继续学习.今天继续上个开篇写,介绍单生产者单消费者模型的队列.根据写入队列的内容是定长还是变长,分为单生产者单消费者定长队列和单生产者单消费者变长队列两种.单生产者单消费者模型的队列操作过程是不需要进行加锁的.生产者通过写索引控制入队操作,消费者通过读索引控制出队列操作.二者相互之间对索引是独享,不存在竞争关系.如下图所示: 2.单生产者单消费者定长

DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了

[概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天晚上,DEMO基本成型,今天再加入了QWorkers来做逻辑处理进程,进一步使得逻辑处理进程更加方便和高效.今天特意写篇blog来记录我的心得与大家分享. [功能实现说明] 沿用上次的草图 目前DEMO图上的功能都已经实现.下面谈谈各部分的实现. 通信服务, 由DIOCP实现,担当与客户端的通信工作

并发无锁队列

1.前言 队列在计算机中非常重要的一种数据结构,尤其在操作系统中.队列典型的特征是先进先出(FIFO),符合流水线业务流程.在进程间通信.网络通信之间经常采用队列做缓存,缓解数据处理压力.结合自己在工作中遇到的队列问题,总结一下对不同场景下的队列实现.根据操作队列的场景分为:单生产者--单消费者.多生产者--单消费者.单生产者--多消费者.多生产者--多消费者四大模型.其实后面三种的队列,可以归纳为一种多对多.根据队列中数据分为:队列中的数据是定长的.队列中的数据是变长的. 2.队列操作模型 (

folly无锁队列正确性说明

folly无锁队列是facebook开源的一个无所队列,使用的是单向链表,通过compare_exchange语句实现的多生产多消费的队列,我曾经花了比较多的时间学习memory_order的说明,对release-acquire语义,自认为还是比较了解.如果一个atomic对象使用std::memory_order_release进行写操作,而另外一个线程使用std::memory_order_acquire进行读操作,那么这两个线程之间形成同步关系.std::memory_order_rel

基于无锁队列和c++11的高性能线程池

基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上 标签: <无> 代码片段(6)[全屏查看所有代码] 1. [代码]lckfree.h ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 // lckfree.h //

【DPDK】【ring】从DPDK的ring来看x86无锁队列的实现

[前言] 队列是众多数据结构中最常见的一种之一.曾经有人和我说过这么一句话,叫做“程序等于数据结构+算法”.因此在设计模块.写代码时,队列常常作为一个很常见的结构出现在模块设计中.DPDK不仅是一个加速网络IO的框架,其内部还提供众多的功能组件,rte_ring就是DPDK内部提供的一种无锁队列,本篇文章将从使用的角度出发阐述DPDK的ring怎么用?在怎么用的角度上再来阐述ring无锁的实现,最后将探讨实现无锁队列的关键以及在不通平台上如何实现,本文将会探讨x86平台下无锁队列的实现. 权当抛

基于循环数组的无锁队列

在之前的两篇博客(线程安全的无锁RingBuffer的实现,多个写线程一个读线程的无锁队列实现)中,分别写了在只有一个读线程.一个写线程的情况下,以及只有一个写线程.两个读线程的情况下,不采用加锁技术,甚至原子运算的循环队列的实现.但是,在其他的情况下,我们也需要尽可能高效的线程安全的队列的实现.本文实现了一种基于循环数组和原子运算的无锁队列.采用原子运算(compare and swap)而不是加锁同步,可以很大的提高运行效率.之所以用循环数组,是因为这样在使用过程中不需要反复开辟内存空间,可

多个写线程一个读线程的无锁队列实现

在之前的一篇博客中,写了一个在特殊情况下,也就是只有一个读线程和一个写线程的情况下,的无锁队列的实现.其中甚至都没有利用特殊的原子加减操作,只是普通的运算.这样做的原因是,即使是特殊的原子加减操作,也比普通的加减运算复杂度高很多.因此文中的实现方法可以达到很高的运行效率. 但是,有的情况下并不是只有一个读线程和一个写线程.越是一般化的实现,支持的情况越多,但是往往损失的性能也越多.作者看到过一个实现(http://www.oschina.net/code/snippet_732357_13465

环形无锁队列

环形无锁队列 Table of Contents 1 环形无锁队列的实现 2 死锁及饥饿 3 一些优化 1 环形无锁队列的实现 数据结构定义: template class LockFreeQueue { private: ElementT *mArray; int mCapacity; int mFront; int mTail; } 由于出队操作是在队首进行,入队操作是在队尾进行,因此,我们可以尝试用mFront和mTail来实现多个线程之间的协调.这其中会用到CAS操作: 入队操作伪码: