作業系統作為所有程式的基礎,對應用程式的效能有著重要的影響。然而,計算機各個組件之間的速度差異非常大。例如,CPU和硬碟之間的速度差異比兔子和烏龜之間的速度差異還要大。
下面,我們將簡要介紹CPU、記憶體和I/O等方面的基礎知識,並介紹一些評估它們性能的命令。
#首先介紹計算機中最重要的計算組件:中央處理器。一般我們可以透過top指令來觀測它的性能。
top
指令可用來觀測CPU的一些運行指標。如圖,進入top
指令之後,按下1
鍵即可看到每核心CPU的詳細狀況。
CPU的使用有多個維度的指標,以下分別說明一下:
一般的,我們比較關注空閒CPU的百分比,它可以從整體上體現CPU的利用情況。
我們還要評估CPU任務執行的排隊情況,這些值就是負載
#(load)。 top指令,顯示的CPU負載,分別是最近1分鐘、5分鐘、15分鐘的數值。
如圖,以單核心作業系統為例,將CPU資源抽象化成一條單向行駛的馬路。則會發生三種情況:
4
輛,車輛暢通無阻,load大約是0.5。 那load為1代表的是啥?針對這個問題,誤解還是比較多的。
很多同學認為,load達到1,系統就到了瓶頸,這不完全正確。 load的值和cpu核數息息相關。舉例如下:
所以,对于一个load到了10,却是16核的机器,你的系统还远没有达到负载极限。通过uptime命令,同样能够看到负载情况。
要看CPU的繁忙程度,还可以通过vmstat命令。下面是vmstat命令的一些输出信息。
我们比较关注的有下面几列:
b
存在于等待队列的内核线程数目,比如等待I/O等。数字过大则cpu太忙。cs
代表上下文切换的数量。如果频繁的进行上下文切换,就需要考虑是否是线程数开的过多。si
/so
显示了交换分区的一些使用情况,交换分区对性能的影响比较大,需要格外关注。$ vmstat 1 procs ---------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 34 0 0 200889792 73708 591828 0 0 0 5 6 10 96 1 3 0 0 32 0 0 200889920 73708 591860 0 0 0 592 13284 4282 98 1 1 0 0 32 0 0 200890112 73708 591860 0 0 0 0 9501 2154 99 1 0 0 0 32 0 0 200889568 73712 591856 0 0 0 48 11900 2459 99 0 0 0 0 32 0 0 200890208 73712 591860 0 0 0 0 15898 4840 98 1 1 0 0 ^C
要想了解内存对性能的一些影响,就需要从操作系统层面来看一下内存的分布。
我们在平常写完代码后,比如写了一个C++程序,如果去查看它的汇编,可以看到其中的内存地址,并不是实际的物理内存地址。
那么应用程序所使用的,就是逻辑内存,这个学过计算机组成结构的同学都有了解。
逻辑地址可以映射到物理内存和虚拟内存上。比如你的物理内存是8GB,分配了16GB的SWAP分区,那么应用可用的总内存就是24GB。
从top命令可以看到几列数据,注意方块括起来的三个区域,解释如下:
由于CPU核内存之间的速度差异是非常大的,解决方式就是加入高速缓存。其实,这些高速缓存,往往会有多层,如下图。
Java有大部分知识点是围绕多线程的,那是因为,如果一个线程的时间片跨越了多个CPU,那么就会存在同步问题。
在Java中,最典型的和CPU缓存相关的知识点,就是并发编程中,针对Cache line
的伪共享(false sharing)问题。
伪共享是指:在这些高速缓存中,是以缓存行
为单位进行存储的。哪怕你修改了缓存行中一个很小很小的数据,它都会整个的刷新。所以,当多线程修改一些变量的值时,如果这些变量在同一个缓存行里,就会造成频繁刷新,无意中影响彼此的性能。
通过以下命令即可看到当前操作系统的缓存行大小。
cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
通过以下命令可以看到不同层次的缓存大小。
[root@localhost ~]# cat /sys/devices/system/cpu/cpu0/cache/index1/size 32K [root@localhost ~]# cat /sys/devices/system/cpu/cpu0/cache/index2/size 256K [root@localhost ~]# cat /sys/devices/system/cpu/cpu0/cache/index3/size 20480K
在JDK8以上的版本,通过开启参数-XX:-RestrictContended
,就可以使用注解@sun.misc.Contended
进行补齐,来避免伪共享的问题。在并发优化中,我们再详细讲解。
回头看我们最长的那副图,上面有一个叫做TLB
的组件,它的速度虽然高,但容量也是有限的。这就意味着,如果物理内存很大,那么映射表的条目将会非常多,会影响CPU的检索效率。
默认内存是以4K
的page来管理的。如图,为了减少映射表的条目,可采取的办法只有增加页的尺寸。像这种将Page Size加大的技术,就是Huge Page。
HugePage有一些副作用,比如竞争加剧,Redis还有专门的研究(https://redis.io/topics/latency) ,但在一些大内存的机器上,开启后会一定程度上增加性能。
另外,一些程序的默认行为,也会对性能有所影响。比如JVM的-XX:+AlwaysPreTouch
参数。默认情况下,JVM虽然配置了Xmx、Xms等参数,但它的内存在真正用到时,才会分配。
但如果加上这个参数,JVM就会在启动的时候,把所有的内存预先分配。这样,启动时虽然慢了些,但运行时的性能会增加。
I/O设备可能是计算机里速度最差的组件了。它指的不仅仅是硬盘,还包括外围的所有设备。
硬盘有多慢呢?我们不去探究不同设备的实现细节,直接看它的写入速度(数据未经过严格测试,仅作参考)。
可以看到普通磁盘的随机写和顺序写相差是非常大的。而随机写
完全和cpu内存不在一个数量级。
缓冲区依然是解决速度差异的唯一工具,在极端情况比如断电等,就产生了太多的不确定性。这些缓冲区,都容易丢。
最能體現I/O繁忙程度的,就是top指令和vmstat
指令中的wa%
。如果你的應用,寫了大量的日誌,I/O wait就可能非常的高。
對於硬碟來說,可以使用iostat指令來查看特定的硬體使用情況。只要%util超過了80%,你的系統基本上就跑不動了。
詳細介紹如下:
I/O
操作的服務時間。如果svctm
的值與await
很接近,表示幾乎沒有I/O
等待,磁碟效能很好,如果await
的值遠高於svctm
的值,則表示I/O
佇列等待太長,系統上執行的應用程式將會變慢。 #kafka比較快的一個原因就是使用了zero copy。所謂的Zero copy,就是在操作資料時, 不需要將資料buffer從一個記憶體區域拷貝到另一個記憶體區域。因為少了一次記憶體的拷貝, CPU的效率就提升。
我們來看看它們之間的差異:
要想將一個檔案的內容透過socket發送出去,傳統的方式需要經過以下步驟:
零拷貝又多種模式,我們拿sendfile來說明。如上圖,在核心的支援下,零拷貝少了一個步驟,那就是核心快取向使用者空間的拷貝。即節省了內存,也節省了CPU的調度時間,效率很高。
除了iotop、iostat这些命令外,sar命令可以方便的看到网络运行状况,下面是一个简单的示例,用于描述入网流量和出网流量。
$ sar -n DEV 1 Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU) 12:16:48 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil 12:16:49 AM eth0 18763.00 5032.00 20686.42 478.30 0.00 0.00 0.00 0.00 12:16:49 AM lo 14.00 14.00 1.36 1.36 0.00 0.00 0.00 0.00 12:16:49 AM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:16:49 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil 12:16:50 AM eth0 19763.00 5101.00 21999.10 482.56 0.00 0.00 0.00 0.00 12:16:50 AM lo 20.00 20.00 3.25 3.25 0.00 0.00 0.00 0.00 12:16:50 AM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 ^C
当然,我们可以选择性的只看TCP的一些状态。
$ sar -n TCP,ETCP 1 Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU) 12:17:19 AM active/s passive/s iseg/s oseg/s 12:17:20 AM 1.00 0.00 10233.00 18846.00 12:17:19 AM atmptf/s estres/s retrans/s isegerr/s orsts/s 12:17:20 AM 0.00 0.00 0.00 0.00 0.00 12:17:20 AM active/s passive/s iseg/s oseg/s 12:17:21 AM 1.00 0.00 8359.00 6039.00 12:17:20 AM atmptf/s estres/s retrans/s isegerr/s orsts/s 12:17:21 AM 0.00 0.00 0.00 0.00 0.00 ^C
不要寄希望于这些指标,能够立刻帮助我们定位性能问题。这些工具,只能够帮我们大体猜测
发生问题的地方,它对性能问题的定位,只是起到辅助作用。想要分析这些bottleneck,需要收集更多的信息。
想要获取更多的性能数据,就不得不借助更加专业的工具,比如基于eBPF的BCC工具,这些牛x的工具我们将在其他文章里展开。读完本文,希望你能够快速的了解Linux的运行状态,对你的系统多一些掌控。
以上是61秒,摸透Linux的健康狀態!的詳細內容。更多資訊請關注PHP中文網其他相關文章!