利用应用程序检测计算机系统性能变化的方法和系统与流程

文档序号:15200144发布日期:2018-08-19 10:42阅读:182来源:国知局

本发明总体地涉及高性能计算系统,特别是涉及检测计算机系统性能变化的方法和系统。



背景技术:

在当前的高性能计算(hpc)系统中,性能变化是一个非常严重的问题。在当前的大规模hpc系统上,由于受到系统性能变化的影响,程序不同次运行的时间可能会差别很大。在大型计算机上,这种情况是很常见的。

无论是普通的用户还是专业的程序开发者都会受到这种性能变化的不良影响。性别变化会影响不可预测的性能下降,这会耗费更多的时间和资源,甚至无法满足用户对性能的要求。此外,对于不同应用程序的性能比较也变得更为困难。而对于程序开发者而言,新加入的优化产生的效果可能会被系统的性能变化所掩盖。根据前人的研究,有许多原因都可以引起性能变化,包括硬件故障,网络拥堵,僵尸进程,操作系统调度,等等。取决于具体的原因,有一些种类的性能变化是可以避免的;但另一些种类却无法避免。例如,如果性能变化是由坏结点造成的,那只要换一个好的就可以了。但是,如果是由网络拥堵造成的,因为网络是一个多用户共享的资源,单一的用户很难去阻止或规避网络拥堵。因此,在抱怨系统或者重新提交作业之前,我们需要先回答两个问题:(1)性能变化有多大;(2)性能变化的原因是什么。因此对于系统性能变化进行快速有效的检测非常重要。

截至目前,检测和处理性能变化的方法大致可以分为四类,但它们无一能够很好地回答上面的两个问题。这四类方法是:(1)重跑。这是一种非常简单的检测性能变化的方法,只要重复运行多次并比较它们的运行时间,就能发现性能的变化。显而易见的是,这种方法将会耗费大量的时间和系统资源,运行时间长的程序尤甚。(2)性能模型。如果有一个准确的性能模型,我们就能准确预测程序的运行时间。这样当实测时间与预测时间不符时,就检测到了性能变化。然而大多数性能模型都着眼于预测程序整体的运行时间,而无法确定性能变化来自何方。此外,性能模型通常需要针对具体程序具体平台进行构建,这使得这种方法的可移植性较差。(3)profile和trace。在程序运行过程中通过某些手段收集性能数据,并在程序结束后进行分析。这种方法最大的不足之处在于,如果采集过多数据,将会使得程序性能下降,并对存储系统产生巨大压力;反之,如果采集的数据太少,又无法获得足够的细节来检测和定位系统性能变化。(4)基准测试。通过在计算机系统上运行一系列精心设计的基准测试程序,可以检测出系统的性能变化。但是这种方法因为是专门的一个测试,所以无法在系统上已经运行着应用程序的时候进行,否则将极大影响应用程序的性能。总而言之,如何低开销地在程序运行中及时检测并定位系统的性能变化,仍是一个尚未解决的问题。



技术实现要素:

鉴于上述情况,提出了本发明。

根据本发明的一个方面,提出了一种利用应用程序检测系统性能变化的方法,包括:在应用程序的源程序中定位探针代码段,探针代码是在一段时间内被多次执行,且每次执行时的工作量固定不变的代码;在定位的探针代码段前后插入自定义的代码,这些插入的代码将在运行时采集性能数据。

进一步地,在源程序中定位探针代码段可以包括:将源程序的源代码编译成中间码;识别中间码中的探针代码;基于识别得到的中间码中的探针代码,在源程序中定位探针代码段。

进一步地,识别中间码中的探针代码可以包括:识别位于循环内部的工作量固定的子循环或函数调用作为探针代码。

进一步地,探针代码的工作量不受相关联的控制语句和/或函数参数影响。

进一步地,性能变化检测方法还可以包括:将插桩后的程序源代码编译为可执行文件;按照原有的方式来运行应用程序;基于插入的插桩代码采集到的性能数据,得到系统性能变化检测结果。

进一步地,性能检测方法还可以包括:将检测结果以可视化的形式展示。

进一步地,性能检测方法还可以包括进行下列项目之一:通过比较单个机器上的单个进程内的探针代码的运行时间来发现所述单个机器的性能随时间变化的关系;对于运行在多个机器上的多进程程序,比较不同进程上的同样代码段的运行时间来检测机器间的性能差异。

根据本发明的另一方面,还提供了一种计算装置,包括存储器和处理器,存储器上存储有计算机可执行指令,所述计算机可执行指令当被处理器执行时执行前述系统性能变化检测方法。

根据本发明的另一方面,还提供了一种计算机可读存储介质,其上存储有计算机可执行指令,当所述计算机可执行指令被计算装置执行时,可操作来执行前述系统性能变化检测方法。

根据本发明的另一方面,还提供了一种利用应用程序检测系统性能变化的方法,包括:在应用程序的源代码或中间码中定位探针代码段,探针代码是在一段时间内被多次执行,且每次执行时的工作量固定不变的代码;在源代码或中间码中,在定位的探针代码段前后插入自定义的代码,这些插入的代码将在运行时采集和/或分析性能数据。

