如何用九条命令在一分钟内检查Linux服务器性能

如何用九条命令在一分钟内检查Linux服务器性能,第1张

一、uptime命令

这个命令可以快速查看机器的负载情况。在Linux系统中,这些数据表示等待CPU资源的进程和阻塞在不可中断IO进程(进程状态为D)的数量。这些数据可以让我们对系统资源使用有一个宏观的了解。

命令的输出分别表示1分钟、5分钟、15分钟的平均负载情况。通过这三个数据,可以了解服务器负载是在趋于紧张还是趋于缓解。如果1分钟平均负载很高,而15分钟平均负载很低,说明服务器正在命令高负载情况,需要进一步排查CPU资源都消耗在了哪里。反之,如果15分钟平均负载很高,1分钟平均负载较低,则有可能是CPU资源紧张时刻已经过去。

上面例子中的输出,可以看见最近1分钟的平均负载非常高,且远高于最近15分钟负载,因此我们需要继续排查当前系统中有什么进程消耗了大量的资源。可以通过下文将会介绍的vmstat、mpstat等命令进一步排查。

二、dmesg命令

该命令会输出系统日志的最后10行。示例中的输出,可以看见一次内核的oom kill和一次TCP丢包。这些日志可以帮助排查性能问题。千万不要忘了这一步。

三、vmstat命令

vmstat(8) 命令,每行会输出一些系统核心指标,这些指标可以让我们更详细的了解系统状态。后面跟的参数1,表示每秒输出一次统计信息,表头提示了每一列的含义,这几介绍一些和性能调优相关的列:

r:等待在CPU资源的进程数。这个数据比平均负载更加能够体现CPU负载情况,数据中不包含等待IO的进程。如果这个数值大于机器CPU核数,那么机器的CPU资源已经饱和。

free:系统可用内存数(以千字节为单位),如果剩余内存不足,也会导致系统性能问题。下文介绍到的free命令,可以更详细的了解系统内存的使用情况。

si,so:交换区写入和读取的数量。如果这个数据不为0,说明系统已经在使用交换区(swap),机器物理内存已经不足。

us, sy, id, wa, st:这些都代表了CPU时间的消耗,它们分别表示用户时间(user)、系统(内核)时间(sys)、空闲时间(idle)、IO等待时间(wait)和被偷走的时间(stolen,一般被其他虚拟机消耗)。

上述这些CPU时间,可以让我们很快了解CPU是否出于繁忙状态。一般情况下,如果用户时间和系统时间相加非常大,CPU出于忙于执行指令。如果IO等待时间很长,那么系统的瓶颈可能在磁盘IO。

示例命令的输出可以看见,大量CPU时间消耗在用户态,也就是用户应用程序消耗了CPU时间。这不一定是性能问题,需要结合r队列,一起分析。

四、mpstat命令

该命令可以显示每个CPU的占用情况,如果有一个CPU占用率特别高,那么有可能是一个单线程应用程序引起的。

五、pidstat命令

pidstat命令输出进程的CPU占用率,该命令会持续输出,并且不会覆盖之前的数据,可以方便观察系统动态。如上的输出,可以看见两个JAVA进程占用了将近1600%的CPU时间,既消耗了大约16个CPU核心的运算资源。

六、iostat命令

r/s, w/s, rkB/s, wkB/s:分别表示每秒读写次数和每秒读写数据量(千字节)。读写量过大,可能会引起性能问题。

await:IO *** 作的平均等待时间,单位是毫秒。这是应用程序在和磁盘交互时,需要消耗的时间,包括IO等待和实际 *** 作的耗时。如果这个数值过大,可能是硬件设备遇到了瓶颈或者出现故障。

avgqu-sz:向设备发出的请求平均数量。如果这个数值大于1,可能是硬件设备已经饱和(部分前端硬件设备支持并行写入)。

%util:设备利用率。这个数值表示设备的繁忙程度,经验值是如果超过60,可能会影响IO性能(可以参照IO *** 作平均等待时间)。如果到达100%,说明硬件设备已经饱和。

如果显示的是逻辑设备的数据,那么设备利用率不代表后端实际的硬件设备已经饱和。值得注意的是,即使IO性能不理想,也不一定意味这应用程序性能会不好,可以利用诸如预读取、写缓存等策略提升应用性能。

七、free命令

free命令可以查看系统内存的使用情况,-m参数表示按照兆字节展示。最后两列分别表示用于IO缓存的内存数,和用于文件系统页缓存的内存数。需要注意的是,第二行-/+ buffers/cache,看上去缓存占用了大量内存空间。

