首页 > 编程知识 正文

好帮手电子(我的好帮手)

时间:2023-05-05 02:11:30 阅读:91506 作者:1709

性能分析的前提是通过将APP内部的运行状况和APP的运行环境状况可视化,从而更直接地表现出来,但是如何实现这种可视化的表现呢? 必须将内置于操作系统的程序监视工具与内置于Java的监视分析工具结合使用,对Java程序进行性能分析。 本文为系列文章,共有三篇分别介绍这几类工具。 本文介绍了操作系统的性能监控工具。

操作系统的程序性能监视工具不仅适用于Java程序,还适用于所有正在运行的程序。 在基于UNIX的操作系统中,可以使用许多命令行工具(如sar、vmstat、iostat和prstat )来监视程序的行为。 在Windows操作系统中,有图形用户界面的资源监视器Perfmon(performancemonitor )和typeperf的命令行工具之类的。

性能测试需要使用操作系统提供的工具收集操作系统中的各种资源监测数据,包括CPU、内存和硬盘的使用数据。 另外,如果被测试的程序使用的是网络,则也需要收集网络使用数据。 只有收集的数据足够、足够时,性能测试的结果才能更准确,更容易进行性能分析。 首先介绍UNIX/类UNIX系统中各种资源的监视和分析方法。

CPU 使用率

CPU使用时间分为“用户时间”(User Time )和“系统时间”(System Time )两种,系统时间在Windows系统中称为“特权时间”(Privileged Time )。 用户时间是CPU执行APP代码的时间,系统时间是CPU执行操作系统内核代码的时间的百分比。 系统时间与APP本身有关。 例如,当APP执行I/O操作时,操作系统内核执行从硬盘读取文件的代码,或者执行将数据写入网络数据缓存的代码。 由于需要使用作为操作系统基础的资源的APP行为,APP应用程序会消耗更多的系统时间。

性能调谐的终极目标是最大限度地提高单位时间的CPU利用率。 CPU利用率是特定时间间隔内的平均值,该时间间隔可以设置为30秒或1秒。 例如,运行程序需要10分钟,其间的CPU利用率为50%。 优化程序代码后,如果CPU使用率上升到100%,程序性能将增加一倍,运行只需要5分钟。 如果这个程序重新优化了代码,使用了两个CPU,CPU的利用率依然是100%,那么程序的运行只需要2.5分钟。 从这个例子可以看出,CPU使用率对程序使用CPU的效率有反应,CPU使用率越高,程序性能越好,反之亦然。

在Linux操作系统上运行vmstat 5命令会得到类似清单1的数据。 每5秒增加一行。 为了清楚起见,本例中的程序只在单线程上运行,同样适用于多线程环境。 从示例数据第一行的数据可以看出,5秒钟内CPU总共使用2.25秒(5*(37% 8% ) ) ),其中37%用于执行用户代码,8%用于执行系统代码。 剩下的2.75秒CPU处于空闲状态(idle )。

列表1. vmstat 5命令的结果

CPU空闲的原因有以下三个。

在解除锁定之前,APP应用程序将被线程同步操作阻止。APP应用程序正在等待特定请求的响应,例如正在等待数据查询请求的响应。 无法进行APP的前两种情况很容易理解,也有相应的调整方式。 第一个原因是,如果能够减轻锁定冲突或调整数据库返回请求资源的性能,APP应用程序将更快地运行。第二个原因是,在优化请求响应端和提高响应速度的其他条件不变的情况下,APP应用程序将更

第三种情况是,如果APP应用程序有事,CPU会利用CPU循环执行APP应用程序的代码。 这是共同的规则。 执行无限循环的代码时,CPU会再消耗100%的时间,如。 如果CPU利用率未达到100%,则操作系统必须执行无限循环,但不执行,而是处于空闲状态。 这种情况对无限循环的影响不大,但是如果我们的程序用于计算公式的结果,这种情况会减慢计算速度。

清单2 .无限循环代码

如果在单核计算机上运行清单2中的代码,大部分时间都不会注意到它正在运行。 但是,如果启动另一个程序或监视另一个程序的性能,就会出现这种影响。 虽然操作系统很擅长使用时间片程序来竞争CPU周期,但是最近启动的程序只获得了很少的可用CPU周期。 解决问题的一个方法是将空闲的CPU循环设置为一定的比例,从而使其他程序不需要使用CPU。 但是,在这种情况下,很明显的问题是,操作系统不知道下一个操作,操作系统只能执行当前的所有操作,而不保留空闲的CPU周期。

>

Java 和单 CPU 使用率

