如何理解 Linux 中的 load averages

原文:https://mp.weixin.qq.com/s?src=11&timestamp=1533697106&ver=1047&signature=poqrJFfcNABv4biKKpa4mZdIW7No2Wo1F5sbZL7ggoVS2GqcSqwQQ8hMulAmezT*zL*klB-eE5BeMyNuyjuIH7YgkBAN25i6*ahhEpWyxqx6vPct-Vr7q7AU0YGe-F*l&new=1

http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages

經常和 Linux 打交道的童鞋都知道,load averages 是衡量機器負載的關鍵指標,但是這個指標是怎樣定義出來的呢?
和其他系統不同,Linux 上的 load averages 不僅追蹤可運行的任務,還追蹤處于不可中斷睡眠狀態的任務,為什么是這樣呢?這篇文章就來聊聊這方面的知識。
Linux 的 load averages 是系統負載平均值,這個值將正在運行線程(任務)對于系統的需求,作為處于運行和等待狀態的線程的平均數量。大多數工具會顯示 1 分鐘,5 分鐘和 15 分鐘的平均值:

$ uptime17:30:01 up 13 days, 20:30,  3 users,  load average: 1.66, 2.03, 2.08$ cat /proc/loadavg
1.48 1.98 2.06 4/3587 117385

對上面的輸出信息稍稍做些解釋

  • 如果平均值是 0.0,說明系統處于空閑狀態
  • 如果 1 分鐘的平均值大于 5 分鐘或者 15 分鐘,說明系統負載正在增加
  • 如果 1 分鐘的平均值小于 5 分鐘或者 15 分鐘,說明系統負載正在減小
  • 如果這些值大于 CPU 的核數,說明可能遇到了性能問題

利用這三個值,我們可以判斷系統的負載是在增加還是在減小,這在實踐中很有用。這三個中的任意一個拿出來也很有用,比如為云服務的自動伸縮設置閾值。不過,在缺少其他信息的情況下,單看這些值是沒有意義的。比如 1 分鐘的 load averages 值在 23 到 25 之間,就沒有任何意義;但如果知道 CPU 核數并且知道運行的任務是計算密集型,那這個值就很有意義。

歷史

最開始的時候,load averages 只顯示對系統 CPU 相關的需求:運行的進程數加上等待的進程數。如 RFC 546 描述的:

TENEX load averages 是衡量 CPU 需求的指標。這個值是給定時間內可運行進程數量的平均值。例如,對于單核 CPU 系統,每小時平均 10 次意思是在該小時內可以期望看到一個進程正在運行和另外九個等待 CPU(即沒有被 I/O 阻塞) 處于 ready 狀態的進程。

下圖是 1973 年繪制的監控圖:

image

以前操作系統的代碼還可以找到,下面是 TENEX) 定義的一些宏:

NRJAVS==3               ;NUMBER OF LOAD AVERAGES WE MAINTAIN
GS RJAV,NRJAVS          ;EXPONENTIAL AVERAGES OF NUMBER OF ACTIVE PROCESSES
[...]
;UPDATE RUNNABLE JOB AVERAGESDORJAV: MOVEI 2,^D5000MOVEM 2,RJATIM          ;SET TIME OF NEXT UPDATEMOVE 4,RJTSUM           ;CURRENT INTEGRAL OF NBPROC+NGPROCSUBM 4,RJAVS1           ;DIFFERENCE FROM LAST UPDATEEXCH 4,RJAVS1FSC 4,233               ;FLOAT ITFDVR 4,[5000.0]         ;AVERAGE OVER LAST 5000 MS
[...]
;TABLE OF EXP(-T/C) FOR T = 5 SEC.EXPFF:  EXP 0.920043902 ;C = 1 MINEXP 0.983471344 ;C = 5 MINEXP 0.994459811 ;C = 15 MIN

Linux 中定義的宏長下面這樣(代碼出處 include/linux/sched/loadavg.h):

#define EXP_1           1884            /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5           2014            /* 1/exp(5sec/5min) */
#define EXP_15          2037            /* 1/exp(5sec/15min) */

指標的三個粒度