这是Linux系统的内存使用策略,尽可能的利用内存,如果应用程序需要内存,这部分内存会立即被回收并分配给应用程序。因此,这部分内存一般也被当成是可用内存。

如果可用内存非常少,系统可能会动用交换区(如果配置了的话),这样会增加IO开销(可以在iostat命令中提现),降低系统性能。

八、sar命令

sar命令在这里可以查看网络设备的吞吐率。在排查性能问题时,可以通过网络设备的吞吐量,判断网络设备是否已经饱和。如示例输出中,eth0网卡设备,吞吐率大概在22 Mbytes/s,既176 Mbits/sec,没有达到1Gbit/sec的硬件上限。

sar命令在这里用于查看TCP连接状态,其中包括:

active/s:每秒本地发起的TCP连接数,既通过connect调用创建的TCP连接;

passive/s:每秒远程发起的TCP连接数,即通过accept调用创建的TCP连接;

retrans/s:每秒TCP重传数量;

TCP连接数可以用来判断性能问题是否由于建立了过多的连接,进一步可以判断是主动发起的连接,还是被动接受的连接。TCP重传可能是因为网络环境恶劣,或者服务器压

九、top命令

top命令包含了前面好几个命令的检查的内容。比如系统负载情况(uptime)、系统内存使用情况(free)、系统CPU使用情况(vmstat)等。因此通过这个命令,可以相对全面的查看系统负载的来源。同时,top命令支持排序,可以按照不同的列排序,方便查找出诸如内存占用最多的进程、CPU占用率最高的进程等。

但是,top命令相对于前面一些命令,输出是一个瞬间值,如果不持续盯着,可能会错过一些线索。这时可能需要暂停top命令刷新,来记录和比对数据。

ime()、gettimeofday()及GetTickCount()效率比较 time()和gettimeofday()是linux的系统调用,GetTickCount()是windows的函数。

time:返回至1970-1-1 00:00:00至今的秒数; gettimeofday:除了返回秒数外,还有纳秒数,用于更精确的计时; GetTickCount:返回系统启动至今的毫秒数

使用三个函数,分别调用1千万次,测试结果如下: time:约967毫秒; gettimeofday:约1800毫秒; GetTickCount:约70毫秒;

可见,GetTickCount要快很多很多,在linux系统下,频繁使用time及gettimeofday严重影响效率。

1:DateDemo1类

[java] view plain copy

/

取得系统的时间

/

