从系统的角度分析影响程序执行性能的因素

2021/5/11 1:25:28

本文主要是介绍从系统的角度分析影响程序执行性能的因素,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Linux系统中应用程序执行性能分析


1. Linux系统


1.1 概念模型

Linux主要分成三部分:

  • 用户空间
  • 内核空间
  • 硬件部分

简单结构如下图所示:

1.2 模型运作过程

以读取文件I/O流为例:

系统调用层中操作系统中处理 read() 函数的入口函数是 sys_read(), sys_read() 会从进程中获取文件描述符以及文件当前的操作位置,接着调用 vfs_read() 函数,而 vfs_read() 函数则是会调用 file 结构中的对应功能函数去完成文件的读操作。

调用关系如下:

sys_read()
  |--- vfs_read()
       |--- generic_file_read()
             |--- generic_file_aio_read()
                  |--- generic_file_direct_IO()

在文件系统层中,Linux支持许多不同的文件系统,并将它们组织成了一个统一的虚拟文件系统(VirtualFileSystem),其旨在为各类文件系统提供一个统一的操作界面和应用编程接口。VFS之上,是对 open、close、read 和 write 等函数的一个通用 API 抽象;而 VFS之下则是文件系统抽象,它定义了上层函数的实现方式。

文件系统层之下的缓冲区缓存为文件系统层提供了一个与具体文件系统无关的通用函数集,优化了对物理设备的访问。

缓冲区缓存之下是设备驱动程序,它实现了特定物理设备的接口。


2. 应用程序性能分析


2.1 性能影响因素

评价Linux系统性能的好坏,大致可以从Linux完成任务的有效性、稳定性以及响应速度等方面进行考量。而系统中的应用程序执行性能的关键则是在于进程管理。进程管理是操作系统的最重要的功能之一,只有完善的进程管理才能保证一个程序平稳而高效地运行。

应用程序性能的问题,大多可分为三种:

  1. 应用程序的运算量较大,CPU过于繁忙,此时CPU性能是瓶颈。
  2. 应用程序需要做大量的I/O,CPU大多时候的是处于等待,I/O性能成为瓶颈。
  3. 内存不足以充分发挥系统性能,应用程序之间相互等待,此时CPU利用率低,程序运行速度慢,事务间的共享与互斥也会制约程序的性能。

三个问题分别受制于硬件CPU,磁盘I/O,内存的性能。

2.2 Linux性能分析工具Perf

Perf是Linux kernel自带的系统性能优化工具,用于查看热点函数以及cache未命中的比率,通俗得说就是可以了解程序中哪些地方最耗时间,从而重点分析。Perf能够分析程序运行期间发生的硬件事件,也能够分析软件事件,做到了同时分析应用程序代码和内核,从而方便开发者全面理解应用程序中的性能瓶颈。

2.2.1 Perf的应用

构建程序test.c如下:

//test.c
#include<stdio>
#include<math.h>
#include<sys/types.h>
#include<linux/unistd.h>

int foo(){
	double Mypi,h,sum,x;
	long long n,i;

	n = 5000000;
	h = 1.0/n;
	sum = 0.0;

	for(i=1;i<=n;i++)
	{
		x = h*(i-0.5);
		sum += 4.0/(1.0+pow(x,2));		
	}

	Mypi = h*sum;
	return 0;
}

int main(){
	printf("pid:%d\n",getpid());
	sleep(8);

	foo();
	return 0;
}

可以看出test是一个计算pi的计算(CPU)密集型程序。

编译并使用 perf stat 命令查看test的运行性能表现:

  • Task-clock:CPU 利用率,该值高说明程序的多数时间花费在CPU计算而非I/O上。test进程的task-clock为0.993极其接近1,证明这确实是一个CPU密集型程序。
  • Context-switches:进程切换次数,记录了程序运行过程中发生了多少次进程切换,为了提升性能需要避免频繁的进程切换。
  • CPU-migrations:CPU迁移次数,为了维持多个处理器的负载均衡,在特定条件下会将某个任务从一个CPU迁移到另一个CPU。发生上下文切换不一定会发生CPU迁移,而发生CPU迁移时肯定会发生上下文切换。发生上下文切换有可能只是把上下文从当前CPU中换出,下一次调度器还是将进程安排在这个CPU上执行。
  • page-faults:缺页异常的次数。当应用程序请求的页面尚未建立、请求的页面不在内存中,TLB不命中,页面访问权限不匹配都会触发一次缺页异常。

针对上面的性能表现报告,可以初步判断进程性能的瓶颈所在。接下来可以用 perf record 命令对程序进行执行性能采样,然后用 perf report -g 命令生成函数调用流程图以及函数的CPU占有时间,由此则可以定位到热点函数。

构建程序test2.c如下:

//test2.c
void longa(int a[])
{
	int i,j;
	for(i = 0; i < 1000000; i++)
	j = i;
	*a = j;
}
 
void foo2(int a[])
{
	int i;
	for(i=0 ; i < 10; i++)
	longa(&a[i]);
}
 
void foo1(int a[])
{
	int i;
	for(i = 0; i< 100; i++)
    	longa(&a[i]);
}
 
int main(void)
{
	int a[100];
	foo1(a);
	foo2(a);
}

生成其函数调用流程图:

针对这些热点函数进行性能优化迭代,就可以将程序的执行性能优化。



这篇关于从系统的角度分析影响程序执行性能的因素的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程