本发明的系统性能变化检测技术能够低开销地在程序运行中及时检测并定位系统的性能变化。

附图说明

从下面结合附图对本发明实施例的详细描述中,本发明的这些和/或其它方面和优点将变得更加清楚并更容易理解,其中:

图1示出了根据本发明实施例的利用应用程序获得能够检测系统性能变化的代码100的方法的总体流程图。

图2示出了根据本发明实施例的在源程序中定位探针代码段的方法的流程图。

图3示出了一段代码中一个子循环作为探针代码段的示意性例子。

图4示出了涉及函数调用的情况下作为探针代码段的子循环的例子。

图5示出了多进程程序情况下的探针代码段的示例。

图6示出了根据本发明实施例的基于一个应用程序得到系统性能变化报告的完整过程200的示意图。

图7示出了一个系统性能检测结果可视化表示示例。

具体实施方式

为了使本领域技术人员更好地理解本发明,下面结合附图和具体实施方式对本发明作进一步详细说明。

在介绍之前,解释一下有关术语在本文中的含义。

探针代码是在一段时间内被多次执行,且每次执行时的工作量固定不变的代码。

在详细描述前,为便于本领域技术人员透彻把握本发明,首先阐述总体发明构思。发明人的观察到,在大部分应用程序中,都包含着一些工作量固定且会被反复执行的代码段,我们将这样的代码段称为“探针代码段”或“探针代码”。因为探针代码每次被执行时的工作量是固定不变的,因此如果它们的运行时间发生了变化,那只能是由于系统本身的性能变化引起的,基于此发现,提出了如下技术方案:识别程序中的探针代码,以及针对探针代码进行插桩操作。由此后面执行插桩后的程序时,能够采集探针代码的运行时间数据,分析数据,从而发现系统性能变化以及性能变化的原因。

后面首先结合图1描述总体流程,然后结合图2给出一个更具体的实施流程,接下来给出探针代码识别的具体实施例,最后给出一个检测性能变化的结果示例。

图1示出了根据本发明实施例的利用应用程序获得能够检测系统性能变化的代码100的方法的总体流程图。

在步骤s110中,在应用程序的源程序中定位探针代码段,探针代码是在一段时间内被多次执行,且每次执行时的工作量固定不变的代码。

在步骤s120中,在定位的探针代码段前后插入自定义的代码,这些插入的代码将在运行时采集性能数据。

作为插入的自定义代码,可以是采集运行时间的代码,还可以是性能异常分析代码,即将已采集到的运行时间进行对比分析。

下面结合图2描述步骤s110的在源程序中定位探针代码段的一个实现例子。

如图2所示,在步骤s111中,将源程序的源代码编译成中间码。

在步骤s112中,识别中间码中的探针代码。

中间码是指编译器将高级语言翻译成二进制可执行机器语言过程中采用的中间表示(intermediaterepresentation)。中间码和源代码或可执行代码的功能逻辑是完全一致的,原则上都可以用来识别探针代码,但基于中间码的识别主要有两个好处,一是中间码对程序逻辑的表示方式更加易于分析,二是对于一个编译器来说中间码是一种统一的表示,这样我们就不需要针对不同语言的源代码和不同平台的二进制代码分别实现探针代码识别算法了。

在步骤s113中,基于识别得到的中间码中的探针代码,在源程序中定位探针代码段。

在此实现例子中,探针代码识别是在中间码上完成的,但为了保持程序良好的可读性,我们将在源代码上对程序进行插桩,因此我们需要将算法找出的探针代码段在源码中进行定位。

主流编译器如llvm在编译时会建立源代码和中间码的双向映射,即可以将一段中间码定位到源代码中。即通常编译器自身支持由中间码定位源代码。

需要说明的是,在前面的图2示例中,是通过在中间码识别探针代码来在源程序中定位探针代码的,最后的插桩操作是在源程序中进行的。不过此为示例,而非作为限制,实际上,在需要的时候,可以在中间代码上实现探针代码识别和插桩操作两者,得到的是直接插桩了的中间代码,然后直接由中间代码得到可执行文件,运行可执行文件即采集性能数据。

下面给出识别探针代码的算法的示例。

如前所述,本文对探针代码段的定义是:在一段时间内被多次执行,且每次执行时的工作量固定不变。由于在程序中单条指令的运行时间非常短以至于难以测量,因此我们只选择循环和函数调用作为可能的代码段候选。又根据定义,我们只选择位于循环中的代码段,因为它可以被反复多次执行。由此,我们筛选探针代码段的标准是:位于循环内部的工作量固定的子循环或函数调用。

进一步地,将工作量固定不变定义为“执行的指令数目和序列不变”。一个代码块最终被执行的指令数目和序列由其中的分支跳转语句决定(其余部分都是顺序执行)。作为实现示例,可以利用一种成熟的编译器分析技术use-defchain对变量的依赖关系进行分析,如果代码块中的分支跳转语句受到外层循环迭代的影响,那么这个代码块的工作量就是不固定的,反之则是固定的。

