สมมติฐานพื้นฐานของฉันเกี่ยวกับระบบ“ iowait” ไม่ได้ถือ


13

สมมติฐานพื้นฐานของฉันคือเมื่อกระบวนการ 'จำกัด ปัจจัยเพียงอย่างเดียวคือดิสก์และ CPU ดังนั้นการใช้งาน CPU "iowait" + ระบบทั้งหมดควรเท่ากับ 100% อย่างน้อยหนึ่งโลจิคัล CPU (ในกรณีอื่น ๆ สิ่งนี้จะไม่ถูกเก็บไว้เช่นเมื่อดาวน์โหลดไฟล์โดยใช้wgetเครือข่ายมักเป็นปัจจัย จำกัด )

สมมติฐานนี้ถูกละเมิดโดยการทดสอบอย่างง่าย คาดหวังหรือไม่ หากคาดว่าจะมีเงื่อนไขใดบ้างที่ฉันควรคาดว่าการสันนิษฐานของฉันจะเป็นจริงหรือไม่?

มีพื้นหลังเกี่ยวกับ "iowait" อยู่ที่นี่: CPU รู้ได้อย่างไรว่ามี IO ค้างอยู่ คำตอบที่นี่เป็นการเสนอราคาแนวคิดแบบตอบโต้ง่าย ๆ ว่าไอโออิทแบบสะสม "อาจลดลงในเงื่อนไขบางประการ" ฉันสงสัยว่าการทดสอบอย่างง่ายของฉันสามารถเปิดใช้งานเงื่อนไขที่ไม่มีเอกสารหรือไม่?

UPDATE : กรุณาข้ามไปที่คำตอบ

คำตอบมีการทดสอบที่ง่ายกว่าที่ฉันเคยใช้ ฉันเก็บคำถามเดิมไว้ด้านล่าง คำถามเดิมอาจแสดงรายละเอียดเพิ่มเติมบางอย่าง

คำถามเดิม

ในการทดสอบสั้น ๆ ฉันใช้ddเพื่อขอเคอร์เนลเพื่อสร้างไบต์แบบสุ่มและเขียนลงในไฟล์ ฉันรันddคำสั่งด้านในperf statเพื่อรับจำนวนเวลา CPU ที่ใช้ภายในเคอร์เนล ฉันก็วิ่งเข้าไปข้างในperf trace -sเพื่อรายงานเวลาที่ใช้write()ไป ในเวลาเดียวกันฉันทำงานvmstat 5ในสถานีอื่นเพื่อดูระบบ "iowait"

  1. ฉันคาดหวังว่าฉันจะเห็น CPU ทั้งหมดอย่างน้อยหนึ่งตัวเป็น "ไม่ได้ใช้งาน" นั่นคือ 100% ของเวลาที่กำลังทำงานหรือหยุดทำงาน แต่รอสถานะ IO ("iowait") มันไม่ใช่
  2. (นอกจากนี้ฉันคาดหวังว่าจะเห็นเวลา "iowait" ตรงกับเวลาที่ใช้ในการเขียน () แต่ดูเหมือนจะไม่ทำเช่นนั้น)

ผลลัพธ์โดยละเอียดและสภาพแวดล้อมการทดสอบแสดงไว้ด้านล่าง ก็แสดงให้เห็นว่าเป็นการทดสอบทางเลือกที่ฉันถือสมมติฐาน หมายเหตุ: จำเป็นต้องเรียกใช้perf statภายในperf traceไม่ใช่วิธีอื่น นี่คือรายละเอียดที่นี่: "perf stat" (และ "time"!) แสดงผลลัพธ์ที่ไม่ถูกต้องเมื่อเรียกใช้ "perf trace-s" หรือไม่

ข้อมูลความเป็นมาของ "iowait"

ต่อไปนี้เป็นคำจำกัดความที่นำมาจากsarmanpage:

% iowait:

เปอร์เซ็นต์เวลาที่ CPU หรือ CPU ไม่ได้ทำงานในระหว่างที่ระบบมีดิสก์ I / O ที่ค้างอยู่

