论文部分内容阅读
NUMA(Non-Uniform Memory Access,非一致性内存访问)架构的出现和普及克服了SMP(Symmetric Multi-Processor,对称多处理器)架构在扩展性方面的局限性,使得单台机器上能够容纳更多的计算核心,同时NUMA架构中物理内存的分布式设计也使得访存操作具有非一致性时延的特征。一方面,更多的计算核心使得共享内存的高并发应用能够生成更多的线程并将其分布到所有的核上来充分利用多核资源提高系统吞吐率;另一方面,内存及缓存的非一致性访问特性也使得挖掘和利用共享数据的局部性成为多线程应用获取更高性能的关键。对于极易成为系统性能和扩展性瓶颈的锁来说,线程数的增多和访存的非一致性特征都对其的设计和改进提出了新的挑战。基于队列的锁,尤其是MCS锁1和CLH锁2,由于其在性能、可扩展性和公平性方面的良好表现,广泛应用于很多锁集中的高性能系统。这些基于队列的锁通过将参与锁竞争的线程按照其请求锁的顺序排成一个先入先出(FIFO,First In First Out)的队列,每个线程在在队列中各自的内存位置自旋等待锁并且按照其在队列中的顺序依次进入关键区域。FIFO的队列保证了基于队列的锁的公平性,而每个线程在不同的内存位置自旋使其能提供良好的性能和可扩展性。在NUMA架构的机器上,为了充分利用多核资源,竞争同一个锁的线程不可避免地要分布在不同的NUMA节点(node)上,从而产生了跨NUMA节点的锁传递,而访存非一致性特征使得跨节点的锁传递时延通常远大于同一节点内的锁传递时延。传统的基于队列的锁由于不能感知到底层NUMA的特征并且要保持FIFO的锁传递顺序,所以产生了大量的跨节点锁传递,进而产生性能严重下降的问题。为了解决基于队列的锁在NUMA架构下出现的性能下降问题,NUMA感知的基于队列的层级锁(以下简称层级锁),例如Cohort锁、HMCS(Hierarchical MCS)锁,改变了基于队列的层级锁全局FIFO的锁传递顺序,通过NUMA感知的锁调度使得锁尽可能地在同一个NUMA节点内的线程间按FIFO的顺序传递,只有当当前节点内没有请求者或者锁在当前节点内的传递次数超过一定限度时才将其传给其他节点内的线程,从而减少锁的跨节点传递比例,改善其在NUMA架构下的性能。由于层级锁高性能的获取要依赖于线程在NUMA节点上的分布,因此线程的放置策略对于其最终能达到的性能改善程度有很大影响。现有层级锁中线程通常会被紧凑(Compact)地放置在尽可能少的节点上来减少锁的跨节点传递,这种线程放置策略有利于层级锁挖掘和利用局部性获取更高的性能,但是层级锁优先本地传递的传递机制使得其不能保证长期公平性。除此以外,将线程平均(Even)放置在所有节点上理论上能够保证层级锁的长期公平性,但是由于线程分布较为分散所以在锁的竞争不是很激烈的时候相比紧凑放置又会存在严重的性能下降问题。现有的简单单一的线程放置策略难以在竞争状况复杂多变的应用中同时保证层级锁的高性能和长期公平性,而对于公有云等应用场景来说,性能和公平性是缺一不可的。在这篇文章中我们提出了一种竞争感知的混合线程放置框架(Contention-Aware Hybrid Threads Placement Framework,以下简称CAH)。在CAH中我们提出了两种新的线程放置策略:有轮换的紧凑放置(Compact With Shift,以下简称CWS)和加强的平均放置(Enhanced Even,以下简称EE)。CWS在紧凑放置的基础上引入了一种轻量级的线程轮换(shift)机制来以极小的性能损失为代价抹平线程之间的吞吐率差异从而使得其能够保证层级锁的长期公平性;EE在平均放置的基础上限制其所能使用的节点数为能放下所有线程的最小节点数而不是所有节点从而在保证长期公平性的前提下尽可能地提高性能。CAH本质上是基于CWS和EE的,能根据应用中层级锁的竞争状况动态调整线程放置策略的一种混合解决方案。它通过定期地取样每个线程的锁相关的事件来评估当前层级锁的竞争状况,并且结合当前的线程数量及其分布来调节线程的放置策略,在层级锁的竞争强度足够高的时候应用EE策略,否则应用CWS策略,从而不论锁的竞争强度如何变化都能以最小的额外代价来同时保证吞吐率和长期公平性。