load averages 有 1 分鐘,5 分鐘,15 分鐘三個粒度的結果。不過事實上,他們并不是真正的平均值,統計的粒度也不是 1,5,15 分鐘。從上面的代碼中可以看出,1,5 和 15 都是常量,用于計算指數衰減的 5 秒平均移動和。由此算出的 1 分鐘,5 分鐘和 15 分鐘的 load averages 所反應的負載遠遠超過 1,5,15 分鐘。

假設在一個空閑的系統上,開啟一個單線程來跑 CPU 密集任務,60 秒后 1 分鐘的 load averages 是多少呢?如果 load averages 按普通平均值來算,這個值將是 1.0. 下面是一個繪制成圖的實驗結果:

image

在上面的實驗中,所謂的“1 分鐘 load averages”在一分鐘內只能達到 0.62 左右。

Linux 不可中斷任務

Linux 中剛引入 load averages 時,和其他系統一樣將其作為衡量 CPU 需求的指標,后來將其更改為不僅包含可運行任務,還包含處于不可中斷狀態的任務(TASK_UNINTERRUPTIBLE 或 nr_uninterruptible)。這種狀態由希望避免信號中斷的代碼使用,其中包括阻塞在磁盤 I/O 和一些鎖上的任務。在pstop的輸出中,這種狀態被標志為“D”。ps(1) 的 man page 將其稱為"不可中斷睡眠狀態(通常被 IO 阻塞)"

# man ps
.....
PROCESS STATE CODESHere are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe thestate of a process:D    uninterruptible sleep (usually IO)...

為什么 Linux 中的 load averages 要加入不可中斷狀態呢,而不是像其他系統一樣只計算 CPU 的需求呢?

加入不可中斷的起源

在 oldlinux.org 找到了一封 1993 年的郵件:

From: Matthias Urlichs <urlichs@smurf.sub.org>
Subject: Load average broken ?
Date: Fri, 29 Oct 1993 11:37:23 +0200The kernel only counts "runnable" processes when computing the load average.
I don't like that; the problem is that processes which are swapping or
waiting on "fast", i.e. noninterruptible, I/O, also consume resources.It seems somewhat nonintuitive that the load average goes down when you
replace your fast swap disk with a slow swap disk...Anyway, the following patch seems to make the load average much more
consistent WRT the subjective speed of the system. And, most important, the
load is still zero when nobody is doing anything. ;-)--- kernel/sched.c.orig Fri Oct 29 10:31:11 1993
+++ kernel/sched.c  Fri Oct 29 10:32:51 1993
@@ -414,7 +414,9 @@unsigned long nr = 0;for(p = &LAST_TASK; p > &FIRST_TASK; --p)
-       if (*p && (*p)->state == TASK_RUNNING)
+       if (*p && ((*p)->state == TASK_RUNNING) ||
+                  (*p)->state == TASK_UNINTERRUPTIBLE) ||
+                  (*p)->state == TASK_SWAPPING))nr += FIXED_1;return nr;}
--
Matthias Urlichs        \ XLink-POP N|rnberg   | EMail: urlichs@smurf.sub.org
Schleiermacherstra_e 12  \  Unix+Linux+Mac     | Phone: ...please use email.
90491 N|rnberg (Germany)  \   Consulting+Networking+Programming+etc'ing      42

看到這么久之前的想法還是很令人驚嘆的。

這也證明了 Linux 改變 load averages 的含義,使其不僅體現對 CPU 的需要,是有意的,這讓 load averages 從“CPU 負載均衡”變成了“系統負載均衡”。

郵件中舉交換磁盤速度慢的例子是有道理的:通過降低系統性能,系統需求(運行和排隊的進程數)應該增加;但是如果僅僅根據 CPU 運行狀態,那么 load averages 值應該會下降。Matthias 認為這是不直觀的,所以修改了代碼。

現代系統的不可中斷

但是難道不會出現磁盤 I/O 不能解釋 Linux load averages 過高的情況嗎?這種情況是會出現的,這是因為在現代 Linux(4.12)版本中,有將近 400 處代碼設置了TASK_UNINTERRUPTIBLE狀態,包括一些鎖原語中。其中部分代碼可能不需要統計在 load averages 中。