ดังนั้น% iowait จึงหมายความว่าจากมุมมองของ CPU ไม่มีภารกิจใดถูกรันได้ แต่อย่างน้อยหนึ่ง I / O กำลังดำเนินการอยู่ iowait เป็นเพียงรูปแบบของเวลาว่างเมื่อไม่มีอะไรสามารถกำหนด ค่าอาจหรือไม่อาจมีประโยชน์ในการระบุปัญหาประสิทธิภาพ แต่มันบอกผู้ใช้ว่าระบบไม่ได้ใช้งานและอาจมีการทำงานมากขึ้น

https://support.hpe.com/hpsc/doc/public/display?docId=c02783994

นอกจากนี้ยังมีบทความอีกต่อไป: การทำความเข้าใจของ I / O รอ (หรือทำไม 0% ไม่ได้ใช้งานสามารถ OK) สิ่งนี้อธิบายวิธีที่คุณสามารถดูคำจำกัดความที่ชัดเจนจากโค้ดเคอร์เนล รหัสมีการเปลี่ยนแปลงบ้าง แต่แนวคิดยังคงชัดเจน:

/*
 * Account for idle time.
 * @cputime: the CPU time spent in idle wait
 */
void account_idle_time(u64 cputime)
{
    u64 *cpustat = kcpustat_this_cpu->cpustat;
    struct rq *rq = this_rq();

    if (atomic_read(&rq->nr_iowait) > 0)
        cpustat[CPUTIME_IOWAIT] += cputime;
    else
        cpustat[CPUTIME_IDLE] += cputime;
}

บทความนี้ยังแสดงจำนวนของการทดลองที่เกี่ยวข้องในระบบ CPU เดียว การทดลองบางอย่างใช้ddกับif=/dev/urandom ! dd if=/dev/urandom of=test.out อย่างไรก็ตามการทดลองไม่รวมถึงการทดสอบของฉัน dd if=/dev/urandom of=/dev/null มันใช้เพียง

"รอ IO" เป็นเรื่องยากมากที่จะคิดในขณะนี้เพราะเราใช้ระบบหลาย CPU แต่ฉันคิดว่าฉันยังคงเข้าใจมันตามรหัสที่ยกมา

สิ่งแวดล้อม

ฉันมี CPU เชิงตรรกะสี่ตัว

ฉันใช้ LVM และระบบไฟล์ ext4 ฉันไม่ได้ใช้การเข้ารหัสบนดิสก์หรือระบบไฟล์ของฉัน ฉันไม่มีระบบไฟล์เครือข่ายใด ๆ เลยฉันเลยไม่อ่านหรือเขียนระบบไฟล์เครือข่าย

ผลลัพธ์ด้านล่างมาจากเคอร์เนล4.20.15-200.fc29.x86_64โดยใช้ตัวnoopจัดกำหนดการ IO เครื่องมือcfqจัดกำหนดการ IO ยังให้ผลลัพธ์ที่คล้ายกัน

(ฉันได้เห็นผลลัพธ์ที่คล้ายกันในการสร้างเคอร์เนลซึ่งเป็นไปตามการกำหนดค่าที่คล้ายกัน แต่ใกล้เคียงกับเคอร์เนลเวอร์ชัน 5.1 และการใช้mq-deadlineดังนั้นจึงใช้blk-mqรหัสใหม่)

การทดสอบและผลลัพธ์

$ sudo perf trace -s \
       perf stat \
       dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000

3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB, 2.9 GiB) copied, 31.397 s, 100 MB/s

 Performance counter stats for 'dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000':

         18,014.26 msec task-clock                #    0.574 CPUs utilized          
             3,199      context-switches          #    0.178 K/sec                  
                 4      cpu-migrations            #    0.000 K/sec                  
               328      page-faults               #    0.018 K/sec                  
    45,232,163,658      cycles                    #    2.511 GHz                    
    74,538,278,379      instructions              #    1.65  insn per cycle         
     4,372,725,344      branches                  #  242.737 M/sec                  
         4,650,429      branch-misses             #    0.11% of all branches        

      31.398466725 seconds time elapsed

       0.006966000 seconds user
      17.910332000 seconds sys

 Summary of events:
