随着多核处理器成为主流,应用开发人员对于如何编写高伸缩性的应用以利用底层硬 件的优势这个问题面临巨大的压力。此外,遗留系统不得不移植到新的架构上。保证应用 伸缩性的一种有效方式是使用高伸缩性组件构建应用。举例来说,在各种应用中, java.util.concurrent.ConcurrentHashMap可以替代同步的HashTable,使应用伸缩性更 好。因此,向应用直接提供一套高伸缩性构造块以引入并行是非常有用的。
我们创建了一套高伸缩性并发Java组件作为Amin库项目的一部分。在本文中,我们将 介绍一些创建该开源库的想法。
概述
作为软件工程师,我们不得不并行我们的应用使它们在多核机器上很好的伸缩。一种 并行方式是把它们分成若干子任务,其中每一个子任务与应用的其他子任务通信和同步。 这通常被称为基于任务的并发。我们可以基于子任务的通信模式将应用分类。
尴尬式并行——应用的子任务从不或者很少与其他子任务通信。通常情况下,每一个 任务只处理自己的私有数据。一些例子包括:
蒙特卡洛模拟程序
快速排序程序,使用fork/join模式很容易实现并发。当我们处理尴尬式并行应用时容 易得到很好的伸缩性。
粗粒度和细粒度式并行——这些应用的子任务需要互相通信。根据子任务之间的通信 频率可以把程序分为粗粒度和细粒度并行。一个例子是生产者/消费者问题。生产者产生 驱动消费者的数据。从生产者到消费者的数据发送需要通信。相比尴尬式并行应用,处理 子任务频繁交互的应用较难得到良好的伸缩性。
经过为伸缩性而优化的组件非常有益于解决这些困难问题。举例来说,如果存在一个 高伸缩性队列组件,那么实现生产者/消费者伸缩性相对容易些。本文中,我们提供了若 干通用技术提高软件组件的伸缩性。
针对伸缩性的分析
应用分析是开发过程的重要方面。分析是为了了解应用的运行特征。分析数据经常被 用于提高应用的性能和伸缩性。大多数分析器遵从一个简单的执行模式,其中有一个配置 阶段。在该阶段,根据信息获取的类型,会配置不同层次的计算堆栈。硬件计数器可以被 用来监控硬件事件。操作系统可以通过配置各种操作系统事件来监控。如果在计算层次中 还有虚拟机,那么需要配置以访问虚拟机的事件。最后,应用需要配置以得到真实应用的 事件。优秀的分析器能够在不要求应用重新编译的情况下完成这些配置。大多数分析器通 常都配置虚拟机和应用层。应用在配置之后运行时,会生成跟踪信息,例如函数运行时间 、资源使用情况、硬件性能参数、锁使用、系统时间、用户时间等等。不同的分析器会在 把跟踪信息输出到文件系统前做一些计算。最后,分析器会通过显示界面可视化这些数据 。
用于并发应用的分析器需要提供有关线程、锁竞争和同步点的详细信息。我们使用了 下面一些分析器作为Amino性能分析:
Java锁监控器(Java Lock Monitor)——Java开发人员使用该工具分析应用中锁的使 用情况。在运行时,监控组件收集各种锁数据用于发现锁竞争。该工具能够通过表格展示 详细的锁和竞争信息。IBM Java Lock Analyzer (JLA)是另一个提供锁信息的工具。它与 JLA类似,只不是通过图形界面显示缩合竞争数据。两个工具都支持x86和Power平台。
THOR ——该工具用于详细分析Java应用的性能。它能够深入分析完整的执行栈,从硬 件到应用层。信息来自于栈的四个层面——硬件、操作系统、JVM和应用。用户可以看到 锁竞争的信息以及对应的代码、瓶颈、多核之间的线程迁移和竞争导致的性能下降。该工 具支持x86和Power平台。
AIX性能工具——IBM的AIX操作系统自带一套底层的性能分析和调试工具。其中包括:
Simple Performance Lock Analysis Tool (SPLAT) ——该工具是AIX系统上的一个锁 分析工具,可以通过命令行运行,用于分析各种内核级的锁。同时,它也可以分析和显示 用户级锁(读/写和mutex)的竞争。应用必须启用跟踪选项,SPLAT需要用到这些跟踪数 据。
XProfiler——该分析工具基于X—Windows,用于C语言应用的函数级分析,能够显示 在用户代码中计算敏感的函数。如果要使用XProfiler,代码需要使用特殊的标志(-pg选 项)编译。
prof、 tprof和gprofncbr——各种prof命令都可以用于分析用户应用。prof命令能够 得到所有应用中的外部符号和函数。gprof是 prof的超集,可以获得应用的调用关系图。 最后,tprof用于得到应用的宏观和微观的分析信息。tprof能够得到各个指令、子程序、 线程、进程的计时数据,还有用户模式函数、库函数、Java类、Java方法、内核函数、内 核扩展等的处理器使用情况。