public class DateDemo1 {

public static void main(String args[]) {

Systemoutprintln(SystemcurrentTimeMillis());

}

输出为:1311060393171

执行结果会显示从1970年1月1日开始到取得系统时间为止所经过的毫秒数,例如1115346430703这个数字,但这样的数字没有人确切了解它的意 义是什么,您可以使用Date类别来让这个数字变的更有意义一些

2:DateDemo2类

[java] view plain copy

public class DateDemo2 {

@SuppressWarnings("deprecation")

public static void main(String args[]) {

Date date = new Date();

Systemoutprintln("datetoString: " + datetoString());

Systemoutprintln("date: " + dategetDate());

Systemoutprintln("day: " + dategetDay());

Systemoutprintln("hour: " + dategetHours());

Systemoutprintln("minutes: " + dategetMinutes());

Systemoutprintln("month: " + (dategetMonth() + 1));

Systemoutprintln("seconds: " + dategetSeconds());

Systemoutprintln("time: " + dategetTime());

Systemoutprintln("timezone: " + dategetTimezoneOffset());

Systemoutprintln("year: " + (dategetYear() + 1900));

Calendar calendar = CalendargetInstance();

int year = calendarget(CalendarYEAR);

int month = calendarget(CalendarMONTH) + 1;

int day = calendarget(CalendarDATE);

int hour = calendarget(CalendarHOUR);

int minute = calendarget(CalendarMINUTE);

int second = calendarget(CalendarSECOND);

Systemoutprintln("----------Calendar-------");

Systemoutprintln("year: " + year);

Systemoutprintln("month: " + month);

Systemoutprintln("day: " + day);

Systemoutprintln("hour: " + hour);

Systemoutprintln("minute: " + minute);

Systemoutprintln("second: " + second);

}

}

用date获得时间的值,如时、分、秒、月、日、年得方法已经过时,需要改用Calendar的方法来获取时间的值

输出结果为:

[java] view plain copy

datetoString: Tue Jul 19 15:32:42 CST 2011

date: 19

day: 2

hour: 15

minutes: 32

month: 7

seconds: 42

time: 1311060762362

timezone: -480

year: 2011

----------Calendar-------

year: 2011

month: 7

day: 19

hour: 3

minute: 32

second: 42

3:DateDemo3类

[java] view plain copy

public class DateDemo3 {

public static void main(String args[]) {

Date date = new Date();

/

DateFormat会依电脑上的区域设定显示时间格式,EE表示星期,MM表示月份、dd表示日期,而yyyy是西元,每个字元的设定都各有其意义

从Date-->String

/

DateFormat dateFormat = new SimpleDateFormat("EE-MM-dd-yyyy");

Systemoutprintln(dateFormatformat(date));

DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");

Systemoutprintln(format1format(date));

DateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Systemoutprintln(format2format(date));

/

从String-->Date

/

String dateStr = "2011-7-19";

try {

Date dateTrans = format1parse(dateStr);

//Systemoutprintln(dateTranstoString());

Systemoutprintln(dateTranstoLocaleString()); //转换为本地的形式

} catch (ParseException e) {

eprintStackTrace();

}

}

}

使用DateFormat来格式化日期数据,上面部分为从Date-->String,下面的部分为从String-->Date

输出结果为:

[java] view plain copy

星期二-07-19-2011

2011-07-19

2011-07-19 15:33:27

2011-7-19 0:00:00

4:DateDemo4类

[java] view plain copy

public class DateDemo4 {

public static void main(String[] args) {

Date date = new Date();

DateFormat shortFormat = DateFormatgetDateTimeInstance(DateFormatSHORT, DateFormatSHORT);

DateFormat mediumFormat = DateFormatgetDateTimeInstance(DateFormatMEDIUM, DateFormatMEDIUM);

DateFormat longFormat = DateFormatgetDateTimeInstance(DateFormatLONG, DateFormatLONG);

DateFormat fullFormat = DateFormatgetDateTimeInstance(DateFormatFULL, DateFormatFULL);

Systemoutprintln(shortFormatformat(date));

Systemoutprintln(mediumFormatformat(date));

Systemoutprintln(longFormatformat(date));

Systemoutprintln(fullFormatformat(date));

}

}

输出结果为:

[java] view plain copy

11-7-19 下午3:33

2011-7-19 15:33:54

2011年7月19日 下午03时33分54秒

2011年7月19日 星期二 下午03时33分54秒 CST

5:DateDemo5类

[java] view plain copy

public class DateDemo5 {

public static void main(String args[]) {

Date date = new Date();

Locale locale = new Locale("en", "US");

DateFormat shortDateFormat = DateFormatgetDateInstance(DateFormatSHORT, locale);

DateFormat mediumDateFormat = DateFormatgetDateInstance(DateFormatMEDIUM, locale);

DateFormat longDateFormat = DateFormatgetDateInstance(DateFormatLONG, locale);

DateFormat fullDateFormat = DateFormatgetDateInstance(DateFormatFULL, locale);

Systemoutprintln(shortDateFormatformat(date));

Systemoutprintln(mediumDateFormatformat(date));

Systemoutprintln(longDateFormatformat(date));

Systemoutprintln(fullDateFormatformat(date));

}

}

输出结果为:

[java] view plain copy

7/19/11

Jul 19, 2011

July 19, 2011

Tuesday, July 19, 2011

对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里可以尽快的确定程序的性能瓶颈,或者对不同的算法作出有说服力的性能比较。

在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。

本文要介绍的,是另一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第 15页-17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。

在 Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。

在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:

inline unsigned __int64 GetCycleCount()

{

__asm RDTSC

}

但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:

inline unsigned __int64 GetCycleCount()

{

__asm _emit 0x0F

__asm _emit 0x31

}

以后在需要计数器的场合,可以像使用普通的Win32 API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:

unsigned long t;

t = (unsigned long)GetCycleCount();

//Do Something time-intensive

t -= (unsigned long)GetCycleCount();

《Windows图形编程》第15页编写了一个类,把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时,做了一点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在 Celeron 800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿也过于粗糙了。

这个方法的优点是:

1高精度。可以直接达到纳秒级的计时精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法所难以企及的。

2 成本低。timeGetTime 函数需要链接多媒体库winmmlib,QueryPerformance 函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。

3 具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和 QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。

这个方法的缺点是:

1现有的C/C++编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。

2数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。

关于这个方法计时的最大长度,我们可以简单的用下列公式计算:

自CPU上电以来的秒数 = RDTSC读出的周期数 / CPU主频速率(Hz)

64位无符号整数所能表达的最大数字是18×10^19,在我的Celeron 800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。

下面是几个小例子,简要比较了三种计时方法的用法与精度

//Timer1cpp 使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15

//编译行:CL Timer1cpp /link USER32lib

#include &ltstdioh>

#include "KTimerh"

main()

{

unsigned t;

KTimer timer;

timerStart();

Sleep(1000);

t = timerStop();

printf("Lasting Time: %d\n",t);

}

//Timer2cpp 使用了timeGetTime函数

//需包含&ltmmsysh>,但由于Windows头文件错综复杂的关系

//简单包含&ltwindowsh>比较偷懒:)

//编译行:CL timer2cpp /link winmmlib

#include &ltwindowsh>

#include &ltstdioh>

main()

{

DWORD t1, t2;

t1 = timeGetTime();

Sleep(1000);

t2 = timeGetTime();

printf("Begin Time: %u\n", t1);

printf("End Time: %u\n", t2);

printf("Lasting Time: %u\n",(t2-t1));

}

//Timer3cpp 使用了QueryPerformanceCounter函数

//编译行:CL timer3cpp /link KERNEl32lib

#include &ltwindowsh>

#include &ltstdioh>

main()

{

LARGE_INTEGER t1, t2, tc;

QueryPerformanceFrequency(&tc);

printf("Frequency: %u\n", tcQuadPart);

QueryPerformanceCounter(&t1);

Sleep(1000);

QueryPerformanceCounter(&t2);

printf("Begin Time: %u\n", t1QuadPart);

printf("End Time: %u\n", t2QuadPart);

printf("Lasting Time: %u\n",( t2QuadPart- t1QuadPart));

}

////////////////////////////////////////////////

//以上三个示例程序都是测试1秒钟休眠所耗费的时间

file://测/试环境:Celeron 800MHz / 256M SDRAM

// Windows 2000 Professional SP2

// Microsoft Visual C++ 60 SP5

////////////////////////////////////////////////

以下是Timer1的运行结果,使用的是高精度的RDTSC指令

Lasting Time: 804586872

以下是Timer2的运行结果,使用的是最粗糙的timeGetTime API

Begin Time: 20254254

End Time: 20255255

Lasting Time: 1001

以下是Timer3的运行结果,使用的是QueryPerformanceCount API

Frequency: 3579545

Begin Time: 3804729124

End Time: 3808298836

Lasting Time: 3569712

古人说,触类旁通。从一本介绍图形编程的书上得到一个如此有用的实时处理知识,我感到非常高兴。有美不敢自专,希望大家和我一样喜欢这个轻便有效的计时器。

1) 计时,也就是获取当前的时间,使用 gettimeofday(),精度 1 毫秒。x86_64 下是用户态实现,无上下文切换且不陷入内核,效率非常高。

