CN101630268B - 同步优化的方法及设备 - Google Patents
同步优化的方法及设备 Download PDFInfo
- Publication number
- CN101630268B CN101630268B CN2009101629791A CN200910162979A CN101630268B CN 101630268 B CN101630268 B CN 101630268B CN 2009101629791 A CN2009101629791 A CN 2009101629791A CN 200910162979 A CN200910162979 A CN 200910162979A CN 101630268 B CN101630268 B CN 101630268B
- Authority
- CN
- China
- Prior art keywords
- synchronous
- invocation
- point
- version
- synchronization object
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Expired - Fee Related
Links
Images
Abstract
本发明提出了一种同步优化方法及设备。该方法包括以下步骤:对被编译方法进行静态程序分析,根据分析结果确定所述被编译方法中无须对同步对象进行同步操作的同步方法调用点,并对所述同步方法调用点进行标记;根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码;根据所述标记的同步方法调用点执行所述本地代码。本发明所提出的同步优化的方法及设备具有高度的灵活性和良好的可扩展性。
Description
技术领域
本发明涉及计算机技术,更具体地涉及同步优化技术。
背景技术
Java是一种在语言级别上支持多线程编程的程序设计语言,它提供基于监视器机制的同步方法和同步语句来用于线程间的同步。Java中每个对象有一个对应的监视器,线程可以通过同步方法调用和同步语句对某对象进行加锁/解锁,每次只有一个线程可以持有某监视器上的锁,其他试图对这个监视器加锁的线程都将被阻塞直到它们获得这个监视器上的锁。
为了保证多线程安全,Java标准库中的很多类都必须设计成线程安全的,也就是在访问共享数据时需要添加同步操作,如java.util.Vector类、java.util.Hashtable类等,应用程序可以在多线程环境中简单安全地使用这些库所提供的功能。除了可以通过调用Java标准库中各个线程安全的类和方法外,程序员还可以自己利用同步方法和同步语句来实现多线程对共享数据的互斥访问,以确保程序的正确性。虽然Java中的同步机制能方便地保证多线程的安全,但是也给多线程程序的运行带来非常大的开销。据研究表明,同步开销通常占总执行时间的5%-10%;在对Marmot(一种Java优化编译器)的测试中,5个中等大小的单线程程序在同步上花费了26%~60%的时间。由此,开展同步优化(synchronization optimization)是十分重要的。
同步优化旨在降低同步操作的开销,提高程序的整体性能。为了减少同步操作的开销,一些方法直接改良同步原语的实现,比如,瘦锁(thin lock)技术和锁保留(lock reservation)技术。还有一些方法利用静态程序分析技术自动分析并消除不必要的同步操作,比如,锁取消(lock elision)技术和锁粗化(lock coarsening,lock coalescence)技术。锁取消技术利用逃逸分析(escapeanalysis)技术确定出线程局部(thread-local)的对象,然后取消这些对象上的同步操作。锁粗化技术合并某些作用于同一同步对象上的多个同步操作,合并之后会导致被同步的代码区域范围增大,这在多线程的环境下会引起程序并发度的下降,尤其是在线程数目非常多的情况下,对并发度的影响会更加明显。
因此目前需要一种具有良好的灵活性和可扩展性并对并发度具有较小影响的同步优化的方案。
发明内容
为了解决上述问题之一,本发明提出了一种同步优化方法,包括以下步骤:对被编译方法进行静态程序分析,根据分析结果确定所述被编译方法中无须对同步对象进行同步操作的同步方法调用点,并对所述同步方法调用点进行标记;根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码;根据所述标记的同步方法调用点执行所述本地代码。
根据本发明的实施例,所述对被编译方法进行静态程序分析,确定无须对同步对象进行同步操作的同步方法调用点的步骤包括:合并作用于同一个同步对象上的相邻同步区域和/或嵌套同步区域,将包含在所述合并后的同步区域内的同步方法调用点确定为所述冗余同步方法调用点。
根据本发明的实施例,所述对被编译方法进行静态程序分析,确定无须对同步对象进行同步操作的同步方法调用点的步骤包括:根据对象是否在多个线程间共享确定对所述对象的同步方法调用点是否是无须对同步对象进行同步操作的同步方法调用点。
根据本发明的实施例,根据对象是否在多个线程间共享确定对所述对象的同步方法调用点是否是无须对同步对象进行同步操作的同步方法调用点的步骤包括:如果所述对象只在创建所述对象的线程中被访问,则将作用于所述对象的同步方法调用点确定为所述无须对同步对象进行同步操作的同步方法调用点。
根据本发明的实施例,根据所述标记的同步方法调用点为同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码的步骤包括:根据所述标记的同步方法调用点为所述同步方法编译生成所述同步方法的普通版本和所述同步方法的非同步版本,其中所述同步方法的非同步版本包括忽略对所述同步方法的同步对象上的同步操作而生成的本地代码。
根据本发明的实施例,根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码的步骤包括:根据所述标记的同步方法调用点为所述同步方法编译生成所述同步方法的分支版本,并在所述被标记的同步方法调用点前插入一条设置标记信息的指令。其中所述同步方法的分支版本通过以下步骤获得:在所述同步方法入口处插入获得标记信息的指令和清除标记的指令;在作用在所述同步方法的同步对象上的同步操作之前插入分支指令,所述分支指令判断获得的标记信息,若所述标记信息为真,则跳转到所述同步操作之后,如果所述标记信息为假,则执行所述同步操作。
根据本发明的实施例,执行所述本地代码的步骤包括:当执行同步方法调用点时,如果所述同步方法调用点为标记的同步方法调用点,则调用所述非同步版本的本地代码,如果所述同步方法调用点为没有标记的同步方法调用点,则调用所述普通版本的本地代码。
根据本发明的实施例,执行所述本地代码的步骤包括:当执行到同步方法调用点时,根据所述同步方法调用点前设置的标记信息指令调用所述分支版本的本地代码。
根据本发明的实施例,对被编译方法进行静态程序分析中出现以下情况之一时不进行将同步方法调用点确定为无须对同步对象进行同步操作的同步方法调用点的步骤:作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含作用于其他对象上的同步操作;所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含访问易变volatile数据的操作;所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含静态无法解析的访问或方法调用;所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含循环;所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含锁定次数不一致的操作,所述锁定次数不一致的操作所属的控制流图CFG节点的各个前驱节点被锁定的次数不同。
本发明还提出了一种同步优化设备,包括分析模块、编译模块和执行模块。其中,所述分析模块用于对被编译方法进行静态程序分析,根据分析结果确定所述被编译方法中无须对同步对象进行同步操作的同步方法调用点,并对所述同步方法调用点进行标记;所述编译模块用于根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码;所述执行模块用于根据所述标记的同步方法调用点执行所述本地代码。
本发明所提出的同步优化的方法及设备具有高度的灵活性和良好的可扩展性。
附图说明
本发明上述的和/或附加的方面和优点从下面结合附图对实施例的描述中将变得明显和容易理解,其中:
图1是根据本发明的一个实施例的同步优化方法的流程图;
图2是根据本发明的一个实施例的同步方法的代码版本的示意图;
图3是根据本发明的一个实施例的双版本算法示意图;
图4是根据本发明的一个实施例的分支版本算法示意图;
图5是根据本发明的一个实施例的同步优化设备的示意图;
图6是根据本发明的一个实施例的未使用方法内联时的吞吐量对比示意图;
图7是根据本发明的一个实施例的使用方法内联后的吞吐量对比示意图。
具体实施方式
下面详细描述本发明的实施例,所述实施例的示例在附图中示出。下面通过参考附图描述的实施例是示例性的,仅用于解释本发明,而不能解释为对本发明的限制。
同步优化在改善应用程序的同步开销的同时,也耗费了较大的程序分析开销。为了权衡过程间同步优化的开销和收益,本发明对同步方法的调用点进行优化,因为:1)在实际的代码中,同步方法调用所花的同步开销在总同步开销中占很大比重;2)对同步方法的调用点的分析相对比较简单。
作为本发明的一个实施例,一个static的同步方法(即类同步方法)的同步对象是指该方法所属的类对应的Class对象;一个非static同步方法(即实例同步方法)的同步对象是指该方法的this对象;一个同步语句的同步对象是指在该同步语句中的圆括号内显式指定的对象,即同步语句synchronized(O){...}中的O。
在字节码级,语言级的同步语句变换成以monitorenter(加锁,即获得同步对象上的监视器)指令开始、以monitorexit(解锁,即释放相应的监视器)指令结束的指令序列。同步方法在字节码级则是在其常量池条目中设置有同步标志ACC_SYNCRONIZED,方法调用指令会检查这个标志,当调用一个设置有该标志的方法时(即调用同步方法时),当前线程将获取监视器,然后调用执行方法体本身,不论方法调用是正常结束还是异常结束都要释放这个监视器。为便于描述,本发明中统一用lock(O)和unlock(O)分别表示对对象O进行加锁和解锁。
作为本发明的一个实施例,作用于对象O的一个同步区域是指从对该对象加锁到对该对象解锁的一段连续执行的指令序列形成的代码区域。
本发明提出一种优化同步方法及其调用点的同步方法优化框架,其基本思想是分析出无须对同步对象进行同步的同步方法调用点,将其改成对该同步方法的非同步版本的调用,或者是设置标记信息并调用该同步方法的分支版本。该框架由程序分析、编译和执行3个阶段组成。下面分别简述这3个阶段。
如图1所示为根据本发明的一个实施例的同步优化方法100的流程图。如图所示,该方法100包括以下步骤:
S101:对被编译方法进行静态程序分析,根据分析结果确定被编译方法中无须对同步对象进行同步操作的同步方法调用点,并对该同步方法调用点进行标记。该步骤或称程序分析阶段。
作为本发明的一个实施例,当编译器对Java程序中的一个方法进行编译时,对被编译方法进行静态程序分析,根据分析结果确定被编译方法中的哪些同步方法调用点在其同步对象上的同步操作是冗余的,并对这些同步方法调用点进行标记。
作为本发明的一个实施例,在该阶段,可以采用不同的程序分析技术来对被编译方法进行分析以确定哪些同步方法调用点需要标记,这些分析技术可以基于锁粗化技术,也可以基于逃逸分析技术,或者是其他技术。
作为本发明的一个实施例,程序分析阶段可以采用基于锁粗化的程序分析。
作为本发明的一个实施例,基于锁粗化的同步优化的主要思想是:如果线程T在获得锁而未释放该锁期间又获取同一个锁,那么第2个锁获取操作是不必要的;如果线程T连续多次获得并释放同一个锁,那么可以将这些锁获取和锁释放操作合并成一对,以减少锁操作的数量。
作为本发明的一个实施例,基于锁粗化技术分析识别无须同步的同步方法调用点的主要方法包括:合并作用于同一个同步对象上的相邻同步区域或嵌套同步区域以减少同步操作的数量。如果把同步方法调用看作是一种特殊的同步区域并让它与相邻的同步区域或者是包含它的同步区域相合并,那么包含在合并后的同步区域内的同步方法调用点在其同步对象上的同步操作是冗余的,从而可以对这些调用点进行标记。
作为本发明的一个实施例,程序分析阶段可以采用基于逃逸分析的程序分析。
作为本发明的一个实施例,基于逃逸分析的同步优化的主要思想是:如果某个线程T对对象O进行同步操作期间没有其他线程T′对O进行访问,那么就可以删除线程T对O的同步操作。在Java应用程序中,常有些看似是单线程的程序使用JDK中的帮助线程,这些程序实际上是多线程的,但是帮助线程并不和应用程序的单线程共享数据;基于逃逸分析会识别出一些线程局部的对象,这些对象只被创建其的线程访问,对这些对象的访问是不需要同步的。
作为本发明的一个实施例,根据一个对象是否在多个线程间共享来决定是否删除作用于该对象上的同步操作。如果一个对象O只在创建它的线程中被访问(即O未逃逸出线程),则所有作用于O的同步操作(包括O的同步方法调用所涉及的、对O的同步操作)是冗余的,从而可以对O的同步方法的任意调用点进行标记。
需要说明的是,程序分析阶段的目的是分析识别出无须同步的同步方法调用点,除了基于锁粗化的程序分析技术和逃逸分析技术外,还可以采用其他的技术。只要这项技术能识别出无须同步的同步方法调用点,这项技术就可以被本发明所述的同步方法优化框架的程序分析阶段所使用。
S102:根据所述标记的同步方法调用点为同步方法编译生成允许不对同步方法的同步对象执行同步操作的本地代码,该步骤或称编译阶段。
作为本发明的一个实施例,根据需要,可以采用双版本策略或分支版本策略为同步方法编译生成不同版本的本地代码。
作为本发明的一个实施例,双版本策略可以包括:为一个同步方法编译生成两个版本的本地代码,一个为该方法的普通版本,另一个为该方法的非同步版本。作为本发明的一个实施例,一个同步方法的普通版本是指按常规方式对该方法的代码进行编译生成的本地代码。一个同步方法的非同步版本是指在编译该方法的代码时,忽略对该方法的同步对象上的所有同步操作而生成的本地代码。
作为本发明的一个实施例,分支版本策略可以包括:为一个同步方法编译生成一个分支版本的本地代码,并在被标记的同步方法调用点前插入一条设置标记信息的指令。作为本发明的一个实施例,一个同步方法的分支版本是指在编译该方法对应的代码时,增加如下处理:(a)在方法入口处插入一条获得标记信息的指令和一条清除标记的指令;(b)对于每个作用在该方法的同步对象上的同步操作,在其之前插入一条分支指令,该分支指令判断获得的标记信息,若为真,则跳转到该同步操作之后,否则,执行该同步操作。
如图2所示为根据本发明的一个实施例的同步方法的不同代码版本的示意图。以图2(a)中的实例同步方法setSharedField()为例,图2中(b)、(c)和(d)分别给出其普通版本、非同步版本和分支版本的伪代码。在(b)图中,执行方法体中的代码之前和之后需要分别对this对象加锁和解锁;在(c)图中,直接执行方法体中的代码;在(d)图中,首先获取当前方法被调用时的标记信息marked,然后清除标记,接着对每个作用在this对象上的加锁和解锁操作增加分支指令以保证这些操作在marked为假时才被执行。
双版本策略和分支版本策略有各自的优缺点。双版本策略为一个同步方法生成并保存两个版本的本地代码,而分支版本策略只需要为一个同步方法生成并保存一个版本的本地代码,故双版本策略需要额外的空间开销并且需要虚拟机内核支持对多版本本地代码的管理。另一方面,双版本策略为一个同步方法生成的每个版本的本地代码中没有添加判断该方法的当前调用是否被标记的分支操作,而分支版本策略则添加了额外的这类分支操作,故分支版本会在一定程度上影响程序的运行时性能。
双版本策略适合那些被标记的同步方法数目少但调用频率高的情况,分支版本策略则适合那些被标记的同步方法数目多且调用频率低的情况。在进行同步方法优化时,可以根据应用程序的特点来决定是使用双版本策略还是使用分支版本策略,或者是设计一种启发式算法,让编译器自动选择最合适的策略。
S103:根据标记的同步方法调用点执行本地代码,该步骤或称执行阶段。该阶段负责执行本地代码,它根据编译阶段采取的是双版本策略还是分支版本策略而略有不同。
作为本发明的一个实施例,如果编译阶段采取的是双版本策略,当执行到一个同步方法的调用点时,若在程序分析阶段标记过该调用点,则调用其非同步版本的本地代码,否则,调用其普通版本的本地代码。
作为本发明的一个实施例,如果编译阶段采取的是分支版本策略,当执行到一个同步方法的调用点时,根据程序分析阶段是否标记过该调用点来决定是否设置标记信息,然后调用其分支版本的本地代码。
以上所述的同步方法优化方法包括程序分析、编译和执行三个阶段,前两个阶段分别可以采取不同的策略。以下介绍同步方法优化框架的几个应用实例,即基于锁粗化的双版本同步方法优化算法(简称双版本粗化算法)、基于锁粗化的分支版本同步方法优化算法(简称分支版本粗化算法)、基于逃逸分析的双版本同步方法优化算法(简称双版本逃逸算法)和基于逃逸分析的分支版本同步方法优化算法(简称分支版本逃逸算法)等。
双版本粗化算法是指在同步方法优化框架的程序分析阶段采用锁粗化分析技术、编译阶段采用双版本策略所形成的同步方法优化算法;分支版本粗化算法指在同步方法优化框架的程序分析阶段采用锁粗化分析技术、编译阶段采用分支版本策略所形成的同步方法优化算法;双版本逃逸算法指在同步方法优化框架的程序分析阶段采用逃逸分析技术、编译阶段采用双版本策略所形成的同步方法优化算法;分支版本逃逸算法指在同步方法优化框架的程序分析阶段采用逃逸分析技术、编译阶段采用分支版本策略所形成的同步方法优化算法。
作为本发明的一个实施例,双版本粗化算法包括以下两个部分:
1)利用Java虚拟机的即时编译器(JIT)对每个被编译方法的CFG(控制流图)进行程序分析和变换,执行如下操作:
(a)找到作用于同一个同步对象上的、可以合并的相邻同步方法调用点以及同步操作,将它们进行合并并标记在合并区域内的同步方法调用点。
(b)在作用于某同步对象的同步语句块内部,找到作用于该同步对象上的、可以合并的同步操作和同步方法调用点,删除这些同步操作并标记这些同步方法调用点。
2)修改Java虚拟机中负责协调Java方法的编译和执行的组件,即编译流水线及虚拟机内核VMCore。当执行到一个同步方法调用点时,如果该调用点未被标记,检查该同步方法的普通版本的本地代码是否存在,如果存在,则执行之,否则启动JIT编译流水线为之编译生成普通版本的本地代码,然后执行之;如果该调用点被标记,检查该同步方法的非同步版本的本地代码是否存在,如果存在,则执行之,否则启动JIT编译生成非同步版本的本地代码,然后执行之。
作为本发明的一个实施例,如果作用于同一个同步对象上的相邻同步方法调用点和同步操作之间存在下列情况之一,则不能进行上述的优化过程:
条件1:包含作用于其他对象上的同步操作。
条件2:包含访问易变(volatile)数据的操作。
条件3:包含静态无法解析的访问或方法调用。
条件4:包含循环。
条件5:某操作对应于CFG中的节点的各个前驱节点被锁定的次数不同。
其中,条件1~3是为了防止执行同步区域合并后的代码以不同的次序获得不同的锁而可能产生死锁;条件3~4是为了防止同步区域合并产生超大的同步区域而降低多线程程序的并发度;条件5是一种复杂的情况,这种情况出现的概率几乎为0,故该算法不处理这种情况。
作为本发明的一个实施例,分支版本粗化算法利用Java虚拟机的即时编译器对每个被编译方法的CFG进行程序分析和变换,执行如下操作:
(a)找到作用于同一个同步对象上的、可以合并的相邻同步方法调用点以及同步操作,将它们进行合并并在这些同步方法调用点前插入一条标记指令(该指令将标记信息置为真)。
(b)在作用于某同步对象的同步语句块内部,找到作用于该同步对象上的、可以合并的同步操作和同步方法调用点,删除这些同步操作,并在这些同步方法调用点前插入一条标记指令(该指令将标记信息置为真)。
(c)如果当前被编译方法是标记过的同步方法,为其变换生成分支版本的本地代码。
与双版本粗化算法一样,如果作用于同一个同步对象上的相邻同步方法调用点和同步操作之间存在条件1~5之一,则不能进行上述的优化过程。
作为本发明的一个实施例,双版本逃逸算法和分支版本逃逸算法在同步方法优化框架的程序分析阶段采用逃逸分析技术,如果逃逸分析的结果表明对象O未逃逸出某个线程,即对象O只被该线程访问,则可以对作用于同步对象O的所有同步方法调用点进行标记。
作为本发明的一个实施例,对于双版本逃逸算法,与双版本粗化算法类似,还需要修改编译流水线及虚拟机内核VMCore。当执行到一个同步方法调用点时,如果该调用点未被标记,检查该同步方法的普通版本的本地代码是否存在,如果存在,则执行之,否则启动JIT编译流水线编译生成普通版本的本地代码,然后执行之;如果该调用点被标记,检查该同步方法的非同步版本的本地代码是否存在,如果存在,则执行之,否则启动JIT编译生成非同步版本的本地代码,然后执行之。
作为本发明的一个实施例,对于分支版本逃逸算法,还需要在每个标记过的同步方法调用点之前插入一条标记指令mark(),并将被标记过的每个同步方法编译成分支版本的本地代码。
需要注意的是,本发明所提出的同步方法优化框架非常灵活,它的前两个阶段均可以分别采取不同的策略,每个阶段选择不同策略可以组合成不同的优化算法。可以根据不同的应用需求,使用不同的组合。
除了高度的灵活性之外,该框架还具有另一个优点,那就是良好的可扩展性。该框架的程序分析阶段除了可以采用锁粗化和逃逸分析之外,还可以采用其他的策略,只要该策略能识别出无须同步的同步方法调用点,都可以作为该同步方法优化框架的第一阶段。同步方法优化框架的程序分析阶段每增加一种新的策略,就可以用这种策略与编译阶段的2种策略分别进行组合,从而生成新的优化算法。
作为本发明的一个实施例,可以在开源的Java SE平台Apache Harmony上,用C++实现双版本粗化算法和分支版本粗化算法,下面分别举例介绍这两个算法的实现。
双版本粗化算法指在同步方法优化框架的程序分析阶段采用锁粗化技术,编译阶段采用双版本策略的算法,该算法包括两个部分:
1)利用Harmony的即时编译器对每个被编译方法的CFG进行程序分析和变换,该过程的算法描述如下:
输入:当前被编译的方法的CFG
输出:变换后的CFG
过程:包括程序分析和代码变换两个阶段,其基本框架如下:
doubleOptimization(){
programAnalyse();//程序分析
transform();//代码变换
}
如图3所示为根据本发明的一个实施例的双版本算法的示意图。其中O.syncCall()指令是对该同步方法的普通版本的本地代码的调用,O.Call()指令是对非同步版本的本地代码的调用。以图3展示的伪CFG(即图中的节点未必是严格的基本块节点)为例对其进行简单描述。
programAnalyse():利用JIT对当前被编译方法的中间表示进行程序分析,找到作用于同一个同步对象上的相邻同步方法调用点,如图3中的O.syncCall1()、O.syncCall2()和O.syncCall3(),以及同步操作,如图3中的lock(O)和unlock(O)。
transform():根据找到的这些同步方法调用点和同步操作对当前被编译方法的中间表示进行代码变换,其具体过程如下:
(a)找到这些相邻的同步方法调用点与同步操作中的第一个,如图3中的O.syncCall1(),在它之前插入lock(O)指令;找到这些相邻的同步方法调用点与同步操作中的最后一个,如图3中的O.syncCall3(),在它之后插入unlock(O)指令。
(b)标记在programAnalyse()中找到的这些同步方法调用点,如图3中的O.syncCall1()、O.syncCall2()和O.syncCall3();删除在programAnalyse()中找到的这些同步操作,如图3中的lock(O)和unlock(O)。
(c)对于在代码变换之前不在同步区域中、但在代码变换之后被包含到同步区域中的基本块,如图3中的基本块D,如果在代码变换之后,存在从不在同步区域中的基本块到该基本块的控制流边,如图3中从基本块C到基本块D的控制流边,则需要在该边上插入lock(O)指令;如果在代码变换之后,存在从该基本块到不在同步区域中的基本块的控制流边,如图3中从基本块D到基本块E的控制流边,需要在该边上插入unlock(O)指令。
(d)修改编译流水线及虚拟机内核VMCore。当执行到一个同步方法调用点时,如果该调用点未被标记,则执行其普通版本的本地代码,然后执行之;如果该调用点被标记,如图3中的O.syncCall1()、O.syncCall2()和O.syncCall3(),则执行其非同步版本的本地代码,如图3中的O.Call1()、O.Call2()和O.Call3()。
作为本发明的一个实施例,分支版本粗化算法指在同步方法优化框架的程序分析阶段采用锁粗化技术,编译阶段采用分支版本策略的算法,其算法描述如下:
输入:当前被编译的方法的CFG
输出:变换后的CFG
过程:包括程序分析、代码变换以及分支变换三个阶段,其基本框架如下:
branchOptimization(){
programAnalyse();//程序分析
transform();//代码变换
branch();//分支变换
}
如图4所示为根据本发明的一个实施例的分支版本算法的示意图。其中O.syncCall()指令是对该同步方法普通版本本地代码的调用,O.brCall()指令是对分支版本本地代码的调用。下面以图4展示的伪CFG为例进行简单描述。
programAnalyse():利用JIT对当前被编译方法的中间表示进行程序分析,找到作用于同一个同步对象上的相邻同步方法调用点,如图4中的O.syncCall1()、O.syncCall2()和O.syncCall3(),以及同步操作,如图4中的lock(O)和unlock(O)。
transform():根据找到的这些同步方法调用点和同步操作对当前被编译方法的中间表示进行代码变换,其具体过程如下:
(a)找到这些相邻的同步方法调用点与同步操作中的第一个,如图4中的O.syncCall1(),在它之前插入lock(O)指令;找到这些相邻的同步方法调用点与同步操作中的最后一个,如图4中的O.syncCall3(),在它之后插入unlock(O)指令。
(b)在programAnalyse()中找到的这些同步方法调用点之前插入一条标记指令mark(),如图4中的O.syncCall1()、O.syncCall2()和O.syncCall3(),删除在programAnalyse()中找到的这些同步操作,如图4中的lock(O)和unlock(O)。
(c)对于在代码变换之前不在同步区域中、但在代码变换之后被包含到同步区域中的基本块,如图4中的基本块D,如果在代码变换之后,存在从不在同步区域中的基本块到该基本块的控制流边,如图4中从基本块C到基本块D的控制流边,需要在该边上插入lock(O)指令,如果在代码变换之后,存在从该基本块到不在同步区域中的基本块的控制流边,如图4中从基本块D到基本块E的控制流边,需要在该边上插入unlock(O)指令。
branch():如果当前被编译方法是同步方法,将其变换成分支版本,其具体过程如下:
(a)在方法入口处插入一条获得标记信息的指令和一条清除标记的指令,如图4中入口块中的marked=getMark()与clearMark()指令。
(b)对于作用在该方法的同步对象上的同步操作,如图4中的lock(O1)和unlock(O1),在其之前插入一条分支指令,该分支指令判断获得的标记信息marked是否为真,若为真,则跳转到该同步操作之后,否则,执行该同步操作。
需要注意的是,作为本发明的一个实施例,无论是双版本粗化算法还是分支版本粗化算法,如果作用于同一个同步对象上的相邻同步方法调用点和同步操作之间满足上述的条件1~5之一,则不能进行优化。如图3及图4中的基本块A、B和D,如果满足上述条件1~5中的任何一条,都不能进行优化。
如图5所示为根据本发明的一个实施例的同步优化设备的示意图。如图所示,该同步优化设备包括分析模块、编译模块和执行模块。其中,
分析模块用于对被编译方法进行静态程序分析,根据分析结果确定被编译方法中在同步对象上存在无须同步的同步方法调用点,并对该同步方法调用点进行标记。
编译模块用于根据标记的同步方法调用点为同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码。
执行模块用于根据标记的同步方法调用点执行所述本地代码。
本发明提出的同步方法优化方法及设备主要有以下三个优点:
第一,本发明的同步方法优化方法及设备具有高度的灵活,可以根据不同的需求,自由组合各阶段的不同策略,生成不同的优化算法。
第二,本发明的同步方法优化方法及设备具有良好的可扩展性,只要一种程序分析方法能识别出无须同步的同步方法调用点,就可以将其应用于该同步方法优化框架的第一阶段。
第三,在本发明的同步方法优化方法及设备的基础上设计的优化算法是过程间的同步优化算法,不仅能删除大量过程内同步算法无法删除的同步操作,而且能用过程内同步优化算法的开销获得接近过程间算法的优化效果,缓解了开销和优化效果之间的矛盾。
发明人在开源的Java SE平台Apache Harmony上,基于该同步方法优化框架实现了双版本粗化算法和分支版本粗化算法,该框架可以同样地应用在其他Java虚拟机上。发明人以SPECjbb2005作为测试程序对同步方法优化算法的实现进行了测试。
表1给出了SPECjbb2005中各种同步操作的数量,其中静态和动态分别表示通过编译时分析和运行时分析统计出来的各种同步操作的数量,内联(inline)前和内联后分别表示执行方法内联前后SPECjbb2005中各种同步操作的数量。静态编译时分析只对应用程序中的每个方法分析一次,它不能准确反映程序在实际运行时执行的各种同步操作数量,但能反映出SPECjbb2005中静态存在的可优化的机会有多少;而动态运行时分析所收集、统计的信息(动态列)能准确反映程序在实际运行时执行的各种同步操作数量,从而能准确反映出同步优化算法对整个程序性能的影响。表中的Locks表示所有monitorenter的数量,Unlocks表示所有monitorexit的数量,inserted Locks表示采用锁粗化技术时插入的monitorenter的数量,insertedUnlocks表示采用锁粗化技术时插入的monitorexit的数量,removed Locks表示优化算法删除掉的monitorenter的数量,removed Unlocks表示优化算法删除掉的monitorexit的数量,Sync-Methods是所有同步方法的数量,optSync-Methods是在双版本策略中存在非同步版本的本地代码的同步方法的数量。对于静态信息而言,sync method Callsites表示所有同步方法调用点的数量,opt sync methods Callsites表示在同步方法优化算法中所有被标记过的同步方法调用点的数量,即被优化的同步方法调用点的数量。对于动态信息而言,sync method Callsites表示同步方法被执行的总次数,opt syncmethods Callsites表示所有被优化的同步方法调用点被执行的总次数。
表1SPECjbb2005中各种同步操作的数量统计
从表1可以看出,在内联之前只能删除被标记的同步方法中同步对象上的同步操作,同步方法优化算法能删除61个同步方法中的61个加锁操作,除此之外不能删除任何加锁操作。在内联之后由于大量的同步方法被内联到其调用者的方法中成为同步语句块,在调用者方法中便出现了大量可以删除加锁操作的机会,从表中的数据可以看出,内联后可以删除431个加锁操作,其中包含29个同步方法中的29个加锁操作。
从表1中的静态信息可以看出,不管是在内联前还是内联后,被优化的同步方法调用点的数量都相当大,说明内联前后都存在大量同步方法优化的机会。从表1中的动态信息可以看出,无论内联前后,优化过的同步方法实际被执行的次数都相当之多。因此,无论编译器是否支持内联,同步方法优化算法都能起到较好的优化同步方法的效果。
从表1中还可以看出,为了保证程序语义不被改变而插入的同步操作的数量远小于删除掉的同步操作的数量;被优化的同步方法的数量相比同步方法的总数量要小得多,而且一般情况下同步方法的代码都非常少,对于双版本粗化算法意味着保存非同步版本的本地代码的额外存储空间开销会很小。
采用双版本策略为每个需要优化的同步方法生成两个版本的本地代码,需要一些额外的存储空间开销。
表2给出了SPECjbb2005在各种情况下所耗费的本地代码的存储空间,其中none表示执行时不进行方法内联也不使用双版本粗化算法时所有本地代码需要的存储空间,none&syncOpt表示执行时不进行方法内联但使用双版本粗化算法时所有本地代码需要的存储空间。从表中所示的数据可以看出,在不使用内联时双版本策略产生的额外存储空间开销只有83324字节,仅增加约5.6%的存储空间。表中的inline表示进行方法内联但不使用双版本粗化算法时所有本地代码需要的存储空间,inline&syncOpt表示进行方法内联而且使用双版本粗化算法时所有本地代码需要的存储空间,从表中所示的数据可以看出,在使用方法内联时双版本策略产生的额外存储空间开销只有114428字节,仅增加约7.5%的存储空间。由此可见,双版本策略对SPECjbb2005产生的额外存储开销不大。假使针对一些应用程序,双版本算法会产生非常大的额外存储空间开销,则可以考虑用分支版本策略。
表2各种情况下SPECjbb2005所耗费的本地代码存储空间(单位:byte)
发明人构造了不同版本的Java虚拟机对SPECjbb2005进行了测试,实验使用的平台为Intel(R)Core(TM)2 Quad CPU Q66002.40GHz,3GB内存,操作系统为Windows XP,部分测试结果如图6和图7所示。
图6为根据本发明的一个实施例的3种不使用方法内联的Java虚拟机执行SPECjbb2005所得的吞吐量(bops:business operation per second)对比示意图。其中,none表示执行时未应用任何同步优化,branch表示执行时应用分支版本粗化同步优化算法,double表示执行时应用双版本粗化同步优化算法,improvement1和improvement2分别表示branch相对于none、double相对于none的吞吐量提高率。图中数据表的第1~3行分别为使用未应用任何同步优化的虚拟机(记为none)、应用分支版本粗化算法的虚拟机(记为branch)、应用双版本粗化算法的虚拟机(记为double)执行SPECjbb2005的6组测试结果。数据表中的后2行分别为branch相对于none、double相对于none的吞吐量提高率。由于Stoodley等的过程内锁粗化算法在不使用方法内联时几乎对同步无改进,故这里未与之对比。从图6中可见,分支版本粗化算法和双版本粗化算法均能改进SPECjbb2005的吞吐量,而双版本粗化算法对吞吐量的提高率比分支版本粗化算法的要高些,这是因为分支版本粗化算法会在一些同步方法中加入判断是否需要执行同步操作的分支指令,这些分支指令将耗用运行时间,从而影响吞吐量的改进。不过,双版本粗化算法的较高性能改进是以更多的编译时开销和存储开销为代价的。
图7为根据本发明的一个实施例的4种使用方法内联的Java虚拟机执行SPECjbb2005所得的吞吐量对比示意图,其中,inline表示执行时未应用任何同步优化,inline&Stoodley表示执行时应用了Stoodley等的同步优化算法,inline&branch表示执行时应用分支版本粗化同步优化算法,inline&double表示执行时应用双版本粗化同步优化算法的测试结果,improvement1、improvement2、improvement3分别表示inline&Stoodley相对于inline、inline&branch相对于inline、inline&double相对于inline的吞吐量提高率。图中数据表的第1~4行分别为使用应用方法内联但未应用任何同步优化的虚拟机(记为inline)、在内联后应用Stoodley等的粗化算法的虚拟机(记为inline&Stoodley)、在内联后应用分支版本粗化算法的虚拟机(记为inline&branch)、在内联后应用双版本粗化算法的虚拟机(记为inline&double)执行SPECjbb2005的6组测试结果。数据表中的后3行分别为inline&Stoodley相对于inline、inline&branch相对于inline、inline&double相对于inline的吞吐量提高率。从中可见,三种同步优化算法都能改进吞吐量,而双版本粗化算法和分支版本粗化算法所带来的改进高于Stoodley等的算法所带来的改进。从表1中可知,在内联后同步方法调用的执行次数由612136827减到87182262,这是由于在执行了内联后绝大多数同步方法调用点被替换成这些同步方法的方法体。另外,由于在内联后应用分支版本粗化算法所产生的判断是否需要执行同步操作的分支指令数显著减少了,故分支版本粗化算法所带来的分支指令对性能的影响也减轻了。从图7中可以看到,inline&branch和inline&double对吞吐量的提高率是差不多的。
由图6和图7中分支版本粗化算法和双版本粗化算法对吞吐量的改进情况可知,两种算法在内联后的改进比对应的内联前的改进都要高。这主要是因为:当不执行内联时,锁粗化算法形成的新的同步区域会包含方法调用和返回、甚至是对未编译过的同步方法的编译等操作,这些操作导致新的同步区域较长,从而严重影响多线程程序的并发性。在内联后,由于大部分同步方法调用点被替换成同步方法的方法体,故锁粗化算法形成的新的同步区域中的方法调用和返回以及对未编译过的同步方法的编译等操作显著减少了,从而新的同步区域相对较短,并发性将得到改善。
尽管已经示出和描述了本发明的实施例,对于本领域的普通技术人员而言,可以理解在不脱离本发明的原理和精神的情况下可以对这些实施例进行多种变化、修改、替换和变型,本发明的范围由所附权利要求及其等同限定。
Claims (10)
1.一种同步优化方法,其特征在于,包括以下步骤:
对被编译方法进行静态程序分析,根据分析结果确定所述被编译方法中无须对同步对象进行同步操作的同步方法调用点,并对所述同步方法调用点进行标记;
根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码;
根据所述标记的同步方法调用点执行所述本地代码。
2.根据权利要求1所述的同步优化方法,其特征在于,所述对被编译方法进行静态程序分析,确定无须对同步对象进行同步操作的同步方法调用点的步骤包括:
合并作用于同一个同步对象上的相邻同步区域和/或嵌套同步区域,将包含在所述合并后的同步区域内的同步方法调用点确定为所述无须对同步对象进行同步操作的同步方法调用点。
3.根据权利要求1所述的同步优化方法,其特征在于,所述对被编译方法进行静态程序分析,确定无须对同步对象进行同步操作的同步方法调用点的步骤包括:
根据对象是否在多个线程间共享确定对所述对象的同步方法调用点是否是无须对同步对象进行同步操作的同步方法调用点。
4.根据权利要求3所述的同步优化方法,其特征在于,根据对象是否在多个线程间共享确定对所述对象的同步方法调用点是否是无须对同步对象进行同步操作的同步方法调用点的步骤包括:
如果所述对象只在创建所述对象的线程中被访问,则将作用于所述对象的同步方法调用点确定为所述无须对同步对象进行同步操作的同步方法调用点。
5.根据权利要求1所述的同步优化方法,其特征在于,根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码的步骤包括:
根据所述标记的同步方法调用点为所述同步方法编译生成所述同步方法的普通版本和所述同步方法的非同步版本,
其中所述同步方法的非同步版本包括忽略对所述同步方法的同步对象上的同步操作而生成的本地代码。
6.根据权利要求1所述的同步优化方法,其特征在于,根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码的步骤包括:
根据所述标记的同步方法调用点为所述同步方法编译生成所述同步方法的分支版本,并在所述被标记的同步方法调用点前插入一条设置标记信息的指令,
其中所述同步方法的分支版本通过以下步骤获得:在所述同步方法入口处插入获得标记信息的指令和清除标记的指令;在作用在所述同步方法的同步对象上的同步操作之前插入分支指令,所述分支指令判断获得的标记信息,若所述标记信息为真,则跳转到所述同步操作之后,如果所述标记信息为假,则执行所述同步操作。
7.根据权利要求5所述的同步优化方法,其特征在于,执行所述本地代码的步骤包括:
当执行同步方法调用点时,如果所述同步方法调用点为标记的同步方法调用点,则调用所述非同步版本的本地代码,如果所述同步方法调用点为没有标记的同步方法调用点,则调用所述普通版本的本地代码。
8.根据权利要求6所述的同步优化方法,其特征在于,执行所述本地代码的步骤包括:
当执行到同步方法调用点时,根据所述同步方法调用点前设置的标记信息指令调用所述分支版本的本地代码。
9.根据权利要求1所述的同步优化方法,其特征在于,对被编译方法进行静态程序分析中出现以下情况之一时不进行将同步方法调用点确定为无须对同步对象进行同步操作的步骤:
作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含作用于其他对象上的同步操作;
所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含访问易变数据的操作;
所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含静态无法解析的访问或方法调用;
所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含循环;
所述作用于同一个同步对象上的相邻同步方法调用点和同步操作之间包含锁定次数不一致的操作,所述锁定次数不一致的操作所属的控制流图节点的各个前驱节点被锁定的次数不同。
10.一种同步优化设备,其特征在于,包括分析模块、编译模块和执行模块,其中,
所述分析模块用于对被编译方法进行静态程序分析,根据分析结果确定所述被编译方法中无须对同步对象进行同步操作的同步方法调用点,并对所述同步方法调用点进行标记;
所述编译模块用于根据所述标记的同步方法调用点为其调用的同步方法编译生成允许不对所述同步方法的同步对象执行同步操作的本地代码;
所述执行模块用于根据所述标记的同步方法调用点执行所述本地代码。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN2009101629791A CN101630268B (zh) | 2009-08-20 | 2009-08-20 | 同步优化的方法及设备 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN2009101629791A CN101630268B (zh) | 2009-08-20 | 2009-08-20 | 同步优化的方法及设备 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN101630268A CN101630268A (zh) | 2010-01-20 |
CN101630268B true CN101630268B (zh) | 2012-07-04 |
Family
ID=41575386
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN2009101629791A Expired - Fee Related CN101630268B (zh) | 2009-08-20 | 2009-08-20 | 同步优化的方法及设备 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN101630268B (zh) |
Families Citing this family (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108170543B (zh) * | 2017-12-26 | 2021-06-01 | 上海展扬通信技术有限公司 | Kernel代码及其上层代码的同步处理方法及装置 |
WO2019241979A1 (en) * | 2018-06-22 | 2019-12-26 | Huawei Technologies Co., Ltd. | Method of deadlock detection and synchronization-aware optimizations on asynchronous processor architectures |
CN112269581B (zh) * | 2020-12-24 | 2021-07-02 | 北京清微智能科技有限公司 | 一种可重构芯片的内存耦合编译方法及系统 |
Citations (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1591335A (zh) * | 2003-08-26 | 2005-03-09 | 微软公司 | 事务型处理过程的数据流分析 |
WO2006128891A2 (en) * | 2005-06-03 | 2006-12-07 | International Business Machines Corporation | Shared memory synchronization |
CN1961292A (zh) * | 2004-06-03 | 2007-05-09 | 英特尔公司 | 用于受管运行时环境的线程同步方法和装置 |
-
2009
- 2009-08-20 CN CN2009101629791A patent/CN101630268B/zh not_active Expired - Fee Related
Patent Citations (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1591335A (zh) * | 2003-08-26 | 2005-03-09 | 微软公司 | 事务型处理过程的数据流分析 |
CN1961292A (zh) * | 2004-06-03 | 2007-05-09 | 英特尔公司 | 用于受管运行时环境的线程同步方法和装置 |
WO2006128891A2 (en) * | 2005-06-03 | 2006-12-07 | International Business Machines Corporation | Shared memory synchronization |
Also Published As
Publication number | Publication date |
---|---|
CN101630268A (zh) | 2010-01-20 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
Stadler et al. | Partial escape analysis and scalar replacement for Java | |
US8104028B2 (en) | Method for JIT compiler to optimize repetitive synchronization | |
Aldrich et al. | Static analyses for eliminating unnecessary synchronization from Java programs | |
Avgustinov et al. | Making trace monitors feasible | |
CN101681294B (zh) | 用于存储器事务分组的方法和系统 | |
EP2049992B1 (en) | Software transactional protection of managed pointers | |
US8473935B2 (en) | Just-ahead-of-time compilation | |
US20080040560A1 (en) | Lightweight Single Reader Locks | |
US6345384B1 (en) | Optimized program code generator, a method for compiling a source text and a computer-readable medium for a processor capable of operating with a plurality of instruction sets | |
Bebenita et al. | Trace-based compilation in execution environments without interpreters | |
Hayashizaki et al. | Improving the performance of trace-based systems by false loop filtering | |
Wang et al. | An adaptive task creation strategy for work-stealing scheduling | |
US7451438B2 (en) | Method, system and product for identifying and executing locked read regions and locked write regions in programming languages that offer synchronization without explicit means to distinguish between such regions | |
Prokopec et al. | Making collection operations optimal with aggressive JIT compilation | |
Afek et al. | Lowering STM overhead with static analysis | |
CN101630268B (zh) | 同步优化的方法及设备 | |
Lin et al. | Speculative register promotion using advanced load address table (alat) | |
JP2006196002A (ja) | 非同期プログラムフローのモデリングを含むソフトウェアツール | |
Itzstein et al. | On implementing high level concurrency in Java | |
Nakaike et al. | Lock elision for read-only critical sections in java | |
Pieper et al. | Structured stream parallelism for rust | |
Giunta et al. | Using aspects and annotations to separate application code from design patterns | |
US20050149945A1 (en) | Method and system of re-reserving object locks without causing reservation thrash | |
US20040243792A1 (en) | Efficiently releasing locks when an exception occurs | |
Stolz et al. | Refactoring and active object languages |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
C14 | Grant of patent or utility model | ||
GR01 | Patent grant | ||
CF01 | Termination of patent right due to non-payment of annual fee |
Granted publication date: 20120704 Termination date: 20150820 |
|
EXPY | Termination of patent right or utility model |