图3示出了一段代码中一个子循环作为探针代码段的示意性例子。由于位于外层循环ln中,三个子循环l1、l2和l3都将会被反复执行。而子循环的工作量受到他们的控制语句(即循环的开始结束条件,以及内部的分支语句)影响。可以看到l1和l2的一些控制语句取决于变量n的值,而n的值在ln的各次迭代间是会改变的,因此也将改变l1和l2的工作量,所以这两个子循环都不是ln内的探针代码段。另一方面,因为l3的工作量完全不受变量n的影响,它的工作量在ln的各次迭代中固定不变,因此l3是ln运行期间的一个探针代码段。

图4示出了涉及函数调用的情况下作为探针代码段的子循环的例子。如果一个代码段的工作量受到函数参数的影响,那么只有这个函数每次执行的时候获得相同的参数,它的工作量才可能是不变的。例如在图4中,循环l4和l5都位于函数foo中,且l4的工作量取决于foo的参数x。由于函数foo在循环l2中被调用(c1和c2),而调用时传入的参数又随着外层循环的迭代而改变,因此,l4并不是l1运行期间的探针代码段,与之相对的,由于l5的工作量不受任何foo的参数或者l1,l2迭代变量的影响,因此它是l1运行期间内的一个探针代码段。

图5示出了多进程程序情况下的探针代码段的示例。对于多进程的程序,可以进一步扩展探针代码段的概念:如果一段代码在各个进程上执行的工作量是相同的,那么就可以用来进行进程间的性能比较,即作为多进程程序下的探针代码段。而分析代码段工作量与进程编号的关系,只需要追踪代码中的控制语句是否收到进程编号的影响即可。图5即给出一个进程间分析的例子。在这个例子中,一个多进程程序通过mpi_comm_rank调用获得属于自己的唯一的进程编号。l1的工作量受到这个编号影响,因此在各个进程上是不同的;而l2的工作量与进程无关,因此可以l2的运行时间可以

找到探针代码段后,就可以在这些代码段前后插入自定义函数,从而采集到每个代码段每次运行的耗时。正如前面讨论的那样,因为探针代码段每次执行时的工作量是固定不变的,因此如果它们的运行时间发生了变化,只可能是由于系统本身的性能发生了变化。即,只要探测到一个探针代码段的运行时间发生了变化,即可报告这个性能变化。一个计算机系统可以拆分为若干个子系统,而不同的类型的探针代码可以对应到不同的子系统的性能变化。例如一个探针代码段包含的是访存代码,那么它的运行时间反映的是内存的性能;而一个执行网络通信的探针代码段的运行时间则与网络系统的性能有关。

可以通过纵向比较单个进程内的探针代码的运行时间来发现某个机器的性能随时间变化的关系,而对于运行在多个机器上的多进程程序,可以通过比较不同进程上的同一个代码段的时间来检测机器间的性能差异(如果同样的工作量在甲机器上比乙机器上耗时更多,显然是由于甲机器的性能不如乙机器)。

图6示出了根据本发明实施例的基于一个应用程序得到系统性能变化报告的完整过程200的示意图。

图6中,位于圆圈中的编号1、2、3、4、5、6、7、8表示对前面框中的对象执行的操作。

如图6所示,整个工作流程可以大致分为8个步骤:

1、编译将源程序的源代码编译成为中间码,如前所述,现存的大量编程语言各自有不同的语法,这对于分析工作带来了额外的复杂性,通过先将源程序的源代码编译成为中间码,不同的高级语言编译得到的中间码是统一的,这使得只需要在中间码上实现探针代码识别的算法即可。

2、探针代码识别,在程序中间码上,识别出程序中的探针代码。

3、源码定位,尽管探针代码识别是在中间码上完成的,为了保持程序良好的可读性,将在源代码上对程序进行插桩,因此需要将算法找出的探针代码段在源码中进行定位。

4、源代码插桩,在识别出的探针代码段前后插入自定义的代码,这些插入的代码将在运行时实现所需的性能分析功能。

5、再次编译,将修改后的程序源代码编译为可执行文件。

6、运行,按照原有的方式来运行应用程序。

7、分析,在运行过程中,实现插入的插桩代码将采集到一些性能数据,分析这些数据,并得到最终的系统性能变化检测结果。

8、可视化,为使得对用户更加友好,最终使用一个可视化的工具将检测结果以图片的形式展示。

图7示出了一个系统性能检测结果可视化表示示例。横轴是程序的运行时间,纵轴是进程号。每个点的灰度表示某一时刻某一进程的性能,颜色越深性能越好。图中的两个白色方块表示在这段时间在这些进程上检测到系统性能下降。

以上已经描述了本发明的各实施例,上述说明是示例性的,并非穷尽性的,并且也不限于所披露的各实施例。在不偏离所说明的各实施例的范围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更都是显而易见的。因此,本发明的保护范围应该以权利要求的保护范围为准。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1