我们回到 Java 应用程序,周期性的 CPU 闲置意味着什么呢?这取决于应用程序的类型。对于有固定作业量的批处理程序,除非全部作业完成,否则 CPU 不会有闲置时间。提高 CPU 的使用率可以使批处理程序更快地完成。如果 CPU 使用率已经达到 100%,我们可以在保持 CPU 使用率 100%的前提下从其他方面进行优化使程序完成地更快。

对于接收请求的服务器类型的应用程序,在没有请求到来的时候,CPU 会处于闲置状态。举例来说,当 Web 服务器处理完当前所有 HTTP 请求处于等待下一个请求的状态时,CPU 为闲置状态。从这里可以理解 CPU 使用率为何为一定时间间隔内的平均数值。上文 vmstat 示例中的数据采集自一个应用服务器的运行过程中,这个服务器每 5 秒接收到一个请求,花费 2.25 秒处理,这意味着在这 2.25 秒内 CPU 的使用率为 100%,而在剩下的 2.75 内使用率为 0。由此计算得出 CPU 使用率为 45%。

这种情况总是发生在非常短的时间间隔内,因此很难被发现,但是这种类似应用服务器的程序总是按照此方式运行。当我们降低时间间隔,上述应用服务每 2.5 秒接受一个请求同时花费 1.125 秒处理请求,剩余的 1.375 秒 CPU 处于闲置状态。平均下来,CPU 平均使用率依然为 45%,55%的时间处于闲置状态。

优化应用服务器之后,处理每个请求只需要 2 秒,CPU 使用率将降至 40%。降低 CPU 使用率是我们优化程序代码的目标。只有在单位时间内,没有外部资源约束的应用程序负载固定。从另一方面来讲,优化这种应用程序可以适当增加程序负载来提升 CPU 使用率。这样一来,可以看出这种优化策略依然遵循前文的规则,即在尽可能短的时间内使 CPU 使用率尽可能高。

Java 和多 CPU 使用率

调优多线程程序的目标依然是尽可能的提高每个 CPU 的使用率,使 CPU 尽可能少的被阻塞。在多核多线程环境中,当 CPU 处于闲置状态时需要多考虑的是即使应用程序有作业未完成,CPU 依然会处于闲置状态,因为该应用程序中没有可用的线程来处理作业。最典型的例子为一个拥有固定大小线程池的应用程序运行数量变化的任务。每个线程每次只能处理一个任务,如果此线程被某些操作阻塞,这个线程不能转而去处理另一个任务。在这种情况下就会出现没有可用线程来处理未完成的任务。因此会导致 CPU 处于闲置状态。对于此种情形应该考虑如何增加线程池的大小来完成更多的任务。

监控 CPU 使用率只是理解应用程序性能的第一步,这只能确定代码的 CPU 使用率是否达到开发人员的期望,或者找到代码中存在的同步问题和资源问题。

CPU Run Queue

在 Windows 和 UNIX 系统中都可以监控当前可以执行任务的线程数。UNIX 系统中称为 Run Queue,有很多工具可以查到此数据。例如前文中的 vmstat,每行的第一个数字即是 Run Queue 的长度。Windows 系统中称之为 Processor Queue,可以通过 typeperf 命令查到。

Windows 与 UNIX 的区别是:在 UNIX 中,Run Queue 长度为当前正在运行和可以运行的线程数,所以这个长度最小为 1;而在 Windows 中,Processor Queue 长度并不包括正在运行的线程数,因此 Processor Queue 长度最小值为 0。

当可用线程数大于可用 CPU 数量,性能就会下降。所以在 Windows 中 Processor Queue 长度为 0,在 UNIX 中 Run Queue 长度等于 CPU 数的情况性能达到最好。但这并不绝对,因为系统程序中会周期性运行导致此数值增大,单对应用程序的影响不大。如果 Run Queue 长度长时间远远大于 CPU 数,表示机器负载过大,应该适当减少当前机器的作业量。

硬盘使用率

监控硬盘使用率有两个重要的目标,一是应用程序本身,如果应用程序进行了非常多的硬盘 I/O 操作,很容易推断出应用程序的性能瓶颈在于 I/O。

需要进行详细的监控才能发现应用程序的性能瓶颈在于 I/O。当应用程序没有高效地使用缓存来进行硬盘写操作时,硬盘 I/O 的数据将会非常低。但是当应用程序进行的 I/O 操作数超出了硬盘能够处理的数量,硬盘 I/O 数据将会非常高。这两种情况都需要进行调优。

在 Linux 系统中执行 iostat -xm 5 命令可以得到清单 3 中的数据:

清单 3. iostat –xm 5 命令结果一