...
 dd (4620), 12156 events, 12.0%

   syscall            calls    total       min       avg       max      stddev
                               (msec)    (msec)    (msec)    (msec)        (%)
   --------------- -------- --------- --------- --------- ---------     ------
   read                3007 17624.985     0.002     5.861    12.345      0.21%
   write               3003 13722.837     0.004     4.570   179.928      2.63%
   openat                12     0.371     0.002     0.031     0.267     70.36%
...

ผมอ่านiowaitตัวเลขจากคอลัมน์wa vmstatคุณสามารถบอกได้ว่าเมื่อใดที่การทดสอบกำลังทำงานโดยดูที่ioคอลัมน์ ( bo= 1K บล็อกเอาต์พุต)

$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 5126892 176512 1486060   0   0  1788  4072  321  414  4  4 83  9  0
 1  0      0 5126632 176520 1485988   0   0     0     7  212  405  0  1 99  0  0
 0  0      0 5126884 176520 1485988   0   0     0     0  130  283  0  0 99  0  0
 0  0      0 5126948 176520 1485908   0   0     0     1  157  325  0  0 99  0  0
 0  0      0 5126412 176520 1486412   0   0   115     0  141  284  0  0 99  0  0
 0  2      0 5115724 176548 1487056   0   0     0  6019 18737 10733  3  6 89  2  0
 1  0      0 5115708 176580 1487104   0   0     3 91840 1276  990  0 13 77  9  0
 1  0      0 5115204 176600 1487128   0   0     2 91382 1382 1014  0 14 81  4  0
 1  0      0 5115268 176636 1487084   0   0     4 88281 1257  901  0 14 83  3  0
 0  1      0 5113504 177028 1487764   0   0    77 92596 1374 1111  0 15 83  2  0
 1  0      0 5114008 177036 1487768   0   0     0 113282 1460 1060  0 16 81  2  0
 1  0      0 5113472 177044 1487792   0   0     0 110821 1489 1118  0 16 74 10  0
 0  0      0 5123852 177068 1487896   0   0     0 20537  631  714  1  3 94  2  0
 0  0      0 5123852 177076 1487856   0   0     0    10  324  529  2  1 98  0  0
 2  0      0 5123852 177084 1487872   0   0     0    70  150  299  0  0 99  0  0

ผลการทดสอบที่จะเก็บไว้ (ภายใน VM)

ฉันลองทดสอบเดียวกันภายใน VM ด้วย 1 CPU ซึ่งใช้เคอร์เนล5.0.9-301.fc30.x86_64และใช้งานmq-deadline(และด้วยเหตุนี้ blk-mq) ในการทดสอบนี้ใช้งานได้ตามที่คาดหวัง

$ sudo perf trace -s \
       perf stat \
       dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000
[sudo] password for alan-sysop:
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB, 2.9 GiB) copied, 46.8071 s, 67.2 MB/s

 Performance counter stats for 'dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000':

         18,734.89 msec task-clock                #    0.400 CPUs utilized
            16,690      context-switches          #    0.891 K/sec
                 0      cpu-migrations            #    0.000 K/sec
               328      page-faults               #    0.018 K/sec
   <not supported>      cycles
   <not supported>      instructions
   <not supported>      branches
   <not supported>      branch-misses

      46.820355993 seconds time elapsed

       0.011840000 seconds user
      18.531449000 seconds sys


 Summary of events:
...
 dd (1492), 12156 events, 38.4%

   syscall            calls    total       min       avg       max      stddev
                               (msec)    (msec)    (msec)    (msec)        (%)
   --------------- -------- --------- --------- --------- ---------     ------
   write               3003 28269.070     0.019     9.414  5764.657     22.39%
   read                3007 18371.469     0.013     6.110    14.848      0.53%
   execve                 6    10.399     0.012     1.733    10.328     99.18%
...

ผลลัพธ์ของvmstat 5:

$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----                                                                     
 r  b  swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st                                                                     
 0  0     0 726176  52128 498508    0    0  2040   231  236  731  7  5 77 11  0                                                                     
 0  0     0 726176  52136 498508    0    0     0    10   25   46  0  0 99  1  0                                                                     
 0  0     0 726208  52136 498508    0    0     0     0   29   56  0  0 100  0  0                                                                    
 0  1     0 702280  55944 511780    0    0  2260 13109 4399 9049  3 17 55 25  0                                                                     
 0  1     0 701776  56040 511960    0    0    18 129582 1406 1458 0 73  0 27  0                                                                    
 0  2     0 701524  56156 512168    0    0    22 87060  960  991  0 50  0 50  0                                                                     
 3  1     0 701524  56228 512328    0    0    14 118170 1301 1322 0 68  0 32  0                                                                    
 1  1     0 701272  56260 512392    0    0     6 86426  994  982  0 53  0 46  0                                                                     
 0  2     0 701020  56292 512456    0    0     6 56115  683  660  0 37  0 63  0                                                                     
 3  2     0 700540  56316 512504    0    0     5 33450  446  457  0 26  0 74  0                                                                     
 0  2     0 700860  56332 512536    0    0     3 16998  311  240  0 19  0 81  0                                                                     
 1  2     0 700668  56368 512616    0    0     7 32563  443  428  0 24  0 76  0                                                                     
 1  0     0 700668  56392 512648    0    0     3 20338  245  272  0 12  0 88  0                                                                   
 0  1     0 707096  56408 512920    0    0    54 20913  312  530  0 12 79  8  0                                                                     
 0  0     0 707064  56432 512920    0    0     0    49   39   64  0  0 45 55  0                                                                     
 0  0     0 707064  56432 512920    0    0     0     0   24   46  0  0 100  0  0                                                                    
 0  0     0 707064  56432 512920    0    0     0    80   28   47  0  0 100  0  0