既然TASK_UNINTERRUPTIBLE在更多的地方被用到,那么是否應該將 load averages 改成只統計 CPU 和磁盤需求呢?Linux 調度程序的維護者 Peter Zijstra 有一個想法:將TASK_UNINTERRUPTIBLE替換成task_struct->in_iowait,這樣 load averages 就更貼近磁盤 I/O 的需求。這樣又引入了另外一個問題,我們到底想要從 load averages 中得到什么?我們是需要用線程對系統的需求來衡量負載,還是只通過物理資源的使用情況來衡量負載呢?如果是前者的話,那么應該包含等待不間斷鎖的線程,因為這些線程并沒有閑置。所以也許 Linux 的 load averages 已經按我們需要的方式工作了。

理解 Linux 的 load averages

也許真正的問題在于“load averages”這個詞和“I/O”一樣含糊不清。到底是哪種 I/O 呢?是磁盤 I/O?文件系統 I/O?還是網絡 I/O。類似的,到底是哪種 load averages 呢?是 CPU 平均負載?還是系統平均負載?下面做一個總結吧:

  • 在 Linux 上,load averages 的真實含義是“系統平均負載”,即對整個系統,測量正在工作并等待工作的線程數(CPU,磁盤,不可中斷鎖)。換句話說,這種方式測量的是不完全空閑的線程數量。這種方式的優勢在于包括了對不同資源的需求。
  • 在其他的系統上,load averages 的含義是“CPU 平均負載”,這組值用于測量正在占有 CPU 執行權的線程數量加上等待 CPU 的線程數量。

還有另一種可能的類型:“物理資源負載平均值”,其中包括僅用于物理資源(CPU+ 磁盤)的負載。

更精確的測量數據

當 Linux 的 load averages 值增加時,可以判斷任務對系統資源(CPU,磁盤和鎖)有了更高的需求,但是到底是對哪種資源的需求增長了呢?這時可以用其他的指標來進行判斷。比如,CPU 資源有如下指標:

  • 單個 CPU 使用率:可以用命令mpstat -P ALL 1查看
  • 每個進程的 CPU 使用率:可用命令toppidstat 1查看
  • 每個線程運行隊列(調度程序)延遲:可用命令perf sched查看,也可以查看文件/proc/PID/schedstats
  • CPU 運行隊列延遲:可用命令perf sched查看,也可以查看文件/proc/schedstat
  • CPU 運行隊列長度:可用vmstat 1命令查看。

上面提供的指標中,前兩個用來衡量使用率,后三個用來度量系統飽和度。利用率指標對于衡量工作負載很有用,而飽和度指標可用來識別性能問題。衡量 CPU 飽和度的最佳指標是運行隊列(或調度程序)的延遲,延遲是指任務或者線程處于可運行狀態,但必須等待 CPU 的時間。通過這樣的指標可以用來衡量性能問題的嚴重程度,比如線程等待調度的時間在運行時間中占的百分比。通過觀察運行隊列長度可以很方便判斷是否存在問題,但比較難定位到問題產生的原因。

schedstats功能在 Linux 4.6 中成為內核可調參數(sysctl.kernel.sched_schedstats),默認是關閉的。

盡管有更明確的指標,但并不意味著 load averages 是無用的。這組指標已經成功用于云計算微服務的擴展策略,微服務根據不同的負載值做出反應。有了這些判斷的依據,即使在自動擴容時犯錯也保險多了:擴容實例會花更多的錢,不擴容則會損失用戶。如果擴容太多,后來調查一下糾正就是了。

總結

在 1993 年,一位 Linux 工程師發現了一個非直觀的 load averages 情況,于是提交了三行代碼的補丁將 load averages 的含義由“CPU 負載平均值”變成了“系統負載平均值”。這次的變動在統計中包括了不可中斷狀態下的任務,所以 load averages 值不僅反映了對 CPU 的需求,還反映了對磁盤資源的需求。系統平均負載計算正在工作和等待工作的線程的數量,并且統計 1 分鐘,5 分鐘,15 分鐘指數衰減的移動總和平均值。通過這三個值,能夠知道系統的負載是在增加還是在減小。

