论文地址:https://www.usenix.org/conference/osdi16/technical-sessions/presentation/schatzberg
参考资料:http://ytliu.info/blog/2016/12/15/sa-fan-na-xiao-zhen-shang-de-osdi2016/
- 问题(OS):
总之,以往的操作系统要么仅针对一部分的应用程序,要么通过构建通用的软件栈来实现广泛使用。
作者认为,通用软件栈与现有的商用操作系统一样,在性能和通用性之间存在着权衡。为了获得广泛应用程序的高性能,必须消除便于应用程序开发的通用软件,与定制的、有性能优势、但开发工作量大的per-application的软件栈之间的差距。
- 解决方法:
为了消除通用软件之间的差距,本文设计并实现了EbbRT(the Elastic Building Block Runtime)框架,它可以在不影响性能的前提下,减少了构建和维护库操作系统的工作量。
- EbbRT原理:
既允许应用直接控制硬件,又能获得通用操作系统所提供的服务,从而减少开发成本(Arrakis中则将操作系统从数据路径中分离)。EbbRT支持在获得高性能和支持广泛的应用程序的同时,减轻系统开发负担。
- EbbRT评估:
经过评估,EbbRT可以获得比Linux高2.08倍的吞吐量,在将node.js移植到EbbRT时展示了EbbRT的广泛适用性和易用性。
- EbbRT使用到的技术(为了性能和可维护性):
- EbbRT由一组弹性构建块(Ebbs)组件组成,开发人员可以通过扩展、替换或丢弃来构造和部署特定的应用程序。这使得系统具有好的定制性,并促进与关键组件重用。
- EbbRT使用一种轻量级执行环境,它允许应用程序逻辑直接与硬件资源(如内存和设备)交互。
- EbbRT库操作系统与通用操作系统一起运行。允许功能被卸载,以达到兼容性,通过避免新软件的构建来减少维护负担。
- EbbRT库操作系统可以在未修改管理程序的虚拟机上运行。这允许我们在商业云上部署EbbRT应用程序。
- EbbRT使用了许多现代高级的编程技术,这是为了减少软件的复杂性而特意选择的。
- EbbRT的目的:
- 性能专门化(Performance Specialization):允许应用程序在各个级别上高效地专门化系统从而实现高性能。为了达到此目的,使用具有最小硬件抽象的事件驱动执行环境,EbbRT通过提供事件句柄来直接处理硬件中断。此外,Ebb组件模型在性能敏感路径上有足够小的开销,支持编译器优化。
- 广泛的适用性(Broad Applicability):EbbRT在设计和实现时考虑到对丰富的现有库和复杂的运行管理的支持,这正是应用程序依赖的。使用异构分布式架构MultiLibOS,EbbRT库操作系统与通用操作系统一起运行,可以透明地卸载功能。
- 便于开发(Ease of Development):EbbRT利用现代语言技术简化了编写系统软件的工作,而Ebb模型则提供了封装现有系统组件的抽象。通过在EbbRT库操作系统和通用操作系统之间进行功能卸载,可以降低移植现有应用程序的困难。
- EbbRT的架构和设计:
- 异构分布式系统架构:作为服务的基础设施使单个应用程序能够在独立的网络内的多台机器上部署。应用程序可以部署在异构的专用库OSs(本地运行时)和通用操作系统(托管运行时)上。
- 模块化的系统结构:EbbRT应用程序几乎完全由弹性构建块(Ebbs)的对象组成。Ebbs是分布式的、多核碎片的对象,Ebbs在本地和托管运行时共享。
- 非抢占式和事件驱动的执行模型:在本机运行时,每个核(core)都有一个事件循环,它将外部和软件生成的事件分派到注册处理程序。这使得在硬件上提供了低开销,允许直接将应用程序软件映射到设备中断,从而避免了调度决策或保护域交换的成本。在托管库中,通过提供事件循环(使用poll或select)来提供和本机类似的环境,虽然托管环境的效率和本地环境不能相比,但是提供了兼容的环境,使得软件库可以在两个运行时重用。
- EbbRT的异构分布式架构:
- EbbRT被实现为一个轻量级的运行时可启动库和一个用户级别的库(可以链接到通用操作系统的进程)。将前者作为本地运行时(the native runtime),后者作为托管运行时(the hosted runtime)。
- 本地运行时允许将应用程序软件直接写入硬件接口,不受通用操作系统中常规接口和保护机制的限制。它设置单一的地址空间、基本系统功能并调用应用程序入口点,所有这些在最高权限级别运行。
- 托管运行用户空间库可以实现EbbRT应用程序和遗留软件的集成。从而使得本机库OSs摆脱对遗留接口处理的负担。而且通过与托管环境交互可以卸载功能。用户可以通过托管运行时与EbbRT应用程序进行交互,因为它们将处理通用操作系统的任何其他过程,而本机运行时支持应用程序的性能关键部分。
- 系统分成两个部分,VM0内运行通用商用操作系统,VM1和VM2内运行native LibOS。
- VM1和VM2内的LibOS设置了一个唯一的地址空间,提供必需的系统功能(比如内存分配、网络等)允许应用直接与硬件交互;如果需要使用通用操作系统的功能,EbbRT可以通过Offloading的方法将请求交给VM0内的通用操作系统完成。
- EbbRT的实现——事件驱动:
- 在托管环境中,使用Boost ASIO库与系统api的接口;在原生环境中,事件驱动API直接在硬件接口上实现。
- 当本地环境引导时,每个核心(core)的事件循环被初始化。事件是非抢占式的,通常由硬件中断生成。
- 为了防止中断饥饿,当事件完成EventManager:a.启用禁用中断,处理任何未决的中断,b.分派一个单一的合成事件,c.调用所有的IdleHandlers,d.允许中断和停止。
- EventManager实现很简单,但它提供了足够的功能来实现动态行为:a.如果中断率超过一个可配置的阈值,则驱动程序禁用接收中断,并安装一个处理接收包的IdleHandler;b.当包到达率低于可配置阈值时,驱动程序重新启用接收中断并禁用空闲处理程序IdleHandler,返回到中断驱动的包处理。
- EbbRT的实现——弹性构建块Ebbs:
- Ebbs隐藏对象的分布式或并行性质,可以扩展或替换为自定义。Ebbs提供了一个使用标准c++类定义的接口。
- Ebbs的每一个实例都有一个系统范围的惟一EbbId。软件调用Ebbs时,将EbbId转换为EbbRef,该EbbRef可以被解引用为每个核心的代表,这是对底层c++类实例的引用。
- 为了在应用程序中的任何机器或核心上调用Ebbs,有必要对每个核心的代表进行初始化,以减少对Ebbs的初始化开销。Ebbs可能需要在机器或其他机器上与Ebbs进行沟通。EbbRT提供了支持分布式数据存储和消息传递服务的核心Ebbs。这些工具可以跨EbbRT本地和托管实例之间通信。
- Ebb模块化既灵活又高效,使它们适合于高性能组件。Ebb的快速路径代价fast-path cost 是一个可预测的、无条件的分支,而不是普通的c++对象的dereference。此外,本文使用静态分派(EbbRef被代表的类型模板化)支持编译优化,如函数内联。
- EbbRT的实现——内存管理:
- 最低级别的分配器PageAllocator,可分配内存中两个大小的页,使用buddy-allocator,单NUMA节点实现。
- 上面是SlabAllocator,用来分派固定大小的对象,SlabAllocator使用单核和单NUMA节点代表来存储释放对象list和部分分配的页。
- GeneralPurposeAllocator通过malloc调用,使用多个SlabAllocator来实现,每个SlabAllocator用于分配不同大小的页。当请求分配的页大于SlabAllocator上限时,GeneralPurposeAllocator会分配从VMemAllocator映射的虚拟内存区域,并由PageAllocator提供支持。
- EbbRT的实现——内存管理优点:
首先,使用Ebbs来创建多核可伸缩性的每个核心(core)代表,并提供封装便于替换不同的分配器。
其次,缺乏抢占使得可以使用没有同步的每个核心代理。
第三,库OS设计支持系统组件和应用程序组件之间的紧密协作——大多数的分配通过实体映射物理内存(identity mapped physical memory)实现,应用程序能够直接管理虚拟内存区域,并实现与设备代码的零拷贝交互。
- EbbRT的实现——Lambdas and Futures原型:
针对事件驱动编程和异常处理,降低复杂性以减轻开发负担。
- EbbRT的实现——网络栈Network Stack:
为本机环境实现了新的网络堆栈,提供IPv4、UDP / TCP和DHCP功能,以便为应用程序提供一个事件驱动的接口,最小化多核同步,并支持零拷贝。
- EbbRT的评估——微型数据集:
- 内存分配器:目的是确定Ebb机制的不影响高性能组件的构建,从结果看来EbbRT在内存分配方面和glibc相比有一定竞争力。
- 网络栈:a.对于少量消息,EbbRT从硬件到应用程序的短路径通过NetPIPE实现了对延迟40%的改进。这个说明了非抢占式事件驱动执行模型和零拷贝指令路径的好处。b.对于大量消息,因为系统管理程序的原因两个系统都必须接收数据包的上一个拷贝,但是EbbRT没有进一步的拷贝,而Linux必须复制到用户空间,然后再一次传输。
- EbbRT的评估——分布式缓存(memcached):
- 单核中,EbbRT能够达到Linux VM的1.88×的吞吐量,优于本地Linux吞吐量的1.15×。
- 六核中,EbbRT能够达到比Linux VM的2.08×更高的的吞吐量,优于本地Linux吞吐量的1.50×。
- EbbRT的评估——Node.js:
- 与memcached相比,Node.js使用了更多操作系统的特性,包括虚拟内存映射、文件I / O、定时计时器等。EbbRT通过自定义工具链分布,而不需要修改现有Node.js。
- V8 JavaScript Benchmark(谷歌的JavaScript引擎):在每个基准测试中,EbbRT优于Linux VM。性能优势的来源:首先,EbbRT的IPC效率稍微好一点;Linux VM效率低的原因是必须执行更多的指令。其次,在Linux上与系统管理程序和内核的额外交互增加了工作集的大小,导致LLC的访问增加了33%;而EbbRT简化了执行路径。第三,Linux会发生相比EbbRT近9×的TLB不命中。我们将我们的TLB效率归因于我们在整个系统中使用大页面。
- Node.js Webserver:结果表明node.js服务器端应用程序通过简单地运行在EbbRT之上,可以获得即时的性能优势。因为没有上下文切换或抢占,支持更大的网络性能。