ฉันลองเพิ่ม CPU ไปยัง VM และทดสอบอีกครั้ง ผลลัพธ์เป็นตัวแปร: บางครั้งมันแสดงให้เห็นประมาณ 0% ในคอลัมน์ว่างและบางครั้งก็แสดงว่าไม่ได้ใช้งานประมาณ 50% (นั่นคือหนึ่งในสอง CPU) ในกรณีของ 0% "idle", "iowait" นั้นสูงมากนั่นคือมี CPU มากกว่าหนึ่งตัว นั่นคือจุดคาดหวังของฉัน 2 ไม่ถูกต้อง ฉันสามารถยอมรับข้อ จำกัดนี้อย่างชัดเจนของ "iowait" ในระบบมัลติซีพียู (แม้ว่าฉันจะไม่เข้าใจเลยทีเดียวถ้ามีคนต้องการอธิบายอย่างแน่นอน อย่างไรก็ตาม "ว่าง" ไม่สูงกว่า 50% ในทั้งสองกรณีดังนั้นการทดสอบเหล่านี้ยังคงสอดคล้องกับข้อสันนิษฐานแรกของฉันเกี่ยวกับ "iowait"

ฉันพยายามปิด VM ลงและเริ่มด้วย 4 CPU ในทำนองเดียวกันบ่อยครั้งที่ฉันมีการใช้งาน 75% อย่างแน่นอนและบางครั้งฉันมีการใช้งานที่ต่ำเป็น 50% แต่ฉันไม่ได้เห็นการใช้งานมากกว่า 75% (เช่นมากกว่าสามในสี่ CPU)

ในขณะที่ระบบฟิสิคัลที่มี CPU 4 ตัวฉันยังคงสามารถทำซ้ำผลลัพธ์ได้มากกว่า 80% ที่ไม่ได้ใช้งานตามที่แสดงไว้ด้านบน


คุณจะช่วยอธิบายความคาดหวังของคุณสองเล็กน้อยได้ไหม คุณสามารถเพิ่มได้ว่ามูลค่าที่แท้จริงนั้นมากหรือน้อยกว่าที่คุณคาดไว้หรือไม่ ฉันเข้าใจว่านี่เป็นข้อมูลดิบมันจะอ่านง่ายขึ้นอีกนิด ฉันไม่ค่อยชัดเจนว่าทำไมคุณถึงคาดหวัง 1 cpu (100%) ขึ้นอยู่กับหนึ่งในลิงก์ของคุณและรหัสเคอร์เนลที่คุณอ้างถึงการดำเนินการ IO เดียวจะเปลี่ยนเวลา IDLE ทั้งหมดเป็นเวลา IOWAIT (ทั้ง 4 คอร์ - 400%)
ฟิลิป Couling

@PhilipCouling "ฉันคาดว่าฉันจะเห็น CPU ทั้งหมดอย่างน้อยหนึ่งตัวเป็น" non-idle "... มันไม่ใช่" เวลาว่างสูงกว่าที่คาดไว้ซึ่งฉันโทษว่าเวลา iowait ต่ำกว่าที่คาดไว้ ในรหัสเคอร์เนลผมคิดว่าthis_rq()->nr_iowaitเป็นจำนวนของงานที่กำลังรอใช้io_schedule() บน CPU ปัจจุบันเท่านั้น ฉันผิดหรือเปล่า?
sourcejedi

1
ฉันไม่แน่ใจเลย แต่ฉันคิดว่ามันน่าแปลกใจถ้าเป็น ความประหลาดใจนี้ดูเหมือนจะตรงกับคำตอบของสตีเฟ่นกิตของที่เขากล่าวว่า" iowaitพยายามที่จะวัดเวลาที่ใช้ในการรอคอยสำหรับ I / O ในทั่วไป. ก็ไม่ได้ติดตามโดย CPU ที่เฉพาะเจาะจงและไม่สามารถ" ให้ฉันเครียดฉันไม่แน่ใจเรื่องนี้แค่แสดงความประหลาดใจ
Philip Couling

@PhilipCouling หากคุณเรียกใช้atopหรือatopsar -c 5คุณจะเห็นตัวเลขการใช้งานต่อซีพียู ซึ่งรวมถึง iowait และตัวเลข iowait ต่อซีพียูสามารถแสดงค่าที่แตกต่างและไม่เป็นศูนย์ :-) หรือถ้าคุณไม่ได้ใช้sar -P ALL 1 atopนี่เป็นวิธีที่iowaitรุ่นขยายสำหรับระบบมัลติซีพียู ... สิ่งที่ฉันไม่ชัดเจนคือรุ่นนี้ใช้งานได้จริงหรือไม่หรือนี่เป็นวิธีที่ทำให้รหัส iowait ทำงานต่อไปได้เมื่อมี CPU เพียงตัวเดียว ออนไลน์ แต่มันก็ไม่น่าไว้ใจอย่างอื่น
sourcejedi

คำตอบ:


7

ประกาศเกี่ยวกับเนื้อหา : โพสต์นี้มีลิงก์ไปยังการอภิปรายและโค้ดต่างๆของ Linux บางเนื้อหาที่เชื่อมโยงไม่ตรงกับปัจจุบันจรรยาบรรณของStackExchangeหรือลินุกซ์ ส่วนใหญ่พวกเขา "ดูถูกรหัส [แต่ไม่ใช่คน]" อย่างไรก็ตามมีการใช้ภาษาบางอย่างซึ่งไม่ควรทำซ้ำ ฉันขอให้คุณหลีกเลี่ยงการเลียนแบบการทำรังนกหรือโต้แย้งภาษาดังกล่าว


Re: บัญชี iowait vs idle คือ "ไม่สอดคล้องกัน" - iowait ต่ำเกินไป

ในวันที่ 05/07/2019 12:38, Peter Zijlstra เขียนว่า:

ในวันศุกร์ที่ 5 ก.ค. 2019 เวลา 12:25:46 น. +0100 อลันเจนกิ้นส์เขียนว่า:

เวลา cpu ของฉัน "iowait" ดูเหมือนว่าจะรายงานไม่ถูกต้อง คุณรู้ไหมว่าทำไมสิ่งนี้ถึงเกิดขึ้นได้?