Linux 中對不可中斷狀態的使用越來越多,現在已經包括了不可中斷的鎖原語。如果需要衡量處于運行狀態和等待狀態的線程對于系統的需求,那么 load averages 依然是很好的指標。

最后引用 kernel/sched/loadavg.c 頭部的注釋來結束吧。

  • This file contains the magic bits required to compute the global loadavg
  • figure. Its a silly number but people think its important. We go through
  • great pains to make it work on big machines and tickless kernels.

轉載于:https://www.cnblogs.com/Irving/p/9441553.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250990.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250990.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250990.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jsp+Servlet+MYSQL注冊登錄案例(界面難看,ε=(′ο`*)))唉)

注冊登錄界面尤為常見&#xff0c;我的界面尤為難看&#xff0c;勉為其難的寫吧&#xff0c;前端不熟就是這樣。。。 這個案例運用到了: 1.Jsp動態頁面--->動態頁面 2.Servlet邏輯判斷后臺---->實現界面與數據庫/業務的連接&#xff0c;簡而言之&#xff0c;起承轉合。PS…

ES6-15 map與set

Promise、Proxy、Map、Set這些ES6新增的api無法用babel實現語法降級&#xff0c;需要使用到polyfill Set 成員是唯一的&#xff0c;不能重復有iterator接口&#xff0c;可迭代具有iterator接口的所有類型&#xff0c;都能作為new Set()的參數&#xff0c;如類數組、數組 con…

jquery --- DOM操作、表單元素的初始化

1.獲取ul里第2個li節點: var $li_two $("ul li:eq(1)"); // 獲取該節點的內容 var $li_two_txt $li_two.text();2.獲取p元素節點的title屬性: var $para $("p"); var p_title $para.attr("title");3.創建2個li節點,并添加道ul中: var $li…

Jquery中post與get之間的區別詳細介紹

1:GET訪問瀏覽器認為是等冪的 GET訪問瀏覽器認為是等冪的&#xff0c;就是一個相同的URL只有一個結果&#xff0c;相同是指整個URL字符串完全匹配。所以&#xff0c;第二次訪問的時候&#xff0c;如果URL字符串沒變化 瀏覽器是直接拿出了第一次訪問的結果&#xff1b; POST則認…

LeetCode 424. Longest Repeating Character Replacement

原題鏈接在這里&#xff1a;https://leetcode.com/problems/longest-repeating-character-replacement/description/ 題目&#xff1a; Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at mo…

ES6-16 WeakMap與WeakSet、proxy與reflect

WeakMap/WeakSet 原型上不存在遍歷方法(沒有部署iterator接口)成員只能是對象垃圾回收機制不考慮對成員對象的應用 WeakSet/WeakMap 中的對象都是弱引用&#xff0c;即垃圾回收機制不考慮 WeakSet 對該對象的引用&#xff0c;也就是說&#xff0c;如果其他對象都不再引用該對象…

jquery--- 屬性和樣式的操作 設置和獲取HTML、文本和值、焦點事件

1.獲取p元素的title屬性: var title $("p").attr("title");2.給p元素加title屬性(值為:栗子)和date屬性(值為:2019/7/15): $("p").attr("title":"栗子", "date":"2019/7/15");3.刪除p中的title屬性:…

day9

前方高能---初識函數 一. 什么是函數 函數:對代碼塊和功能的封裝和定義. 二. 函數的定義,函數名,函數體,以及函數的調用 def 函數名(): 函數體 函數體:就是函數被執行之后要執行的代碼. 三, 函數的返回 執行完函數之后,我們可以使用return來返回結果. 函數中return的使用: 1.函…

MySQL 數據庫索引

數據庫索引在數據庫中、索引使數據庫程序無須對整個表進行全表掃描就可以在其中找到所需的數據&#xff1b;數據庫中的索引是某個表中一列或者若干列值的集合、以及物理標識這些值的數據頁的邏輯指針清單&#xff1b;MySQL 索引的增刪查SQL 語句效率的分析索引的作用&#xff1…