应用程序在向硬盘 sda 中写入数据,看上去硬盘写入的时间情况还不错,每次写入等待时间(await)为 5.04 毫秒,硬盘使用率也仅为 2.02%。但仔细来看,系统执行内核代码用掉 40.2%的时间,这是意味着应用程序中存在低效的写操作。系统每秒进行 34.60(w/s)次写操作,但是只写入了 0.23MB(wMB/s) 数据。可以判断 I/O 是应用程序的性能瓶颈所在。下一步将分析应用程序如何进行写操作。

再看另一组数据(清单 4),硬盘使用率(%util)达到 100%,等待硬盘的时间占到了 49.81%(%iowait),应用程序每秒写入 60.45mb 数据,这些数据共同证明 I/O 是应用程序的性能瓶颈所在,必须减少如此大量的 I/O 操作。

清单 4. iostat –xm 5 命令结果二

监控硬盘使用率的另一个作用是得知系统是否在进行交换(swapping),计算机拥有固定数量的物理内存,但是它可以运行使用内存远远大于其物理内存的一些应用程序。应用程序占有的内存往往多于它们真正需要的内存,在这种情况下,操作系统将这些没有被用到内存挪入硬盘,当需要的时候将它们通过换页换进物理内存中。对于大多数应用程序,这种内存管理方式是不错的,但是对于服务器类型的应用程序而言,这种方式就显得尤为糟糕,因为由于 Java 内存堆的存在,服务器类型的应用往往需要用到非常多的物理内存。

由于需要将硬盘中的数据与物理内存中的数据进行交换,会严重影响系统性能。vmstat 命令的结果中 si,so 两列数据表示了换入物理内存和换出物理内存的数据量。通过这些数据可以知道系统是否在进行交换。

网络使用率

如果应用程序运行过程中使用了网络,在进行性能监控时必须监控系统网络传输使用率。网络传输类似于硬盘传输,低效地使用网络传输会造成网络带宽不足;如果网络传输的数据量超过了其所能负载的上限同样会造成网络传输性能瓶颈。

操作系统内置的网络监控工具只能获得某个网络接口接收和发送的包数和字节数。通过这些信息还不足以确定网络负载正常还是负载过大。

在 UNIX 系统中,基本的网络监控工具是 netstat。

当然,还有非常多的第三方网络监控工具,nicstat 就是 UNIX 系统中使用很广泛的一个命令行工具,通过这个工具可以得到指定网络接口的使用率。

执行 nicstat 5 命令,得到清单 5 中的数据,从数据中可以看到,网络接口 e1000g1 为 1000MB 接口,该接口使用率只有 2.98%(%Util),每秒钟通过此接口读入 156.4Kb 数据,写入 256.9Kb 数据,通过这些数据,可以明确得出网络接口的带宽以及使用率。

清单 5. nicstat 5 命令结果

如果只用 netstat 命令,可以获得每秒读写的数据量,但是必须知道网络带宽并且通过额外的脚本才能计算得出网络接口的使用率。在计算过程中需要注意,带宽单位为位每秒(bps),因此 1000Mb 带宽每秒可以传输 125MB 数据。而在 nicstat 已经帮我们做了类似的计算。

网络传输无法支撑 100%的使用率,在本地以太网网络,超过 40%的使用率就被认为接口饱和。使用其他媒介进行网络传输的饱和使用率需要咨询网络架构师。Java 程序只是使用操作系统的网络接口进行传输,并不能决定网络使用率的饱和值。

总结

本文在性能监测和优化方面给出了多种方法,并结合 CPU 时间特性阐述了其性能影响的因素和原因。总体上讲,性能监测首先应当从应用程序运行时所消耗的 CPU 时间来入手,剖析其运行状态,以及资源消耗的瓶颈在哪里。其次,以 CPU 使用率的提升为目标来优化代码。

性能监测还可以通过监测硬盘的使用情况来获得,大量硬盘的读写将会产生应用程序的性能问题,这就要求我们的程序设计人员在设计程序的时候尽量降低减少磁盘的读写操作,以及读写的数据量,并采用缓存交换的数据的形式提升应用程序性能。

对基于网络的应用程序,监测其网络传输的开销,也是性能监测的一种方法。大量数据在网络层面上的交换也会带来性能上的开销。

最后,本文讲解了 Java 自带的性能分析工具的使用,在使用这些工具的时候请大家铭记一点,

没有一个完美的工具来帮您完全理解应用程序的整体性能问题,实际工作中我们可能需要结合多种工具来完成一个应用程序的性能分析。不同的工具有不同的方向,全方面的理解和使用才能够更好的完成分析任务。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。