在很久以前,就對(duì)性能調(diào)優(yōu)有非常濃厚的興趣邪财。雖然之前也在做過一些性能調(diào)優(yōu)的工作拧抖,但是主要集中在代碼層面,以及業(yè)務(wù)層面坝初。對(duì)如何從Linux操作系統(tǒng)方面進(jìn)行調(diào)優(yōu),一直都沒有一個(gè)清晰的認(rèn)識(shí)钾军。不過鳄袍,最近偶然發(fā)現(xiàn)了一本IBM出的Linux調(diào)優(yōu)指南,于是就拜讀了一下吏恭。
讀完一些之后拗小,就發(fā)現(xiàn)這本書確實(shí)就是我所需要的一本書。
雖然之前讀過一些關(guān)于操作系統(tǒng)的書籍樱哼,但是并不懂如何把它們應(yīng)用到性能調(diào)優(yōu)中哀九。而從網(wǎng)上看到的一些關(guān)于性能調(diào)優(yōu)的文章,也主要是集中在檢測(cè)并發(fā)現(xiàn)性能瓶頸這些我們?cè)缇颓宄膬?nèi)容搅幅。對(duì)于發(fā)現(xiàn)瓶頸之后阅束,如何調(diào)優(yōu),從哪些方面進(jìn)行調(diào)優(yōu)茄唐,這背后的原理是什么息裸,為什么要這么調(diào)優(yōu),卻沒有詳細(xì)的說明沪编。
而這本書恰恰彌補(bǔ)了這個(gè)空缺界牡。彌補(bǔ)了操作系統(tǒng)高層理論以及底層調(diào)優(yōu)之間的空缺。我們熟悉的操作系統(tǒng)漾抬,以及計(jì)算機(jī)網(wǎng)絡(luò),他們的處理過程常遂,都是一些可以優(yōu)化的點(diǎn)纳令。
這本書,其實(shí)稱為指南更合適克胳。從CPU平绩,內(nèi)存,IO漠另,計(jì)算機(jī)網(wǎng)絡(luò)等方面捏雌,一一為我們展示了優(yōu)化的過程。
這本指南也不厚笆搓,大概只有160頁(yè)性湿。內(nèi)容不多纬傲,非常精簡(jiǎn)。同時(shí)也造成了一個(gè)缺點(diǎn)肤频,就是叹括,很多內(nèi)容并不能全面鋪開。
但是感覺用這本指南來進(jìn)入性能調(diào)優(yōu)的世界宵荒,還是綽綽有余的汁雷。
這本指南的名稱是,《Linux Performance and Tuning Guidelines》报咳。
這篇文章侠讯,便是我在讀完這本指南的時(shí)候,摘錄的一些筆記暑刃。
CPU方面
處理器指標(biāo)
- CPU使用率: 每個(gè)處理器的利用率
- user time: CPU執(zhí)行用戶代碼的時(shí)間厢漩,包括nice time
- system time: CPU執(zhí)行內(nèi)核代碼的時(shí)間,包括IRQ和softirq time
- waiting: CPU等待IO的時(shí)間
- Idle time: CPU空閑并等待任務(wù)的時(shí)間
- nice time: CPU花在改變進(jìn)程優(yōu)先級(jí)以及執(zhí)行順序的時(shí)間
- load average: 任務(wù)隊(duì)列中稍走,等待被CPU執(zhí)行的任務(wù)的總數(shù)袁翁,以及那些等待不可中斷任務(wù)完成的任務(wù)的總數(shù),它們的平均值婿脸。也就是粱胜,系統(tǒng)中處于TASK_RUNNABLE以及TASK_UNINTERRUPTIBLE狀態(tài)的任務(wù)的總數(shù)的平均值。
- Runnable process: 等待被CPU執(zhí)行的任務(wù)的總數(shù)
- Blocked: 那些因?yàn)镮O操作被掛起的進(jìn)程的數(shù)量
- Context switch: 系統(tǒng)中線程切換的總數(shù)狐树。
- Interrupt: 硬中斷和軟中斷的次數(shù)焙压。
消除CPU瓶頸的方法
- 確保后臺(tái)沒有不必要的程序
- 給那些不重要并且是CPU密集型的應(yīng)用調(diào)整優(yōu)先級(jí),讓其優(yōu)先級(jí)相對(duì)較低一些
- 更新CPU
內(nèi)存方面
內(nèi)存指標(biāo)
- Free memory: 空閑內(nèi)存抑钟。在Linux中涯曲,內(nèi)核會(huì)將沒有使用的內(nèi)存中的大部分分配給文件系統(tǒng)緩存。所以在塔,F(xiàn)ree memory減去buffers以及cache占用的內(nèi)存的數(shù)量幻件,才是系統(tǒng)中真正的空閑內(nèi)存的數(shù)量。
- swap usage: swap in/out衡量?jī)?nèi)存是否出現(xiàn)了瓶頸才更加正確蛔溃。因?yàn)長(zhǎng)inux內(nèi)核如果發(fā)現(xiàn)內(nèi)存中的一些page绰沥,長(zhǎng)時(shí)間沒有被用到,就回將它放到swap中贺待。而并不是說徽曲,只有當(dāng)內(nèi)存不足的時(shí)候,才會(huì)將page放到swap中麸塞。如果每秒有200-300次 swap in/out秃臣,那么說明系統(tǒng)的內(nèi)存可能是瓶頸。
- Buffer and cache: 為文件系統(tǒng)和block size分配的緩存
- slab: 內(nèi)核使用的內(nèi)存數(shù)量哪工。需要注意的是奥此,內(nèi)核使用的page不能被page out到磁盤中
- active versus inactive memory: inactive memory將會(huì)被kswapd daemon swap out到磁盤中弧哎。
free工具輸出解釋
消除內(nèi)存瓶頸的方法
- 調(diào)整page的大小
- 調(diào)整處理active和inactive內(nèi)存的方式
- 降低page-out的速度
- 限制服務(wù)器上每個(gè)用戶能夠使用的內(nèi)存的數(shù)量
- 停止不需要的service
- 增加內(nèi)存
文件系統(tǒng)方面
文件系統(tǒng)指標(biāo)
- IOWait: CPU等待IO操作的時(shí)間
- Average queue length: 未完成的IO請(qǐng)求的數(shù)量
- Average wait: IO請(qǐng)求等待被處理的時(shí)間,毫秒級(jí)
- Transfers per second: 每秒有多少IO操作被執(zhí)行
- Blocks read/write per seconds: 每秒中讀和寫block的數(shù)量得院。在2.6版本的內(nèi)核中傻铣,以block大小為1KB衡量。不同的內(nèi)核版本中祥绞,block大小不同非洲,從512bytes到4KB不等
- Kilobytes per second read/write: 每秒讀寫block device的數(shù)據(jù)量,用kilobytes來衡量
Linux中常見的文件系統(tǒng)
- Ext2
- Ext3
- ReiserFS
- Journal File System(JFS)
- XFS
其中蜕径,Ext3能夠保證數(shù)據(jù)的一致性两踏。而且,還能夠通過配置journal mode兜喻,在數(shù)據(jù)的完整性和速度之間取得一個(gè)較好的平衡梦染。
而JFS和XFS,主要用在需要支持大文件的場(chǎng)景中朴皆。
消除文件系統(tǒng)瓶頸的方法
- 如果程序訪問磁盤的方式是順序訪問帕识,那么就換一個(gè)更好的磁盤控制器。如果是隨機(jī)訪問的遂铡,那么就增加更多的磁盤控制器
- 使用RAID肮疗。RAID的讀性能比較高,但是寫性能低一些扒接。而且伪货,優(yōu)先使用基于硬件實(shí)現(xiàn)的RAID。
- 給磁盤合理分區(qū)
- 增加內(nèi)存
- 通過/proc/sys/vm/dirty_background_ratio來調(diào)整內(nèi)存中有多少臟數(shù)據(jù)時(shí)钾怔,pdflush daemon才將這些數(shù)據(jù)寫入到磁盤
- 通過ionice來分配IO操作的優(yōu)先級(jí):
- idle: 最低的優(yōu)先級(jí)碱呼,只有當(dāng)沒有高優(yōu)先級(jí)的進(jìn)程訪問磁盤時(shí),才有資格訪問磁盤
- Best-effort: 默認(rèn)優(yōu)先級(jí)宗侦。從CPU優(yōu)先級(jí)中繼承
- Real time: 最高的優(yōu)先級(jí)愚臀。進(jìn)程總是能夠訪問磁盤。
- 禁止access time updates
- 選擇合適的文件系統(tǒng)矾利,以及合適的journal模式
- 調(diào)整block size:
如果你的服務(wù)器懊悯,更多的是處理小的文件,那么將block size調(diào)小一點(diǎn)梦皮,可能會(huì)提高性能。但是如果處理大文件更多桃焕,那么調(diào)大一點(diǎn)可能會(huì)提高性能剑肯。但是這一項(xiàng)對(duì)性能提升并不大,所以观堂,默認(rèn)使用操作系統(tǒng)的4k的block size就好让网。
網(wǎng)絡(luò)方面
網(wǎng)絡(luò)指標(biāo)
- Packets received and sent
- Bytes received and sent
- Collisions per second: 網(wǎng)絡(luò)中發(fā)生的碰撞數(shù)量呀忧。一個(gè)配置正確的網(wǎng)絡(luò)中,應(yīng)當(dāng)很少發(fā)生碰撞
- Packet dropped: 被丟棄的包的數(shù)量溃睹。包括被防火墻過濾掉的而账,以及由于buffer空間不夠而丟掉的
- Overruns: buffer空間溢出的次數(shù)
- Errors: 出錯(cuò)的包的數(shù)量
數(shù)據(jù)傳輸?shù)倪^程
- 應(yīng)用程序開啟一個(gè)Socket并將數(shù)據(jù)寫入到這個(gè)Socket的buffer中
- 數(shù)據(jù)經(jīng)過TCP/IP協(xié)議棧一層層地做一些處理,包裝因篇。數(shù)據(jù)并不會(huì)層層復(fù)制泞辐,因?yàn)檫@樣性能不好。在內(nèi)核中竞滓,只是修改buffer中的引用咐吼,將其傳遞給下一層
- 數(shù)據(jù)通過網(wǎng)絡(luò)到達(dá)另一臺(tái)主機(jī),我們暫且稱它為主機(jī)B
- 如果這個(gè)包的MAC地址就是主機(jī)B商佑,那么把它放到主機(jī)B的socket buffer中
- 主機(jī)B給CPU發(fā)出一個(gè)硬中斷
- 主機(jī)B再將數(shù)據(jù)通過TCP/IP協(xié)議棧的層層處理锯茄,傳遞給應(yīng)用層
Linux中的協(xié)議棧,更注重的是可靠性和低延遲茶没,而不是低開銷和高吞吐量肌幽。
由于每一個(gè)數(shù)據(jù)包都會(huì)引發(fā)一次中斷,所以抓半,Linux中引入了一項(xiàng)叫做NAPI的技術(shù)喂急。當(dāng)?shù)谝粋€(gè)數(shù)據(jù)包到來時(shí),還是跟之前一樣琅关,會(huì)引發(fā)一次中斷煮岁。但是從此之后,網(wǎng)絡(luò)接口會(huì)啟動(dòng)輪訓(xùn)模式涣易,即画机,當(dāng)有數(shù)據(jù)包到達(dá)時(shí),不會(huì)發(fā)出中斷新症,而是直到buffer都滿了的時(shí)候步氏,才發(fā)出一個(gè)中斷。這樣就能減少中斷的次數(shù)徒爹。
TCP/IP傳輸窗口
TCP/IP傳輸窗口指的是荚醒,在收到ACK響應(yīng)之前,最多能夠發(fā)送的數(shù)據(jù)量隆嗅。接收主機(jī)會(huì)通過TCP首部中的window size字段告訴發(fā)送主機(jī)傳輸窗口的大小界阁。通過使用傳輸窗口,TCP能夠處理地效率更高一些泡躯,因?yàn)榘l(fā)送主機(jī)不需要等待每一個(gè)數(shù)據(jù)包的ACK。
高速網(wǎng)絡(luò)中,可以使用一種叫做窗口伸縮的技術(shù)较剃,來增加傳輸窗口的大小。
Offload
如果你的網(wǎng)絡(luò)適配器支持offload功能写穴,那么你可以內(nèi)核就可以將一部分工作轉(zhuǎn)移到網(wǎng)絡(luò)適配器惰拱,來減少CPU的工作量,進(jìn)而提高性能啊送。
常見的offload功能有:
- Checksum Offload: 每一個(gè)數(shù)據(jù)包中偿短,都會(huì)有一個(gè)校驗(yàn)碼,用于驗(yàn)證這個(gè)數(shù)據(jù)包是否在傳輸過程中出現(xiàn)了問題
- TCP segmentation offload: 當(dāng)要傳輸?shù)臄?shù)據(jù)量大于MTU的時(shí)候删掀,就要對(duì)數(shù)據(jù)進(jìn)行分段處理翔冀。
消除網(wǎng)絡(luò)瓶頸的方法
- 確保網(wǎng)卡的配置和路由器以及交換機(jī)的配置配套
- 調(diào)整網(wǎng)絡(luò)的拓?fù)浣Y(jié)構(gòu)
- 使用更快的網(wǎng)卡
- 在內(nèi)核中調(diào)整關(guān)于網(wǎng)絡(luò)的參數(shù)
- MTU
- 接收和發(fā)送緩沖區(qū)的大小
- 傳輸窗口
- 通過調(diào)整net.ipv4.tcp_tw_reuse參數(shù)讓處于
TIME_WAIT
狀態(tài)的Socket對(duì)新連接可重用 - 通過調(diào)整tcp_fin_timeout參數(shù),讓處于
FIN-WAIT-2
狀態(tài)的Socket可以早一些關(guān)閉披泪,進(jìn)而節(jié)省內(nèi)存 - 通過調(diào)整tcp_keepalive_time參數(shù)纤子,調(diào)整keepalive連接的關(guān)閉時(shí)間
- 通過調(diào)整tcp_max_syn_backlog參數(shù)來調(diào)整最大能夠容納的處于半連接狀態(tài)的socket的數(shù)量
- 關(guān)閉一些不需要的服務(wù),以及端口號(hào)
Linux的工具
性能監(jiān)控工具
- top
- vmstat
- uptime, w
- ps, pstree
- free
- iostat
- sar
- mpstat
- numastat
- pmap
- netstat
- iptraf
- tcpdump, etheral
- nmon
- strace
- proc file system
- KDE System guard
- Gnome System Monitor
分析工具
- lmbench
- iozone
- netperf
/proc
/proc目錄中的內(nèi)容款票,對(duì)于查看系統(tǒng)狀態(tài)控硼,應(yīng)用程序的狀態(tài)至關(guān)重要。
/proc目錄中艾少,又有這么幾塊:
- 名稱為數(shù)字的目錄:每一個(gè)這樣的目錄卡乾,里面都包含了pid為這個(gè)數(shù)字的對(duì)應(yīng)的進(jìn)程的信息,比如缚够,進(jìn)程使用的虛擬內(nèi)存
- acpi: ACPI中包含一些高級(jí)配置幔妨,以及電源管理等信息。因?yàn)锳CPI主要是用在筆記本谍椅,或者個(gè)人PC中误堡,所以,在服務(wù)器上雏吭,一般是禁用的
- bus: 包含了一些和bus相關(guān)的信息锁施,比如PCI bus或者USB接口
- irq: 包含和中斷相關(guān)的信息。每個(gè)子目錄都對(duì)應(yīng)一種中斷杖们。我們可以通過直接修改對(duì)應(yīng)子目錄的信息悉抵,來將中斷綁定到一個(gè)CPU上
- net: 包含和網(wǎng)絡(luò)相關(guān)的統(tǒng)計(jì)信息
- scsi: 包含和SCSI相關(guān)的信息
- sys: 包含和內(nèi)核相關(guān)的參數(shù)
- tty: 包含和tty相關(guān)的信息
從安裝Linux就開始調(diào)優(yōu)
考慮下面幾個(gè)問題:
- 安裝什么版本的Linux?
- 商業(yè)版的還是開源版本的?
- 選擇商業(yè)版的哪一個(gè)版本摘完?
- 選擇正確的內(nèi)核
有這么幾種內(nèi)核姥饰。- standard: 應(yīng)用在單處理器上
- SMP: 支持SMP以及超線程技術(shù)。一些實(shí)現(xiàn)也支持NUMA.
- Xen: 包括一個(gè)可以在Xen虛擬機(jī)上運(yùn)行的Linux版本
- 如何給磁盤分區(qū)孝治?
盡可能使用交換分區(qū)而不是交換文件列粪。交換分區(qū)相對(duì)于交換文件來講栅螟,沒有文件系統(tǒng)上的開銷。 - 使用什么文件系統(tǒng)篱竭?
- 安裝時(shí),盡可能少安裝包還是安裝全部的包步绸?
- 防火墻配置
- SELinux
- Runlevel選擇
除非有特別需求掺逼,否則服務(wù)器上都是使用runlevel 3.