ES6-17 class與對象

class 模擬類的方式語法糖&#xff08;把以前的寫法換了一個方式&#xff09; 類內部的方法是不可枚舉的 ES5用Object.assign拓展的原型屬性是可枚舉的 function Point(x, y) {this.x x;this.y y; } // 這樣定義的原型上方法eat\drink是可枚舉的 Point.prototype Object…

8.8 正睿暑期集訓營 Day5

目錄 2018.8.8 正睿暑期集訓營 Day5總結A 友誼巨輪(線段樹 動態開點)B 璀璨光滑C 構解巨樹考試代碼ABC2018.8.8 正睿暑期集訓營 Day5時間&#xff1a;3.5h(實際)期望得分&#xff1a;602020實際得分&#xff1a;202020 比賽鏈接這里也有一些 總結 線段樹&#xff01;&#xff0…

算法 --- 二叉樹的最大深度

思路: 1.二叉樹的深度,等于Max(左子樹最大深度,右子樹最大深度) 1 2.節點不存在時,此時的深度為0 3.當節點存在,左右子樹不存在時(此時為葉子節點) 返回1 /*** Definition for a binary tree node.* function TreeNode(val) {* this.val val;* this.left this.righ…

ES6-18/19 異步的開端-promise

ES6-18異步的開端-promise ES6-19 promise的使用方法和自定義promisify try catch只能捕獲同步異常&#xff0c;不能捕獲異步的 等待所有異步都執行完&#xff0c;打印結果&#xff0c;比較笨拙的方法&#xff0c;在每個異步操作加arr.length 3 && show(arr) Promis…

leetcode35 C++ 4ms 搜索插入位置

class Solution { public:int searchInsert(vector<int>& nums, int target) {for(int i 0;i<nums.size();i){if(nums[i] > target){return i;}}return nums.size()-1;} }; 轉載于:https://www.cnblogs.com/theodoric008/p/9449049.html

OpenCV-Python 中文教程(搬運)目錄

OpenCV-Python 中文教程 OpenCV官方教程中文版&#xff08;For Python&#xff09; OpenCV2-Python-Tutorials 段力輝 譯 說明&#xff1a;搬運自linux公社pdf文件&#xff0c;粗略搬運&#xff0c;僅作個人筆記參考&#xff0c;有時間再美化 部分文件參考&#xff1a; https:/…

算法 --- 平衡二叉樹

解題思路: 1.首先寫一個返回深度的函數d 2.寫一個遍歷函數t 3.在t中首先判斷,r是否為空(為空則此時就是平衡二叉樹,返回true),然后判斷是否為葉子節點(r.left null && r.right null)若是則返回true,最后判斷,其左子樹的深度與右子樹的深度之差是否大于1.若是則返回fal…

【co】ES6-20/21 iterator與generator

ES6-20 iterator與generator ES6-21 async與await、ES6的模塊化 try catch不能捕獲異步異常 try catch是同步代碼 try {setTimeout(() > {console.log(a)}) } catch (e) {console.log(e) }iterator 內部迭代器&#xff1a;系統定義好的迭代器接口&#xff08;如數組Symbol…

嵌入式系統UBOOT

一個完整的嵌入式linux系統包含4部分內容&#xff1a;Bootloader、Parameters、Kernel、Root File System。3、4、5、6部分詳細介紹了這4部分的內容&#xff0c;這是Linux底層軟件開發人員應該掌握的。通過學習這些章節&#xff0c;您可以詳細了解到如何在一個裸板上裁減、移植…

驅動芯片

一 LED驅動芯片&#xff1a; 1.1 TM1640:16位數碼管驅動芯片&#xff0c;2線制控制&#xff08;CLK/DIN&#xff09;,SCLK低電平時DIN輸入&#xff0c;而SCLK高電平時保持DIN保持不變&#xff1b;開始傳輸&#xff1a;SCLKH時DIN由高變低&#xff0c;停止傳輸SCLKH時DIN由由低變…

jquery --- 控制元素的隱藏/顯示

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> </head> <body> <div id"panel"><h5 class"head">什么是jquery?</h5><div class"content" style"display:non…