clock_gettime() 精度可到纳秒,但需要陷入内核,效率较低。

2) 定时,使用 timerfd_create() / timerfd_gettime() / timerfd_settime()。实现确保不使用 SIGALRM 信号,避免冲突和多线程问题。精度可到纳秒。

楼上的想让你的程序变成悲剧linux下sleep函数的参数是秒为单位的休眠200秒

睡眠小于1秒用usleep,单位是毫秒

所以,楼上的程序把sleep改成usleep就可以 了

while(1)

{

/ any thing you want to do/

usleep(200);

}

另外我觉得你要说的好像是:希望while循环执行某些 *** 作,执行时间到200毫秒之后退出while循环?

最简单是用间隔定时器

你查下这几个函数:timer_create,timer_settime等。

时间设置比较精确,可以设置一段时间间隔,过了指定的时间之后,会给当前进程发送一个SIGALRM信号,你while循环的条件,可以在SIGALRM的信号处理函数里面修改,这样,到时间之后while就可以退出了

这样写:

//

static char flag=1

int main(void)

{

signal(SIGALRM, timer_handler);

/

申请并且设置间隔定时器的间隔

/

while(flag)

{

/循环内的 *** 作/

}

return 0;

}

void timer_handler(unsigned int signal)

{

flag=0;

}

以上就是关于如何用九条命令在一分钟内检查Linux服务器性能全部的内容,包括:如何用九条命令在一分钟内检查Linux服务器性能、gettickcount linux用什么替代、请教关于linux下java类DateFormat的使用等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9652003.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存