เพราะ iowait เป็นตัวเลขสุ่มเวทย์มนตร์ที่ไม่มีความหมายใด ๆ โดยส่วนตัวแล้วฉันต้องการลบทั้งหมดยกเว้นABI : /

ดูความคิดเห็นที่อยู่ใกล้กับnr_iowait ()

ขอบคุณ ฉันใช้ [ปัญหาที่กล่าวถึงในเอกสารปัจจุบัน] ว่าเป็นปัญหาที่แตกต่างกัน แต่คุณหมายถึงว่ามีความต้องการ (หรือจุด) ไม่มากในการ "แก้ไข" ปัญหาของฉัน

ฉันพบปัญหาของฉัน มันสังเกตเห็นแล้วเมื่อห้าปีที่แล้วและมันจะไม่แก้ไขปัญหาเล็กน้อย

ฟังก์ชั่น "iowait" เวลามีการปรับปรุงโดยaccount_idle_time():

/*
 * Account for idle time.
 * @cputime: the CPU time spent in idle wait
 */
void account_idle_time(u64 cputime)
{
    u64 *cpustat = kcpustat_this_cpu->cpustat;
    struct rq *rq = this_rq();

    if (atomic_read(&rq->nr_iowait) > 0)
        cpustat[CPUTIME_IOWAIT] += cputime;
    else
        cpustat[CPUTIME_IDLE] += cputime;
}

สิ่งนี้ทำงานได้ตามที่คาดไว้หากคุณประมาณเวลาของซีพียูด้วย "การสุ่มตัวอย่าง" ด้วยตัวจับเวลาแบบดั้งเดิม ("ติ๊ก") แต่มันอาจจะไม่ทำงานถ้าติ๊กถูกปิดในช่วงเวลาที่ไม่ได้ใช้งานเพื่อประหยัดพลังงาน NO_HZ_IDLE- นอกจากนี้ยังอาจล้มเหลวหากคุณอนุญาตให้ติ๊กถูกปิดเพื่อเหตุผลด้านประสิทธิภาพ - NO_HZ_FULL- VIRT_CPU_ACCOUNTINGเพราะที่ต้องเริ่มต้น เมล็ด Linux ส่วนใหญ่ใช้คุณสมบัติการประหยัดพลังงาน ระบบฝังตัวบางตัวไม่ใช้คุณสมบัติใดคุณสมบัติหนึ่ง นี่คือคำอธิบายของฉัน:

เมื่อ IO เสร็จสมบูรณ์อุปกรณ์ส่งสัญญาณขัดจังหวะ try_to_wake_up()ตัวจัดการเคอร์เนลขัดจังหวะตื่นขั้นตอนโดยใช้ มันลบหนึ่งจากnr_iowaitเคาน์เตอร์:

if (p->in_iowait) {
    delayacct_blkio_end(p);
    atomic_dec(&task_rq(p)->nr_iowait);
}

หากกระบวนการดังกล่าวถูกปลุกบน CPU ที่ไม่มีการใช้งาน CPU นั้นจะเรียกaccount_idle_time()ใช้ ทั้งนี้ขึ้นอยู่กับการตั้งค่าใช้นี้เรียกว่าทั้งจากtick_nohz_account_idle_ticks()จาก__tick_nohz_idle_restart_tick()หรือจากจากvtime_task_switch()finish_task_switch()

มาถึงตอนนี้->nr_iowaitได้ลดลงแล้ว ถ้ามันลดลงเหลือศูนย์จะไม่มีการบันทึกเวลาของ iowait

เอฟเฟกต์นี้อาจแตกต่างกันไป: ขึ้นอยู่กับ CPU ที่กระบวนการตื่นขึ้นมา หากกระบวนการดังกล่าวถูกปลุกบน CPU เดียวกันกับที่ได้รับการขัดจังหวะการทำ IO จนเสร็จสิ้นเวลาว่างอาจถูกคิดก่อนหน้านี้ก่อนที่->nr_iowaitจะลดลง ในกรณีของฉันฉันพบ CPU 0 จับAHCIwatch cat /proc/interruptsขัดจังหวะโดยดูที่

ฉันทดสอบสิ่งนี้ด้วยการอ่านตามลำดับอย่างง่าย:

dd if=largefile iflag=direct bs=1M of=/dev/null

ถ้าฉันปักคำสั่งไปที่ CPU 0 โดยใช้taskset -c 0 ...ฉันเห็นค่า "ถูกต้อง" สำหรับ iowait ถ้าฉันตรึงมันไว้กับ CPU ตัวอื่นฉันเห็นค่าที่ต่ำกว่ามาก ถ้าฉันรันคำสั่งตามปกติมันจะแตกต่างกันไปขึ้นอยู่กับพฤติกรรมของตัวกำหนดตารางเวลาซึ่งมีการเปลี่ยนแปลงระหว่างเวอร์ชันเคอร์เนล ในเคอร์เนลล่าสุด (4.17, 5.1, 5.2-rc5-ish) คำสั่งดูเหมือนว่าจะใช้เวลาประมาณ 1/4 ของเวลาใน CPU 0 เนื่องจากเวลา "iowait" ลดลงเหลือเพียงเศษส่วนนั้น

(ไม่ได้อธิบาย: เหตุใดการเรียกใช้การทดสอบนี้บนเครื่องเสมือนของฉันจึงดูเหมือนจะทำซ้ำ iowait "ถูกต้อง" สำหรับแต่ละซีพียู (หรือใด ๆ ) ฉันสงสัยว่านี่อาจเกี่ยวข้องกับIRQ_TIME_ACCOUNTINGแม้ว่าคุณสมบัตินี้จะถูกใช้ในการทดสอบของฉันนอก VM

ฉันยังไม่ได้รับการยืนยันอย่างแน่ชัดว่าเหตุใดการระงับจึงNO_HZ_IDLEให้ iowait "ถูกต้อง" สำหรับแต่ละ CPU ใน 4.17+ แต่ไม่ใช่ใน 4.16 หรือ 4.15

การรันการทดสอบนี้บนเครื่องเสมือนของฉันดูเหมือนจะทำซ้ำ iowait "ถูกต้อง" สำหรับซีพียู (หรือใด ๆ ) แต่ละตัว IRQ_TIME_ACCOUNTINGนี่คือสาเหตุที่ นอกจากนี้ยังใช้ในการทดสอบนอก VM แต่ฉันได้รับการขัดจังหวะมากขึ้นเมื่อทดสอบภายใน VM โดยเฉพาะอย่างยิ่งมีมากกว่า 1,000 "การขัดจังหวะการเรียกใช้ฟังก์ชัน" ต่อวินาทีบน CPU เสมือนที่ "dd" ทำงาน

ดังนั้นคุณไม่ควรพึ่งพารายละเอียดของคำอธิบายของฉันมากเกินไป :-)

มีพื้นหลังเกี่ยวกับ "iowait" อยู่ที่นี่: CPU รู้ได้อย่างไรว่ามี IO ค้างอยู่ คำตอบที่นี่เป็นการเสนอราคาแนวคิดแบบตอบโต้ง่าย ๆ ว่าไอโออิทแบบสะสม "อาจลดลงในเงื่อนไขบางประการ" ฉันสงสัยว่าการทดสอบอย่างง่ายของฉันสามารถเปิดใช้งานเงื่อนไขที่ไม่มีเอกสารหรือไม่?

ใช่.

เมื่อฉันดูครั้งแรกฉันพบการพูดของ "hiccups" นอกจากนี้ปัญหาก็แสดงให้เห็นโดยการแสดงเวลา "iowait" สะสมนั้นไม่ใช่แบบโมโนโทนิก นั่นคือบางครั้งมันก็กระโดดไปข้างหลัง (ลดลง) มันไม่ได้ตรงไปตรงมาเหมือนการทดสอบข้างต้น

อย่างไรก็ตามเมื่อพวกเขาตรวจสอบพวกเขาพบปัญหาพื้นฐานเดียวกัน โซลูชันได้ถูกเสนอและสร้างต้นแบบโดย Peter Zijlstra และ Hidetoshi Seto ตามลำดับ ปัญหาอธิบายไว้ในข้อความหน้าปก:

[RFC PATCH 0/8] rework iowait การบัญชี (2014-07-07)

ฉันไม่พบหลักฐานของความคืบหน้านอกเหนือจากนี้ มีคำถามเปิดในรายละเอียดอย่างใดอย่างหนึ่ง นอกจากนี้ชุดเต็มรูปแบบได้สัมผัสรหัสเฉพาะสำหรับสถาปัตยกรรมซีพียู PowerPC, S390 และ IA64 ดังนั้นฉันพูดแบบนี้ไม่น่าจะแก้ไขได้


2
คุณสามารถยืนยันหรือปฏิเสธ (โดยใช้ vmstat): เคอร์เนล 4.15 ทำในสิ่งที่คุณคาดหวังโดยไม่คำนึงถึงสถานะ idles ที่เปิดใช้งานหรือปิดใช้งาน เคอร์เนล 4.16 ไม่ได้ทำตามที่คุณคาดหวัง ดูเหมือนว่า vmstat จะใช้/proc/statแต่ฉันใช้/sys/devices/system/cpu/cpu*/cpuidle/state*/usageและความรู้ที่ดีที่สุดของฉันนั้นแม่นยำเสมอ (+ - สองสาม%) ฉันไม่สามารถใช้เครื่องมือของฉันกับเมล็ดข้าวที่มีอายุมากกว่าได้เนื่องจากมีข้อมูลใหม่บางอย่างที่ไม่ได้อยู่ที่นั่น โปรดทราบว่าฉันคาดว่า test1 และ test3 จะให้ผลลัพธ์เดียวกันเนื่องจากเห็บไม่เคยหยุดนิ่งในสถานะ Idle 0
Doug Smythies

1
ฉันตั้งใจจะเขียน/sys/devices/system/cpu/cpu*/cpuidle/state*/timeข้างต้น ฉันสามารถคิดได้ว่าจะตัดเคอร์เนลเพียงครั้งเดียวระหว่างเคอร์เนล 4.15 และ 4.16 จากนั้นอีกครั้งระหว่าง 4.16 และ 4.17 การแบ่งครึ่งที่สองอาจเร็วขึ้นโดยความรู้ที่ได้รับจากครั้งแรก ฉันไม่ได้มีเวลาที่จะทำมันตอนนี้อาจจะในไม่กี่วัน
Doug Smythies

1
@DougSmythies ขอบคุณ! การทดสอบของคุณใช้ได้ผลเช่นเดียวกับแบบทดสอบดั้งเดิมของฉัน ผลลัพธ์ของฉันสำหรับ4.15.0-1.fc28และ4.16.0-300.fc28เห็นด้วยกับคุณ
sourcejedi

ตกลงฉันคิดว่าฉันพร้อมสำหรับการตอบกลับรายการ linux-pm หวังว่าบางคนจะมีความเข้าใจลึกซึ้งและเราสามารถหลีกเลี่ยงการแบ่งส่วนเคอร์เนล
Doug Smythies

1
@DougSmythies wtf แบ่งออกเป็นสองส่วนแรก (4.15-4.16) ให้github.com/torvalds/linux/commit/806486c377e3 "sched / fair: อย่าโอนย้ายหาก prev_cpu ไม่ได้ทำงาน" ดังนั้นฉันทดสอบกับtaskset -c 0v4.15 ... การรันddคำสั่งด้วยการtaskset -c 2ให้ iowait "ถูกต้อง" การปักหมุด CPU อื่น ๆ จะทำให้ iowait "ผิด" และ cpu2 เป็นที่ที่จะจบลงถ้าฉันไม่ได้ใช้dd taskset(ฉันเคยatopเห็นซีพียู iowait ต่อเวลา) ฉันกำลังดูที่การแบ่งครึ่งที่สองแม้ว่าเพื่ออธิบายพฤติกรรมปัจจุบัน ในโอกาสที่อาจมีความคิดเห็นเกี่ยวกับเรื่องนี้ในการเปลี่ยนแปลงครั้งที่สอง
sourcejedi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.