WPR/WPA ในทางปฏิบัติ — บทนำการสอบสวนประสิทธิภาพทั้งระบบเมื่อ "พีซีทั้งเครื่องช้า"
· Go Komura · Windows, ประสิทธิภาพ, WPR, WPA, ETW, การสอบสวนประสิทธิภาพ, การแก้ปัญหา, การพัฒนา Windows
“เขาบอกว่าพีซีทั้งเครื่องช้าหลังจากติดตั้งแอปใหม่ แต่พอดู Task Manager ทั้ง CPU และหน่วยความจำยังเหลือหัว” “มีพีซีเครื่องหนึ่งสตาร์ตใช้เวลา 3 นาที ไม่รู้ว่าอะไรผิด” — คำปรึกษาเรื่องประสิทธิภาพมาในรูปนี้จริง ๆ บ่อย สิ่งที่ร่วมกันคือ การมองโปรเซสเฉพาะไม่ให้คำตอบ
เครื่องมือระดับโปรเซสมีพร้อมแล้ว การเข้าถึงไฟล์และรีจิสทรีเห็นได้ด้วย Process Monitor และ CPU กับ GC ของแอป .NET ตามได้ด้วย PerfView แต่อาการอย่าง “พีซีทั้งเครื่องช้า” หรือ “CPU ว่างแล้วยังช้า” เริ่มจากยังไม่รู้ด้วยซ้ำว่าโปรเซสใดเป็นตัวการ แอป A อาจช้าเพราะสแกนแอนติไวรัส หรือเพราะบริการอื่นเขียนดิสก์หนัก หรือเพราะโซ่ล็อกที่ข้ามหลายโปรเซส สิ่งที่คุณต้องการคือ ข้อมูลที่บันทึกไม่ใช่ข้างในโปรเซส แต่ OS ทั้งก้อนบนไทม์ไลน์เดียว
เครื่องมือสำหรับจับและอ่านนั่นคือ Windows Performance Recorder (WPR) และ Windows Performance Analyzer (WPA) WPR บันทึกกิจกรรมทั้ง OS บนฐาน ETW (Event Tracing for Windows) และ WPA วิเคราะห์การบันทึกนั้นในกราฟและตาราง ใครใช้ CPU บนสแตกใด เธรดรอใคร โปรเซสใดออกดิสก์ I/O ไปยังไฟล์ใด — ข้อเท็จจริงที่ต่ำกว่า Task Manager หนึ่งหรือสองขั้นทั้งหมดยังอยู่ พร้อมตราประทับเวลา
มุ่งไปที่เจ้าหน้าที่ไอทีในธุรกิจขนาดกลางและขนาดย่อม และนักพัฒนาแอป Windows บทความนี้จัดระเบียบการปฏิบัติของการจับด้วย WPR และวิธีอ่าน WPA — โดยเฉพาะความต่างระหว่างการสอบสวน “เมื่อ CPU สูง” กับ “เมื่อ CPU ต่ำแล้วยังช้า” — ยึดแหล่งปฐมภูมิ ณ สิงหาคม 2026
1. สรุปก่อนเลย
- ตัวเลือกแรกสำหรับการสอบสวน “พีซีทั้งเครื่องช้า” คือ WPR/WPA ซึ่งจับและอ่าน ETW เทรซทั้ง OS ปัญหาที่เครื่องมือระดับโปรเซส (Task Manager, Procmon, PerfView) ตรึงไม่ได้ สามารถตามได้หากคุณมองทุกโปรเซสและเคอร์เนลบนไทม์ไลน์เดียว12
- เครื่องมือจับ wpr.exe มากับ Windows 8.1 เป็นต้นไป คุณใช้ได้โดยไม่ต้องติดตั้งเพิ่ม รุ่น GUI (WPRUI) และเครื่องมือวิเคราะห์ WPA รวมอยู่ใน Windows ADK12
- ขั้นตอนพื้นฐานมีสามบรรทัด ในฐานะผู้ดูแลระบบ
wpr -start GeneralProfile -filemode→ ทำซ้ำปัญหา →wpr -stop C:\temp\trace.etlจำแค่นั้นแล้วเริ่มจับได้3 - เส้นฐานในสนามคือการแยก “ในสภาพแวดล้อมลูกค้า จับด้วย wpr.exe เท่านั้น การอ่านคือ WPA บนเครื่องตัวเอง” คุณจับได้แม้บนเซิร์ฟเวอร์ที่ติดตั้งซอฟต์แวร์ไม่ได้ เป็นแนวคิดเดียวกับ packet capture ที่ “จับด้วยเครื่องมือมาตรฐาน อ่านใน Wireshark”1
- การอ่าน WPA เริ่มด้วยการจำแนก “CPU การรอ หรือ I/O” หาก CPU ไหม้ CPU Usage (Sampled) หาก CPU ว่างแล้วยังช้า วิเคราะห์การรอใน CPU Usage (Precise) หากสงสัยดิสก์ Disk Usage — เส้นทางแยกตั้งแต่ต้น45
- CPU Usage (Sampled) แสดง “ฟังก์ชันใดใช้ CPU” จากการสุ่มประมาณทุก 1 มิลลิวินาที คุณเดินรายละเอียดของ “50%” ใน Task Manager จากโปรเซส → เธรด → สแตก → ฟังก์ชัน6
- CPU Usage (Precise) คือระเบียนสมบูรณ์ของ context switch และบอกว่า “เธรดรอใคร” การเดิน Waits (เวลารอ) ReadyingProcess (ใครปลุกมัน) และ ReadyThreadStack (สแตกของผู้ปลุก) คือเทคนิคที่บทความนี้ต้องการสื่อมากที่สุด47
- การอ่านสแตกต้องการการตั้งค่าสัญลักษณ์ WPA อ้างเซิร์ฟเวอร์สัญลักษณ์สาธารณะของ Microsoft โดยค่าเริ่มต้น เพื่อเห็นชื่อฟังก์ชันในแอปของตัวเอง ให้เพิ่มเส้นทางไปยัง PDB ของตัวเอง8
- ไฟล์ ETL มีข้อมูลภายในระบบ เช่น ชื่อโปรเซสและเส้นทางไฟล์ เก็บการจับให้เหลือเท่าที่จำเป็น และตัดสินว่าจะจัดการอย่างไรหากออกจากบริษัท ก่อนจับ
2. เครื่องมืออยู่ตรงไหน — WPR จับ WPA อ่าน
Windows Performance Toolkit (WPT) คือชุดเครื่องมือสอบสวนประสิทธิภาพที่รวมใน Windows ADK (Windows Assessment and Deployment Kit) ศูนย์กลางคือคู่ของ WPR และ WPA2 บทบาทแยกชัด
- WPR (Windows Performance Recorder) = จับ มันมัดกลุ่มผู้ให้บริการ ETW เป็นหน่วยเรียก “โปรไฟล์” เริ่มและหยุดการบันทึก และผลิตไฟล์ ETL รุ่นบรรทัดคำสั่ง wpr.exe มากับ Windows 8.1 เป็นต้นไป โดยไม่ต้องติดตั้งเพิ่ม รุ่น GUI (WPRUI.exe) รวมอยู่ใน ADK1
- WPA (Windows Performance Analyzer) = วิเคราะห์ มันเปิดไฟล์ ETL และวิเคราะห์ในกราฟและตาราง ต้องติดตั้ง ADK2
กล่าวอีกอย่าง ไม่มีอะไรที่คุณต้องวางในสภาพแวดล้อมลูกค้า จับด้วย wpr.exe มาตรฐานของ OS นำไฟล์ ETL กลับบ้าน และอ่านใน WPA บนพีซีตัวเอง — การแยกเดียวกับ packet capture ที่ “จับด้วย pktmon อ่านใน Wireshark” ยังใช้ได้
flowchart TB
accTitle: การแยกจับด้วย WPR และอ่านด้วย WPA
accDescr: ในสภาพแวดล้อมลูกค้า บันทึกด้วย wpr.exe มาตรฐานของ OS และผลิตไฟล์ ETL นำกลับบ้านแล้ววิเคราะห์ใน WPA ที่ติดตั้งผ่าน ADK บนพีซีตัวเอง
subgraph customer["พีซีลูกค้า(ไม่ติดตั้งเพิ่ม)"]
wpr["wpr start → ทำซ้ำ → stop"] --> etl["ไฟล์ ETL"]
end
subgraph office["พีซีของคุณ(WPA ผ่าน ADK)"]
wpa["วิเคราะห์กราฟและตาราง"]
end
etl -->|"นำกลับบ้าน"| wpa
ภาพ 1: ในสภาพแวดล้อมลูกค้า บันทึกด้วย wpr.exe มาตรฐานของ OS และผลิตไฟล์ ETL นำกลับบ้านแล้ววิเคราะห์ใน WPA ที่ติดตั้งผ่าน ADK บนพีซีตัวเอง
ความต่างจากเครื่องมือคล้ายกันก็คุ้มที่จะจัดไว้ก่อน
| Process Monitor | PerfView | WPR + WPA | |
|---|---|---|---|
| คำถามที่มันตอบ | โปรเซสใดทำอะไรกับเส้นทางใด และเกิดอะไร | CPU, GC และการจัดสรรของแอป .NET เป็นอย่างไร | ข้ามทั้ง OS เวลาหายไปที่ไหน |
| ขอบเขต | ล็อกการทำงานของไฟล์ รีจิสทรี และการสตาร์ตโปรเซส | โค้ด managed เป็นหลัก | CPU การรอ ดิสก์ ไฟล์ I/O พลังงาน และอื่น ๆ ทั้งระบบ |
| อาการที่เหมาะ | การตั้งค่าไม่ถูกอ่าน ACCESS DENIED | ความช้าหรือหน่วยความจำของแอป .NET ของตัวเองเพียงอย่างเดียว | พีซีทั้งเครื่องช้า CPU ว่างแล้วยังช้า ไม่รู้โปรเซสตัวการ |
| บทความ | คู่มือปฏิบัติ Procmon | บทนำปฏิบัติ PerfView | บทความนี้ |
หาก Procmon คือล็อกการทำงานของ “มันทำอะไร” และ PerfView คือ “เกิดอะไรข้างใน .NET” WPA คือเครื่องมือที่ ตรวจ “เวลาหายไปที่ไหน” ข้ามทุกโปรเซส กลไกของ ETW เอง และวิธีใส่เครื่องมือแอปของตัวเองด้วย ETW อยู่ใน “บทนำ Windows Event Log และ ETW” หากแอปของตัวเองปล่อยอีเวนต์ ETW จุดตรวจของแอปถูกบันทึกในเทรซเดียวกัน และการเรียงกันง่ายขึ้นมาก อย่างไรก็ตาม WPR บันทึกเฉพาะอีเวนต์จากผู้ให้บริการที่โปรไฟล์การบันทึกที่คุณเลือกเปิดใช้ GeneralProfile ไม่รวมผู้ให้บริการของตัวเอง ดังนั้นหากต้องการผสม ให้เตรียมโปรไฟล์การบันทึกกำหนดเอง (.wprp) ที่เปิดผู้ให้บริการของคุณ และรวมเป็น wpr -start GeneralProfile -start MyApp.wprp!MyAppProfile โดยระบุชื่อโปรไฟล์ในไฟล์ .wprp ด้วย !3
3. จับในทางปฏิบัติ (WPR) — start ทำซ้ำ stop
ขั้นตอนพื้นฐานในเทอร์มินัลผู้ดูแลระบบ
:: List of built-in profiles you can use
wpr -profiles
:: 1. Start capture (general-purpose profile, file mode)
wpr -start GeneralProfile -filemode
:: 2. Reproduce the issue (check capture status with wpr -status)
:: 3. Stop and save (you can attach a description of the problem).
:: Create the destination folder in advance (without it, -stop fails to save)
mkdir C:\temp 2>nul
wpr -stop C:\temp\slow-pc.etl "Reproduced the issue where the whole PC becomes slow while starting App X"
:: To abandon without saving
wpr -cancel
สิ่งที่คุณส่งให้ -start คือ โปรไฟล์ มัดของผู้ให้บริการ ETW ที่การสอบสวนต้องการ3 จำเฉพาะที่ใชบ่อยก็พอ9
| โปรไฟล์ | สิ่งที่มันบันทึก | เมื่อใดควรใช้ |
|---|---|---|
GeneralProfile |
ชุดทั่วไปรวมตัวอย่าง CPU, context switch และดิสก์ I/O | เริ่มที่นี่ ก้าวแรกเมื่อไม่รู้ว่าอะไรผิด |
CPU |
การใช้ CPU ละเอียด | เมื่อรู้แล้วว่า CPU ไหม้ |
DiskIO |
กิจกรรมดิสก์ I/O | เมื่อสงสัยดิสก์ |
FileIO |
กิจกรรมไฟล์ I/O | เมื่อต้องการตามว่าไฟล์ใดถูกเข้าถึง |
คุณระบุหลายโปรไฟล์พร้อมกันได้ด้วยการเรียง -start (เช่น wpr -start GeneralProfile -start FileIO -filemode)3
flowchart TB
accTitle: ไหลการจับ WPR และวิธีเลือกโหมด
accDescr: ปัญหาที่ทำซ้ำได้ทันทีถูกจับสั้นและเชื่อถือได้ในโหมดไฟล์ ปัญหาที่จังหวะไม่รู้ถูกรอในบัฟเฟอร์วงโหมดหน่วยความจำค่าเริ่มต้น ปัญหาระหว่างบูตหรือล็อกออนใช้เทรซบูต ในทุกกรณีขั้นตอน start / ทำซ้ำ / stop เหมือนกัน
q{"เกิดเมื่อใด"}
q -->|"ทันที"| file["โหมดไฟล์: จับสั้น"]
q -->|"จังหวะไม่รู้"| mem["โหมดหน่วยความจำ: รอ(3.1)"]
q -->|"บูตหรือล็อกออน"| boot["เทรซบูต(บทที่ 8)"]
file --> s1["start → ทำซ้ำ → stop"]
mem --> s1
ภาพ 2: ปัญหาที่ทำซ้ำได้ทันทีถูกจับสั้นและเชื่อถือได้ในโหมดไฟล์ ปัญหาที่จังหวะไม่รู้ถูกรอในบัฟเฟอร์วงโหมดหน่วยความจำค่าเริ่มต้น ปัญหาระหว่างบูตหรือล็อกออนใช้เทรซบูต ในทุกกรณีขั้นตอน start / ทำซ้ำ / stop เหมือนกัน
3.1. โหมด Memory และโหมด File — ทำซ้ำได้ หรือคุณรอ
WPR มีสองโหมดปลายทางบันทึก ค่าเริ่มต้นคือ โหมด Memory (บัฟเฟอร์วงกลมในหน่วยความจำ) เป็นบัฟเฟอร์วงที่เขียนทับจากอีเวนต์เก่าสุด จึงเหมาะกับ ปล่อยการจับรันขณะรอปัญหาที่จังหวะไม่รู้ และหยุดเมื่อมันเกิด การเพิ่ม -filemode สลับเป็น โหมด File และทุกอย่างถูกบันทึกลงไฟล์ต่อเนื่อง อันนี้ไม่ถูกเขียนทับไป เพดานเดียวคือพื้นที่ดิสก์ว่าง และไฟล์โตไม่มีขอบ10
flowchart TB
accTitle: โหมด Memory และโหมด File บันทึกอย่างไร
accDescr: โหมด Memory บันทึกลงบัฟเฟอร์วงกลมในหน่วยความจำ อีเวนต์เก่าถูกเขียนทับและเหลือเฉพาะล่าสุด จึงเหมาะกับการรอ โหมด File เก็บทุกอย่างในไฟล์ แต่เพดานเดียวคือพื้นที่ดิสก์ว่าง จึงเหมาะกับการทำซ้ำสั้นที่เชื่อถือได้
ev["อีเวนต์ ETW"] --> ring["โหมด Memory: บัฟเฟอร์วง"]
ev --> filem["โหมด File: โตไฟล์"]
ring -.-> use1["รอจังหวะที่ไม่รู้"]
filem -.-> use2["ทำซ้ำสั้นที่เชื่อถือได้"]
ภาพ 3: โหมด Memory บันทึกลงบัฟเฟอร์วงกลมในหน่วยความจำ อีเวนต์เก่าถูกเขียนทับและเหลือเฉพาะล่าสุด จึงเหมาะกับการรอ โหมด File เก็บทุกอย่างในไฟล์ แต่เพดานเดียวคือพื้นที่ดิสก์ว่าง จึงเหมาะกับการทำซ้ำสั้นที่เชื่อถือได้
กฎง่าย ๆ สำหรับการเลือกมีดังนี้
- ทำซ้ำได้ทันที → โหมด File เริ่มก่อนทำซ้ำเล็กน้อย หยุดทันทีหลัง และ เก็บการจับในไม่กี่นาที
- จังหวะไม่รู้ → รอในโหมด Memory (ค่าเริ่มต้น) ทันทีที่เกิด
wpr -stop - แม้ GeneralProfile ไม่กี่นาทีก็ผลิต ETL ระดับหลายร้อย MB ถึง GB ไฟล์ที่ใหญ่เกินไปอาจวิเคราะห์ใน WPA ไม่ได้ ดังนั้น “จับนานยิ่งดี” จึงสวนทาง1011
เพื่อจับจาก GUI เริ่ม WPRUI เลือกโปรไฟล์และ Logging mode แล้ว Start/Save How-to ทางการสรุปขั้นตอน11 หากขอให้ผู้ติดต่อที่ไซต์ลูกค้าจับ สามคำสั่งข้างบนใส่ในขั้นตอนได้ตามที่เป็น
4. พื้นฐานการอ่าน WPA — กราฟ กฎทองของตาราง และการบีบเวลา
เมื่อคุณเปิด ETL ที่จับใน WPA Graph Explorer ด้านซ้ายแสดงภาพย่อกราฟเป็นหมวด เช่น System Activity, Computation, Storage และ Memory12 ลากกราฟที่ต้องการเห็นไปยังแท็บ Analysis ด้านขวา กราฟปรากฏด้านบนและตารางด้านล่าง สามสิ่งแรกที่ต้องรับไว้คือเหล่านี้
- กฎทองของตาราง — ลำดับคอลัมน์ตัดสินการจัดกลุ่ม ตาราง WPA มีแถบแนวตั้งสองอัน ทองและน้ำเงิน และ คอลัมน์ทางซ้ายของแถบทองจัดลำดับชั้น (จัดกลุ่ม) ข้อมูลตามลำดับนั้น และคอลัมน์ทางขวาของแถบน้ำเงินคือผลรวม13 จัดเป็น Process → Stack คุณได้การรวมสแตกต่อโปรเซส Stack → Process คุณได้การรวมของทุกโปรเซสที่ใช้สแตกเดียวกัน — การลากคอลัมน์เพื่อเรียงใหม่เองคือการดำเนินการวิเคราะห์ เข้าใจจุดเดียวนี้แล้วทุกตาราง WPA อ่านแบบเดียวกัน
flowchart TB
accTitle: กฎทองของตาราง — สองแถบและบทบาทของคอลัมน์
accDescr: คอลัมน์ทางซ้ายของแถบทองจัดลำดับชั้นข้อมูลตามลำดับนั้น คอลัมน์ระหว่างแถบทองและน้ำเงินคือคอลัมน์แสดง คอลัมน์ทางขวาของแถบน้ำเงินคือผลรวม การลากคอลัมน์เพื่อเรียงใหม่เองคือการดำเนินการวิเคราะห์
left["ซ้ายของทอง: การจัดกลุ่ม"] --> gold["แถบทอง"]
gold --> mid["ระหว่างแถบ: แสดง"]
mid --> blue["แถบน้ำเงิน"]
blue --> right["ขวาของน้ำเงิน: ผลรวม"]
left -.-> op["ลากคอลัมน์เพื่อวิเคราะห์"]
ภาพ 4: คอลัมน์ทางซ้ายของแถบทองจัดลำดับชั้นข้อมูลตามลำดับนั้น คอลัมน์ระหว่างแถบทองและน้ำเงินคือคอลัมน์แสดง คอลัมน์ทางขวาของแถบน้ำเงินคือผลรวม การลากคอลัมน์เพื่อเรียงใหม่เองคือการดำเนินการวิเคราะห์
- บีบช่วงเวลา ลากบนกราฟเพื่อเลือกช่วง แล้วคลิกขวาและ “Zoom” การรวมสลับเป็นช่วงนั้นเท่านั้น การสอบสวนประสิทธิภาพโดยหลักแล้วมองเฉพาะ “ช่วงที่ปัญหากำลังเกิด” (บทที่ 9)
- ตั้งค่าสัญลักษณ์ เพื่ออ่านสแตกตามชื่อฟังก์ชัน รัน Trace > Load Symbols จากเมนู14 โดยค่าเริ่มต้นมันอ้างเซิร์ฟเวอร์สัญลักษณ์สาธารณะของ Microsoft (msdl.microsoft.com) ดังนั้นสแตกของ Windows เองแก้ได้หากมีอินเทอร์เน็ต เพื่อเห็นชื่อฟังก์ชันในแอปของตัวเอง เพิ่มโฟลเดอร์ PDB ของแอปใน Trace > Configure Symbol Paths8 PDB คืออะไร และทำไมควรรักษาไว้เสมอแม้สำหรับบิลด์ Release สรุปใน “PDB (Program Database) คืออะไร” สำหรับอิมเมจเนทีฟ NGen ของ .NET Framework WPR สร้าง NGen PDB (.ngenpdb) ตอนจับและวางในโฟลเดอร์ข้างเทรซ และ WPA อ้างอัตโนมัติ8 นี่เป็นกลไกสำหรับอิมเมจ NGen เท่านั้น และ โค้ด JIT .NET ธรรมดาของตัวเองอยู่นอกขอบเขต การแมปจากที่อยู่โค้ด JIT ไปยังชื่อฟังก์ชันแก้จากอีเวนต์ JIT ที่ CLR ปล่อย ดังนั้นเมื่อสอบสวนแอป .NET ให้เตรียมโปรไฟล์การบันทึก (.wprp) ที่เปิดผู้ให้บริการ CLR (Microsoft-Windows-DotNETRuntime และ Rundown ที่คู่กัน) และรวมแบบเดียวกับผู้ให้บริการของตัวเองในบทที่ 3
wpr -start GeneralProfile -start MyDotNet.wprp!profile-nameเพื่อให้อีเวนต์ CLR รวมในเทรซ (ตรวจว่าโปรไฟล์ในตัวที่ WPR ท้องถิ่นเสนอด้วยwpr -profiles) นอกจากนั้น เก็บ PDB ที่บิลด์สร้างสำหรับการแมปไปยังบรรทัดซอร์ส และเพิ่มในเส้นทางสัญลักษณ์ข้างบน
flowchart TB
accTitle: การแก้สัญลักษณ์เพื่ออ่านสแตกตามชื่อฟังก์ชัน
accDescr: การรัน Trace Load Symbols แก้ Windows เองจากเซิร์ฟเวอร์สัญลักษณ์สาธารณะของ Microsoft และแอปของตัวเองจาก PDB บิลด์ที่เพิ่มในเส้นทางสัญลักษณ์ อิมเมจ NGen ใช้ NGen PDB ที่ WPR สร้าง โค้ด JIT .NET แก้จากอีเวนต์ CLR JIT ในเทรซบวก PDB บิลด์
load["Trace > Load Symbols"] --> ms["Windows: สัญลักษณ์สาธารณะ"]
load --> own["แอปของตัวเอง: PDB บิลด์"]
ms -.-> ngen["NGen: WPR .ngenpdb"]
own -.-> jit["JIT: อีเวนต์ CLR + PDB"]
ภาพ 5: การรัน Trace Load Symbols แก้ Windows เองจากเซิร์ฟเวอร์สัญลักษณ์สาธารณะของ Microsoft และแอปของตัวเองจาก PDB บิลด์ที่เพิ่มในเส้นทางสัญลักษณ์ อิมเมจ NGen ใช้ NGen PDB ที่ WPR สร้าง โค้ด JIT .NET แก้จากอีเวนต์ CLR JIT ในเทรซบวก PDB บิลด์
เมื่อเตรียมพร้อมแล้ว คุณเข้าจากสาขาถัดไป ในช่วงนั้น CPU สูงหรือต่ำ หากสูง บทที่ 5 (Sampled) หากต่ำแล้วยังช้า บทที่ 6 (Precise)
flowchart TB
accTitle: สาขาสำหรับเลือกกราฟ WPA จากอาการ
accDescr: ซูมไปช่วงปัญหา หาก CPU สูงไป CPU Usage Sampled หากต่ำแล้วยังช้า ตรวจการตรึงคอร์เดียว / เธรดเดียว แล้ววิเคราะห์การรอใน CPU Usage Precise หากสงสัยดิสก์ Disk Usage และ File IO
zoom["ซูมไปช่วงปัญหา"] --> cpu{"CPU ในช่วงนั้น"}
cpu -->|"สูง"| sampled["บทที่ 5: Sampled"]
cpu -->|"ต่ำ ยังช้า"| core{"ตรึง 1 คอร์ / 1 เธรด"}
core -->|"ใช่"| sampled
core -->|"ไม่"| precise["บทที่ 6: Precise"]
cpu -->|"สงสัยดิสก์"| disk["บทที่ 7: ดิสก์ / ไฟล์ I/O"]
ภาพ 6: ซูมไปช่วงปัญหา หาก CPU สูงไป CPU Usage Sampled หากต่ำแล้วยังช้า ตรวจการตรึงคอร์เดียว / เธรดเดียว แล้ววิเคราะห์การรอใน CPU Usage Precise หากสงสัยดิสก์ Disk Usage และ File IO
5. เมื่อ CPU สูง — “ใครไหม้ฟังก์ชันใด” ด้วย CPU Usage (Sampled)
หาก CPU ถูกตรึง สิ่งที่คุณมองคือ CPU Usage (Sampled) นี่คือข้อมูลสุ่มที่บันทึก ประมาณทุก 1 มิลลิวินาทีบนทุก CPU ว่า “สแตกใดของโปรเซสใดกำลังรันตอนนี้” และอัตราส่วนของจำนวนตัวอย่างคือรายละเอียดของเวลา CPU ตามที่เป็น6
flowchart TB
accTitle: CPU Usage Sampled ทำงานอย่างไร
accDescr: ประมาณทุก 1 มิลลิวินาที สแตกที่รันบนทุก CPU ถูกบันทึก และอัตราส่วนตัวอย่างที่รวมคือรายละเอียดของเวลา CPU อ่านจากโปรเซสไปเธรด สแตก และฟังก์ชัน กิจกรรมสั้นที่จบระหว่างตัวอย่างไม่ปรากฏ
tick["ขัดจังหวะประมาณทุก 1 มิลลิวินาที"] --> snap["บันทึกสแตกที่รัน"]
snap --> agg["อัตราส่วนตัวอย่าง = รายละเอียด CPU"]
agg --> drill["โปรเซส → เธรด → สแตก"]
snap -.-> miss["กิจกรรมระหว่างตัวอย่างพลาด"]
ภาพ 7: ประมาณทุก 1 มิลลิวินาที สแตกที่รันบนทุก CPU ถูกบันทึก และอัตราส่วนตัวอย่างที่รวมคือรายละเอียดของเวลา CPU อ่านจากโปรเซสไปเธรด สแตก และฟังก์ชัน กิจกรรมสั้นที่จบระหว่างตัวอย่างไม่ปรากฏ
- จาก Computation ของ Graph Explorer วาง CPU Usage (Sampled) บนแท็บ Analysis และเลือกพรีเซ็ต Utilization by Process, Stack5
- มองโปรเซสเรียงจาก Weight (หรือ Count) มากไปน้อย ตัวตนของสิ่งที่เคยเป็น “50%” ใน Task Manager ชัดขึ้นก่อนที่ระดับโปรเซส
- ขยายคอลัมน์ Stack ของโปรเซสตัวการ สแตกถูกรวมเป็นต้นไม้ และ การเดินเส้นทางที่ตัวเลขไม่ตกมากที่กิ่ง พาคุณลงที่ฟังก์ชันที่ไหม้ CPU หากสัญลักษณ์ถูกแก้แล้ว เป็นเส้นตรงไปยังฟังก์ชันใดในโค้ดของตัวเอง
- หากการขยายต้นไม้ยุ่งยาก สลับการแสดงกราฟเป็น Flame มันถูกวาดด้วยความกว้าง = ส่วนแบ่งเวลา CPU ดังนั้นเส้นทางเรียกใดครอบงำชัดในพริบตา CPU Usage (Sampled) ยังมีพรีเซ็ต Flame by Process, Stack13
มีข้อควรระวังหนึ่ง เพราะเป็นการสุ่ม กิจกรรมสั้นที่จบระหว่างตัวอย่างไม่ปรากฏ6 จำไว้ว่าเป็นเครื่องมือสำหรับเห็น “CPU ถูกใช้ที่ไหนโดยรวม” ไม่ใช่เครื่องมือวัดระยะต่อครั้งเรียกที่แม่นยำ
6. เมื่อ CPU ต่ำแล้วยังช้า — CPU Usage (Precise) และการวิเคราะห์การรอ
นี่คือแกนของบทความ ก่อนไปวิเคราะห์การรอ มีสิ่งหนึ่งต้องยืนยัน “การใช้ CPU โดยรวมต่ำ” ไม่ได้หมายความว่า “CPU ไม่ใช่คอขวด” บนพีซี 16 คอร์ งานต่อเนื่องที่ตรึงคอร์เดียว (เธรด UI เดียวที่รันเต็มที่) ดูเหมือนแค่ประมาณ 6% โดยรวม ตรวจก่อนใน Sampled ของบทที่ 5 (หรือ Utilization by CPU ของ CPU Usage (Precise)) ว่าไม่มีการตรึงบนคอร์หรือเธรดเฉพาะ และหากไม่มี มาที่บทนี้ — งานไม่ได้ รันไม่ได้ มันกำลัง รอ สิ่งที่บอกว่ามันรออะไรคือ CPU Usage (Precise)
ที่ Sampled คือการสุ่ม Precise คือ ระเบียนสมบูรณ์ของ context switch (การสลับเธรด) เธรดเข้าสู่การรอ ถูกใครสักคนปลุก (Ready) และลงบน CPU — รอบนั้นยังอยู่ทีละแถว และคุณอ่านคอลัมน์ต่อไปนี้ได้74
| คอลัมน์ | ความหมาย |
|---|---|
| NewThreadStack | บนสแตกใดที่เธรดนั้นเข้าสู่การรอ (= มันกำลังทำอะไรเมื่อหยุด) |
| Waits (us) | มันรอนานเท่าใด |
| Ready (us) | มันถูกรอนานเท่าใดตั้งแต่ถูกปลุกจนลงบน CPU (การแย่ง CPU) |
| ReadyingProcess / ReadyingThreadId | โปรเซสและเธรดที่ ปลุกเธรดนั้น (ปล่อยการรอ) |
| ReadyThreadStack | บนสแตกใดที่ผู้ปลุกปลุกมัน |
flowchart TB
accTitle: รอบการรอหนึ่งรอบและการสอดคล้องของคอลัมน์
accDescr: เธรดเข้าสู่การรอบนสแตกที่ยังอยู่ใน NewThreadStack และรอเวลา Waits เมื่อใครสักคนปลุกมัน ฝ่ายนั้นยังอยู่ใน ReadyingProcess และ ReadyThreadStack มันรอเวลา Ready สำหรับการแย่ง CPU แล้วรันอีก
run1["กำลังรัน"] -->|"เข้าสู่การรอ"| waitst["รอ(Waits us)"]
waitst -->|"ใครสักคนปลุก"| ready["Ready(การแย่ง CPU)"]
ready -->|"ลงบน CPU"| run2["รันอีก"]
waitst -.-> col["NewThreadStack / ReadyingProcess"]
ภาพ 8: เธรดเข้าสู่การรอบนสแตกที่ยังอยู่ใน NewThreadStack และรอเวลา Waits เมื่อใครสักคนปลุกมัน ฝ่ายนั้นยังอยู่ใน ReadyingProcess และ ReadyThreadStack มันรอเวลา Ready สำหรับการแย่ง CPU แล้วรันอีก
รูปแบบการอ่านมีดังนี้4
- ใช้พรีเซ็ต Utilization by Process, Thread และเพิ่ม NewThreadStack และ ReadyThreadStack ในคอลัมน์
- ระบุก่อน เธรดที่กำลังดำเนินการปฏิบัติการที่ล่าช้า (เธรด UI เธรดที่จัดการคำขอที่เป็นปัญหา) การมองเฉพาะเรียงจาก Waits รวมมากไปน้อยทำให้สับสน เพราะเธรดที่ “ตั้งใจรอตลอดเวลา” เช่น message pump หรือตัวตั้งเวลา ครองอันดับบน เมื่อหาเธรดเป้าหมายได้แล้ว หาก CPU Usage (ms) ของมันใหญ่ เป็นปัญหา CPU บทที่ 5 หาก Waits ครอบงำ เป็นปัญหาการรอ
- ขยาย NewThreadStack และดู มันกำลังทำอะไรเมื่อหยุด
WaitForSingleObjectหรือEnterCriticalSectionคือการรอล็อก ข้างใน I/O ซิงโครนัส เช่นReadFileคือการรอ I/O ข้างในรับซ็อกเก็ตคือการรอคู่สนทนาตอบ - ต่อไปดู ใครปล่อยการรอ ขยาย ReadyThreadStack และตรวจ ReadyingProcess / ReadyingThreadId หากถูกปลุกจาก
KiTimerExpirationของเคอร์เนล มันเป็นตัวตั้งเวลา (= มันหลับจนหมดเวลา) หากถูกปลุกจากการจัดการความสมบูรณ์ของ I/O นั่นยืนยันว่าเป็นการรอ I/O4 - หากฝ่ายที่ปลุกมันเป็นเธรดอื่นหรือโปรเซสอื่น สอบสวนเธรดนั้นด้วยขั้นตอนเดียวกัน “A รอให้ B ปล่อยล็อก B รอการตอบ RPC ของ C C รอดิสก์ I/O” — สิ่งที่คุณมีเมื่อเดินโซ่นี้ถึงรากคือเส้นทางวิกฤตของความล่าช้า7
flowchart TB
accTitle: โซ่เส้นทางวิกฤตที่คุณเดินในการวิเคราะห์การรอ
accDescr: ดูใน NewThreadStack ของเธรด A ที่ล่าช้าว่ามันกำลังทำอะไรเมื่อหยุด ระบุผู้ปลุก B จาก ReadyThreadStack และ ReadyingProcess และสอบสวน B ด้วยขั้นตอนเดียวกันลงถึงดิสก์ I/O ที่ราก
a["เธรด A(งานที่ล่าช้า)"] -->|"รอล็อก"| b["เธรด B(ถือล็อก)"]
b -->|"รอ RPC"| c["โปรเซส C"]
c -->|"รอ I/O ซิงค์"| d["ดิสก์ I/O(ราก)"]
d -.->|"ความสมบูรณ์ปลุก C"| c
c -.->|"การตอบปลุก B"| b
b -.->|"การปล่อยล็อกปลุก A"| a
ภาพ 9: ดูใน NewThreadStack ของเธรด A ที่ล่าช้าว่ามันกำลังทำอะไรเมื่อหยุด ระบุผู้ปลุก B จาก ReadyThreadStack และ ReadyingProcess และสอบสวน B ด้วยขั้นตอนเดียวกันลงถึงดิสก์ I/O ที่ราก
ในกรณีอย่าง “เราทำมัลติเธรดแล้วยังไม่เร็วขึ้น” ขั้นตอนนี้แสดง ทุกเวิร์กเกอร์เรียงบนล็อกเดียว ตามที่เป็น การหลีกเลี่ยงการแย่งล็อกด้วยการออกแบบอยู่ใน “แนวปฏิบัติมัลติเธรดในทางปฏิบัติ: ฉบับ .NET” และกลไก Windows ที่รันบนการแจ้งความสมบูรณ์แทนการรอใน I/O ซิงโครนัสอยู่ใน “I/O Completion Ports (IOCP) และ .NET Thread Pool” การตรึง “มันรอใคร” ใน WPA และการแก้ด้วยข้อโต้แย้งการออกแบบเหล่านั้นเป็นไหลต่อเนื่องหนึ่งสาย
7. ดิสก์และไฟล์ I/O — การระบุ “ใครสักคนกำลังสแกนดิสก์”
ตัวการคลาสสิกของ “พีซีทั้งเครื่องช้า” ไม่ใช่ CPU แต่เป็นดิสก์ คุณสอบสวนด้วย Disk Usage และ File I/O ในหมวด Storage15
Disk Usage คือระเบียนของดิสก์ I/O และสองคอลัมน์สำคัญ Disk Service Time คือเวลาที่อุปกรณ์ดิสก์ใช้จริงในการประมวลผล I/O นั้น IO Time คือเวลาตั้งแต่ I/O เข้าคิวของ OS จนเสร็จ IO Time อย่างน้อยเท่ากับ Service Time ตามปริมาณการเข้าคิว ดังนั้น หาก IO Time ยาวกว่า Service Time มาก I/O นั้นกำลัง “รอในคิว”6 อย่างไรก็ตาม แค่นั้นยังไม่ตัดสินว่าตัวการที่ทำให้คิวคือโปรเซสอื่น หรือเพียง I/O หนักของโปรเซสนั้นเองที่เรียงบนอุปกรณ์ช้า อย่าสรุปที่นี่ ให้ลงด้วย Service Time (การตอบของอุปกรณ์เอง) และการแยกรายละเอียดถัดไปตามโปรเซส เส้นทาง และสแตก
แล้วด้วยพรีเซ็ต Utilization by Process, Path Name, Stack มองว่าโปรเซสใดออก I/O ไปยังไฟล์ใดจากสแตกใด เรียงจาก IO Time หรือ Size มากไปน้อย15 คำตอบที่ขึ้นบ่อยในสนามคือสองอย่างนี้
- แอนติไวรัสกำลังสแกนทุกไฟล์ ในหน้าต่างที่แอปสตาร์ตช้า โปรเซสแอนติไวรัสถูกเห็นออกการอ่านปริมาณมาก ชื่อโปรเซส เส้นทาง และปริมาณเป็นหลักฐานตามที่เป็นสำหรับการพูดคุยเรื่องการยกเว้น
- โปรเซสอื่นกำลังเขียนหนัก สำรอง อินเด็กเซอร์ ล็อกที่เขียนมากเกินไป และคล้ายกัน เมื่อการเขียนถึงดิสก์เกี่ยวข้องกับ cache manager ดังนั้นข้อเท็จจริงที่ “ขณะที่คุณเขียน” กับ “ขณะที่ดิสก์ยุ่ง” แยกได้ก็อยู่ใน “Cache Manager — เมื่อใด WriteFile ของคุณถึงดิสก์จริง ๆ”
File I/O คือชั้นขึ้นไปหนึ่งขั้น ระเบียนของการดำเนินการไฟล์ที่แอปออก (Create/Read/Write และคล้ายกัน) และพรีเซ็ตเช่น Duration by Process, Thread, Type สามารถรวมเวลาต่อชื่อไฟล์และต่อการดำเนินการ15 กรณีที่ใช้เวลาในระบบไฟล์หรือไดรเวอร์กรองก่อนถึงดิสก์ไม่ปรากฏใน Disk Usage ดังนั้นความไม่ตรงเอง — “Disk Usage สงบแต่ File I/O ช้า” — คือเบาะแส หากต้องการเริ่มจากกลไกของ I/O ซิงโครนัสและอะซิงโครนัส ดู “I/O ซิงโครนัสและอะซิงโครนัส — OVERLAPPED หมายความว่าอะไรจริง ๆ”
flowchart TB
accTitle: ชั้นต่างที่ File IO และ Disk Usage เห็น
accDescr: การดำเนินการไฟล์ของแอปเดินผ่านระบบไฟล์และไดรเวอร์กรองจากคิว I/O ของ OS ไปยังอุปกรณ์ดิสก์ File IO บันทึกการดำเนินการที่ชั้นบน Disk Usage บันทึก I/O ที่ถึงดิสก์ ความต่างระหว่าง IO Time กับ Disk Service Time คือเวลาคิว
app["แอป: ReadFile / WriteFile"] --> fio["FS และตัวกรอง(File I/O)"]
fio --> queue["คิว I/O ของ OS"]
queue --> dev["อุปกรณ์ดิสก์(Disk Usage)"]
fio -.-> n1["Disk Usage พลาด"]
queue -.-> n2["IO Time − Service Time"]
dev -.-> n3["Service Time = อุปกรณ์"]
ภาพ 10: การดำเนินการไฟล์ของแอปเดินผ่านระบบไฟล์และไดรเวอร์กรองจากคิว I/O ของ OS ไปยังอุปกรณ์ดิสก์ File IO บันทึกการดำเนินการที่ชั้นบน Disk Usage บันทึก I/O ที่ถึงดิสก์ ความต่างระหว่าง IO Time กับ Disk Service Time คือเวลาคิว
แนวคิด “อาจขาดหน่วยความจำและกำลังสลับ” สามารถแยกเบื้องต้นใน Task Manager และ Resource Monitor ก่อนไป WPA อย่างไรก็ตาม อย่าตัดจากหน่วยความจำที่ commit เพียงอย่างเดียว — แม้มีหัว commit สถานการณ์ที่แรงดันหน่วยความจำกายภาพตัด working set และ hard fault ต่อเนื่องก็เป็นไปได้ ตรวจหน่วยความจำกายภาพที่ใช้ได้และ “Hard Faults/sec” ของ Resource Monitor ด้วย วิธีอ่านอยู่ใน “"การใช้หน่วยความจำ" ของ Windows หมายความว่าอะไรจริง ๆ”
8. บูตและล็อกออนช้า — ประตูเข้าเทรซบูต
ประเภท “สตาร์ตใช้เวลา 3 นาที” จบก่อนที่คุณจะรัน wpr -start ด้วยมือได้ WPR มี เทรซบูต และคุณจัดให้ OS เริ่มบันทึกอัตโนมัติในการบูตครั้งถัดไปได้3
:: 1. Arrange automatic recording on the next boot
wpr -boottrace -addboot GeneralProfile -filemode
:: 2. Restart (reproduce the slow boot)
:: 3. After boot, stop recording and save (the arrangement is also cleared)
mkdir C:\temp 2>nul
wpr -boottrace -stopboot C:\temp\boot.etl "Issue where boot takes 3 minutes"
flowchart TB
accTitle: ไหลเทรซบูต
accDescr: หลังจากจัดการบันทึกอัตโนมัติในการบูตครั้งถัดไปด้วย addboot และรีสตาร์ต OS เริ่มบันทึกอัตโนมัติตอนบูต การบันทึกด้วย stopboot หลังล็อกออนยังล้างการจัดด้วย หากละทิ้ง ให้ล้างด้วย cancelboot
add["wpr -boottrace -addboot"] --> rebootpc["รีสตาร์ต(บูตช้า)"]
rebootpc --> auto["OS บันทึกตอนบูต"]
auto --> stop2["หลังล็อกออน: -stopboot"]
add -.-> cancel["ละทิ้ง: -cancelboot"]
ภาพ 11: หลังจากจัดการบันทึกอัตโนมัติในการบูตครั้งถัดไปด้วย addboot และรีสตาร์ต OS เริ่มบันทึกอัตโนมัติตอนบูต การบันทึกด้วย stopboot หลังล็อกออนยังล้างการจัดด้วย หากละทิ้ง ให้ล้างด้วย cancelboot
การวัดบูตและชัตดาวน์ที่ xbootmgr เคยเป็นเจ้าของยังรันใน WPR ปัจจุบันได้ด้วยตัวเลือกเช่น -onoffscenario Boot3 เทรซที่จับอ่านด้วยชุดเครื่องมือเดียวกับบทก่อน มองว่าโปรเซสใดเกิดเมื่อใดบนไทม์ไลน์ในกราฟ Processes ซูมไปหน้าต่างที่บูตค้าง และจำแนก CPU การรอ หรือดิสก์ — แอปสตาร์ตที่รออะไรเป็นชุด บริการสตาร์ตที่ค้างบน I/O เฉพาะ และคล้ายกัน กลายเป็นมองเห็นได้ การวิเคราะห์บูตเป็นความเชี่ยวชาญลึกในตัวเอง ดังนั้นบทความนี้ไปแค่ประตูเข้า: “ปัญหาที่จับด้วยมือไม่ได้ยังจับด้วย WPR ได้” เริ่มด้วยการจับภาพรวมด้วยเทรซบูต GeneralProfile
9. รูปแบบการทำงาน — จำแนก → ซูม → สแตก ซ้ำ
เมื่อเครื่องมือชัดแล้ว นี่คือรูปแบบสำหรับการสอบสวนโดยรวม
- ตรึงเวลาของปรากฏการณ์ ไม่ใช่ “มันช้า” แต่ “10:23:40–10:24:10 ช้า” ล็อกแอป ล็อกอีเวนต์ บันทึกจากผู้ที่ดำเนินการ — อะไรก็ได้ หากแอปของตัวเองเขียนจุดตรวจไปยัง ETW หรือล็อกอีเวนต์ อีเวนต์ข้างในเทรซกลายเป็นหลักเวลาตามที่เป็น
- ซูมไปช่วงนั้นเท่านั้น การรวมทั้งเทรซถูกเฉลี่ย และความผิดปกติที่สำคัญถูกเจือจาง การวิเคราะห์ WPA เสมอคือการเปรียบเทียบ “ช่วงที่ผิดปกติ” กับ “ช่วงที่ปกติ”
- จำแนก “CPU การรอ หรือ I/O” ก่อน มอง CPU Usage (Sampled) หากไหม้ บทที่ 5 หากไม่ไหม้ Waits ใน CPU Usage (Precise) (บทที่ 6) หาก Disk Usage IO Time พอง บทที่ 7 การแยกสามทางนี้ก่อนกันไม่ให้หลง
- ทำซ้ำสมมติฐาน → ซูม → สแตก หากคิดว่า “แอนติไวรัส?” บีบไปโปรเซสนั้นและหนุนด้วยสแตก หากไม่ยืน สมมติฐานถัดไป ไม่สรุปก่อนเดินถึงสแตกและหนุน คือวินัยของการสอบสวนชนิดนี้
flowchart TB
accTitle: วงวนซ้ำของการสอบสวนประสิทธิภาพ
accDescr: ตรึงเวลาของปรากฏการณ์ ซูมไปช่วง จำแนก CPU / การรอ / I/O สร้างสมมติฐานและบีบ และหนุนด้วยสแตก หากยืน สาเหตุยืนยัน หากไม่ ทำซ้ำด้วยสมมติฐานถัดไป
time["ตรึงเวลา"] --> zoomstep["ซูมไปช่วงนั้น"]
zoomstep --> triage["จำแนก CPU / การรอ / I/O"]
triage --> hypo["สมมติฐานและบีบ"]
hypo --> stack["หนุนด้วยสแตก"]
stack -->|"ยืน"| fix["สาเหตุยืนยัน"]
stack -->|"ไม่"| hypo
ภาพ 12: ตรึงเวลาของปรากฏการณ์ ซูมไปช่วง จำแนก CPU / การรอ / I/O สร้างสมมติฐานและบีบ และหนุนด้วยสแตก หากยืน สาเหตุยืนยัน หากไม่ ทำซ้ำด้วยสมมติฐานถัดไป
สุดท้าย การจัดการไฟล์จับ ไฟล์ ETL สะท้อนข้างในระบบกว้าง: ชื่อทุกโปรเซส เส้นทางไฟล์ที่ถูกเปิด โมดูลที่ถูกโหลด และ (ขึ้นกับโปรไฟล์) ชื่อคีย์รีจิสทรี การจับ GeneralProfile มาตรฐานไม่รวมตัวข้อมูล เช่น เนื้อหาการสื่อสาร แต่ หากคุณเปิดผู้ให้บริการกำหนดเอง เพย์โหลดของอีเวนต์นั้น (สตริงที่แอปบันทึก และคล้ายกัน) เข้าไปตามที่เป็น หลังยืนยันว่าผู้ให้บริการที่คุณเปิดปล่อยอะไร ถือเป็นไฟล์ลับพอที่จะออกจากบริษัท เช่นเดียวกับ packet capture พับ การจับเท่าที่จำเป็น ข้อตกลงกับฝ่ายที่คุณส่งให้ และระยะเก็บและการลบ เข้าสู่ขั้นตอน
flowchart TB
accTitle: สิ่งที่ไฟล์ ETL สะท้อน และวิธีจัดการ
accDescr: ETL สะท้อนทุกชื่อโปรเซส เส้นทางไฟล์ที่ถูกเปิด โมดูล และขึ้นกับโปรไฟล์ชื่อคีย์รีจิสทรี การเปิดผู้ให้บริการกำหนดเองยังรวมเพย์โหลด ถือเป็นความลับ: การจับเท่าที่จำเป็น ข้อตกลงกับอีกฝ่าย และระยะเก็บและการลบ
etl["ไฟล์ ETL"] --> a1["ชื่อ เส้นทาง โมดูล"]
a1 --> a2["คีย์รีจิสทรี(บางส่วน)"]
a2 --> a3["เพย์โหลดกำหนดเอง"]
a3 -.-> rule["ถือเป็นความลับ"]
ภาพ 13: ETL สะท้อนทุกชื่อโปรเซส เส้นทางไฟล์ที่ถูกเปิด โมดูล และขึ้นกับโปรไฟล์ชื่อคีย์รีจิสทรี การเปิดผู้ให้บริการกำหนดเองยังรวมเพย์โหลด ถือเป็นความลับ: การจับเท่าที่จำเป็น ข้อตกลงกับอีกฝ่าย และระยะเก็บและการลบ
10. สรุป
- “พีซีทั้งเครื่องช้า” ที่ Task Manager อธิบายไม่ได้ สอบสวนด้วย ETW เทรซทั้ง OS — จับด้วย WPR อ่านด้วย WPA wpr.exe มากับ Windows 8.1 เป็นต้นไป ดังนั้นการแยกจับในสภาพแวดล้อมลูกค้า นำ ETL กลับบ้าน และอ่านใน WPA บนเครื่องตัวเองยังใช้ได้
- การจับคือสามขั้น
wpr -start GeneralProfile -filemode→ ทำซ้ำ →wpr -stop trace.etlหากทำซ้ำได้ โหมด File ในไม่กี่นาที หากรอ โหมด Memory (บัฟเฟอร์วง) นานกว่าไม่ดีกว่า - WPA เริ่มได้เมื่อรับสามจุด: กฎทองของตาราง (ซ้ายของแถบทอง = การจัดกลุ่ม) การซูมช่วงเวลา และการตั้งค่าสัญลักษณ์ (แอปของตัวเองต้องการ PDB)
- หาก CPU สูง เดินโปรเซส → สแตก → ฟังก์ชันใน CPU Usage (Sampled) หาก CPU ต่ำแล้วยังช้า เดินโซ่ NewThreadStack (มันกำลังทำอะไรเมื่อหยุด) → Waits (รอนานเท่าใด) → ReadyingProcess และ ReadyThreadStack (ใครปลุกมัน) ถึงรากใน CPU Usage (Precise)
- สำหรับดิสก์ เห็น “เวลาที่ใช้ในคิว” จากความต่างระหว่าง Disk Usage IO Time กับ Service Time และระบุสาเหตุ (อุปกรณ์เองช้า หรือใครทำให้คิว) จาก Service Time และการแยกรายละเอียดตามโปรเซส เส้นทาง และสแตก บูตช้าจับได้ด้วย
wpr -boottrace - รูปแบบการทำงานคือ (1) ตรึงเวลา (2) ซูมไปช่วง (3) จำแนก CPU การรอ หรือ I/O (4) ทำซ้ำสมมติฐาน → ซูม → สแตก ถือ ETL เป็นความลับเพราะมีข้อมูลภายใน
หน้าจอของ WPA น่าเกรง และทุกคนหลงในชั่วโมงแรก เมื่อสองกระดูกสันหลัง — “ซ้ายของแถบทองคือการจัดกลุ่ม” และ “Sampled คือที่มันไหม้ Precise คือใครที่มันรอ” — เข้าแล้ว ที่เหลือคือการดำเนินการเดียวกันซ้ำ ครั้งถัดไปที่คำปรึกษามาว่า “CPU ยังเหลือแล้วยังช้า” ปิด Task Manager แล้วจับเทรซ
บทความที่เกี่ยวข้อง
- ตรึง “ช้า” ด้วย PerfView และ dotnet-trace — บทนำปฏิบัติการสอบสวนประสิทธิภาพ .NET
- คู่มือปฏิบัติ Process Monitor (ProcMon) — ตรึง “การตั้งค่าไม่ถูกใช้” และ “ACCESS DENIED” ใน 10 นาที
- บทนำ Windows Event Log และ ETW — วางล็อกของแอปธุรกิจบนกลไกมาตรฐานของ OS
- “การใช้หน่วยความจำ” ของ Windows หมายความว่าอะไรจริง ๆ — อ่าน Working Set, Private Bytes, Commit และ Page File ให้ถูก
- การตั้งค่า Processor Scheduling ของ Windows - บริการพื้นหลังและคอร์ P/E
- PDB (Program Database) คืออะไร — เข้าใจข้อมูลดีบัก สัญลักษณ์ และ Source Link
ด้านให้คำปรึกษาที่เกี่ยวข้อง
KomuraSoft LLC รับการสอบสวนปัญหาประสิทธิภาพทั้งระบบ เช่น “พีซีทั้งเครื่องช้าและไม่รู้ว่าทำไม” “CPU ยังเหลือแล้วแอปยังช้า” และ “เฉพาะสภาพแวดล้อมหนึ่งสตาร์ตช้ามาก” เราจัดการเป็นการมีส่วนร่วมต่อเนื่องหนึ่งสาย ทั้งการออกแบบจับด้วย WPR/WPA (สภาพแวดล้อมใด โปรไฟล์ใด จับเท่าใด) การวิเคราะห์เทรซ และการแก้ที่ตามมาทั้งฝั่งแอปและฝั่งการตั้งค่า
- การพัฒนาแอปพลิเคชัน Windows
- การตรวจสอบบั๊กและวิเคราะห์หาสาเหตุที่แท้จริง
- ที่ปรึกษาด้านเทคนิคและการตรวจทานการออกแบบ
- ติดต่อเรา
ลิงก์อ้างอิง
-
Microsoft Learn, Introduction to WPR. ว่าด้วย WPR เป็นเครื่องมือบันทึกประสิทธิภาพบนฐาน ETW ว่าด้วยรุ่นบรรทัดคำสั่ง WPR.exe มากับ Windows 8.1 เป็นต้นไปโดยไม่ต้องติดตั้งเพิ่ม ความสัมพันธ์กับรุ่น GUI WPRUI.exe และแนวคิดของโปรไฟล์การบันทึก ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Windows Performance Analyzer. ว่าด้วย WPA รวมอยู่ใน Windows ADK เป็นเครื่องมือวิเคราะห์ที่สร้างกราฟและตารางข้อมูลจากอีเวนต์ ETW ที่ WPR, Xperf และคล้ายกันบันทึก และเปิดและวิเคราะห์ไฟล์ ETL ใดก็ได้ ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WPR Command-Line Options. วากยสัมพันธ์ของ wpr -start/-stop/-cancel/-status/-profiles -filemode (ค่าเริ่มต้นคือโหมดหน่วยความจำ) การระบุหลายโปรไฟล์พร้อมกัน เทรซบูตด้วย -boottrace (addboot/stopboot/cancelboot) และการบันทึกการเปลี่ยน On/Off เช่น Boot ด้วย -onoffscenario ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, CPU Analysis. นิยามของคอลัมน์กราฟ CPU Usage (Precise) (NewThreadStack, ReadyThreadStack, ReadyingProcess, Waits และคล้ายกัน) ขั้นตอนการขยาย ReadyThreadStack และเดิน ReadyingProcess/ReadyingThread ถึงสาเหตุรากของการรอ และวิธีบอกการปลุกจาก KiTimerExpiration (การรอตัวตั้งเวลา) หรือจากความสมบูรณ์ของ I/O ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Troubleshoot processes and threads by using WPR and WPA. การตั้งค่าเช่นการอ่าน CPU Usage (Sampled) เป็น Process→Stack เมื่อการใช้ CPU สูง และการใช้ CPU Usage (Precise) Readying Process, Readying Thread, Readying Stack และคอลัมน์ Wait ในการวิเคราะห์การรอ และตารางสอดคล้องของโปรไฟล์และกราฟตามอาการ ↩ ↩2
-
Microsoft Learn, Exercise 2 - Evaluate Fast Startup Using Windows Performance Toolkit. ว่าด้วย CPU Usage (Sampled) คือการสุ่มที่ช่วงประมาณ 1 มิลลิวินาทีและกิจกรรมสั้นระหว่างตัวอย่างไม่ถูกบันทึก ขั้นตอนการเดินโปรเซส → เธรด → สแตกเพื่อระบุรายละเอียดของการใช้ CPU และความหมายของ Disk Usage IO Time (รวมเวลาคิว) และ Disk Service Time (เวลาประมวลผลดิสก์) ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Exercise 3 - Understand Critical Path and Wait Analysis. แนวคิดของการวิเคราะห์เส้นทางวิกฤต (การจำแนก Running / Ready / Waiting) ความหมายของคอลัมน์ตาราง CPU Usage (Precise) NewThreadStack, ReadyThreadStack, ReadyingProcess, Waits, Ready และคล้ายกัน และขั้นตอนการเดินเธรดผู้ปลุกทีละตัวเพื่อคลายโซ่ความล่าช้า ↩ ↩2 ↩3
-
Microsoft Learn, Loading Symbols. ว่าด้วยเมื่อ _NT_SYMBOL_PATH ไม่ถูกตั้ง WPA อ้างเซิร์ฟเวอร์สัญลักษณ์สาธารณะของ Microsoft (msdl.microsoft.com) โดยค่าเริ่มต้น การเพิ่มเส้นทาง PDB สำหรับคอมโพเนนต์ของตัวเอง และว่าด้วย WPR สร้าง PDB สำหรับสัญลักษณ์ managed ของ .NET ในโฟลเดอร์ .ngenpdb ข้างเทรซและ WPA อ้างอัตโนมัติ ↩ ↩2 ↩3
-
Microsoft Learn, Built-in Recording Profiles. รายการโปรไฟล์การบันทึกที่สร้างใน WPR (การใช้ CPU กิจกรรม Disk I/O กิจกรรม File I/O กิจกรรม Registry I/O กิจกรรม Networking I/O และอื่น ๆ) และสิ่งที่แต่ละโปรไฟล์บันทึก ↩
-
Microsoft Learn, Logging Mode. ว่าด้วยโหมดบันทึกคือ File (ไฟล์ต่อเนื่อง) และ Memory (บัฟเฟอร์วงกลมในหน่วยความจำ) และค่าเริ่มต้นคือ Memory ว่าด้วย Memory เหมาะกับปัญหาที่จังหวะไม่รู้และอีเวนต์เก่าถูกเขียนทับ และว่าด้วยเพดานเดียวของ File คือพื้นที่ดิสก์ว่างและไฟล์ที่ใหญ่เกินไปอาจวิเคราะห์ใน WPA ไม่ได้ ↩ ↩2
-
Microsoft Learn, WPR How-to Topics. ขั้นตอนการเริ่มและหยุดการบันทึกใน WPRUI การเลือกโปรไฟล์ ระดับรายละเอียด และ Logging mode และข้อควรระวังว่าการบันทึกนานทำให้ไฟล์ใหญ่และวิเคราะห์ใน WPA ไม่ได้ จึงควรเลือกโหมด Memory ↩ ↩2
-
Microsoft Learn, Graph Explorer. ว่าด้วยหน้าต่าง Graph Explorer แสดงภาพย่อกราฟเป็นหมวด เช่น System Activity, Computation, Storage และ Memory และว่าด้วยคุณลากกราฟไปแท็บ Analysis เพื่อแสดงร่วมกับตาราง ↩
-
Microsoft Learn, Graphs (WPA Features). การแสดงกราฟ Flame ของ WPA โครงสร้างตารางที่คอลัมน์ทางซ้ายของแถบทองคือการจัดกลุ่มและคอลัมน์ทางขวาของแถบน้ำเงินคือผลรวม และพรีเซ็ต Flame by Process, Stack ของ CPU Usage (Sampled) ↩ ↩2
-
Microsoft Learn, Load Symbols or Configure Symbol Paths. การโหลดสัญลักษณ์ด้วย Load Symbols จากเมนู Trace ของ WPA และขั้นตอนการตั้งและเปลี่ยนเส้นทางสัญลักษณ์ในกล่องโต้ตอบ Configure Symbol Paths ↩
-
Microsoft Learn, List of WPA Graphs. รายการกราฟที่มีใน WPA พรีเซ็ต Disk Usage เช่น IO Time by Process, IO Type Service Time by Process, Path Name, Stack Utilization by Process, Path Name, Stack และพรีเซ็ต File I/O เช่น Duration by Process, Thread, Type ↩ ↩2 ↩3
บทความที่เกี่ยวข้อง
บทความล่าสุดที่มีแท็กเดียวกัน เพื่อเจาะลึกหัวข้อใกล้เคียง
แอปที่พังเมื่อรีซูมจากสลีป — อีเวนต์พลังงานของ Windows ทำงานอย่างไร และสร้างแอปธุรกิจที่รอดได้อย่างไร
เปิดแล็ปท็อปแล้วการเชื่อมต่อของแอปธุรกิจตาย — สาเหตุคือการออกแบบที่ไม่เคยคิดถึงสลีป บทความนี้ครอบคลุมลำดับการแจ้ง WM_POWERBROADCAST พฤติก...
DllMain และ Loader Lock — เหตุผลจริงที่ถูกบอกให้ "อย่าทำอะไรในการเริ่มต้น DLL"
ทำไมคุณต้องไม่เรียก LoadLibrary หรือซิงโครไนซ์กับเธรดอื่นจาก DllMain บทความนี้อธิบายจากแหล่งปฐมภูมิว่า loader lock ทำให้การแจ้ง DLL ทุกคร...
"ไม่ตอบสนอง" คืออะไรจริง ๆ — Windows ตัดสินว่าแอปแฮงอย่างไร และออกแบบอย่างไรให้ไม่แฮง
"ไม่ตอบสนอง" ของ Windows คือกลไกที่ OS ตัดสินว่าหน้าต่างไม่ได้ดึงข้อความเป็นเวลา 5 วินาทีแล้วแทนที่ด้วยหน้าต่างโกสต์ บทความนี้ครอบคลุมภาย...
Win32 Thread Pool API — คอนเคอร์เรนซีโดยไม่สร้างเธรดเอง ด้วย CreateThreadpoolWork
โค้ดเนทีฟของคุณกระจายการเรียก CreateThread ไปทั่วหรือไม่ บทความนี้อธิบาย Win32 thread pool API ที่ออกแบบใหม่ใน Vista — ออบเจ็กต์สี่ชนิด w...
Named Pipe ในทางปฏิบัติ — IPC มาตรฐานของ Windows ตั้งแต่การออกแบบถึงความปลอดภัย
คู่มือเชิงปฏิบัติเรื่อง named pipe ซึ่งเป็นการสื่อสารระหว่างโปรเซสมาตรฐานของ Windows บทความนี้จัดระเบียบจากแหล่งปฐมภูมิ ทั้งการเลือกระหว่...
หัวข้อที่เกี่ยวข้อง
หน้าเหล่านี้วางหัวข้อไว้ในบริบทที่กว้างขึ้นของบริการและการตัดสินใจ
หัวข้อเทคนิคของ Windows
ประตูสู่การพัฒนา Windows การตรวจสอบบั๊ก และการใช้ประโยชน์จากสินทรัพย์เดิม
บริการที่เกี่ยวข้องกับหัวข้อนี้
บทความนี้เกี่ยวข้องโดยตรงกับบริการต่อไปนี้
พัฒนาแอป Windows
แอปธุรกิจ การเชื่อมต่ออุปกรณ์ และเครื่องมือสื่อสาร ตั้งแต่ความต้องการจนถึงการพัฒนา
คำถามที่พบบ่อย
คำถามที่มักพบในการปรึกษาเกี่ยวกับหัวข้อของบทความนี้
- หา WPR และ WPA ได้ที่ไหน ใช้ในสภาพแวดล้อมลูกค้าที่ติดตั้งซอฟต์แวร์ไม่ได้หรือไม่
- เครื่องมือจับ wpr.exe (รุ่นบรรทัดคำสั่ง) มากับ Windows 8.1 เป็นต้นไป จึงใช้ได้โดยไม่ต้องติดตั้งเพิ่ม รุ่น GUI คือ WPRUI และเครื่องมือวิเคราะห์ WPA (Windows Performance Analyzer) รวมอยู่ใน Windows ADK (Windows Assessment and Deployment Kit) และต้องติดตั้งแยก ในทางปฏิบัติ หากแยกงานเป็น "ในสภาพแวดล้อมลูกค้าจับไฟล์ ETL ด้วย wpr.exe มาตรฐานของ OS เท่านั้น นำกลับบ้าน แล้ววิเคราะห์ใน WPA บนเครื่องตัวเอง" คุณสอบสวนประสิทธิภาพทั้งระบบได้แม้ที่ไซต์ที่เพิ่มซอฟต์แวร์ไม่ได้
- ทำไมช้าทั้งที่ Task Manager แสดงว่า CPU ยังเหลือ เห็นอะไรใน WPA ได้บ้าง
- เมื่อการใช้ CPU ต่ำแล้วยังช้า งานไม่ได้ใช้ CPU ไม่ได้ — มันหยุด "รออะไรสักอย่าง" การแย่งล็อก การรอ I/O ซิงโครนัสให้เสร็จ และการรอโปรเซสอื่นตอบ เป็นแบบฉบับ Task Manager แสดงแค่ผล คือการใช้ WPA ของ CPU Usage (Precise) แสดงจากระเบียนต่อ context switch ว่าเธรดเริ่มรอที่ไหน (NewThreadStack) รอนานเท่าใด (Waits) และใครปลุกมัน (ReadyingProcess, ReadyThreadStack) โดยเดินตามฝ่ายที่ทำให้มันรอ คุณระบุ "ตัวการของความช้า" ลงถึงฟังก์ชันได้
- ควรจับเทรซนานเท่าใด ไฟล์จะไม่ใหญ่เกินไปหรือ
- หากทำซ้ำปัญหาได้ เส้นฐานคือเริ่มก่อนทำซ้ำเล็กน้อย หยุดทันทีหลัง และเก็บไว้ในไม่กี่นาที ค่าเริ่มต้นของ WPR คือโหมด Memory ซึ่งบันทึกลงบัฟเฟอร์วงกลมในหน่วยความจำ อีเวนต์เก่าถูกเขียนทับ จึงเหมาะกับการรอปัญหาที่จังหวะไม่รู้ โหมด File ด้วย -filemode เก็บทุกอย่างในไฟล์ต่อเนื่อง แต่เพดานเดียวคือพื้นที่ดิสก์ว่าง และไฟล์ที่ใหญ่เกินไปอาจวิเคราะห์ใน WPA ไม่ได้ ใช้โหมด Memory สำหรับการรอนาน โหมด File สำหรับการทำซ้ำสั้นที่เชื่อถือได้
- ควรเลือกระหว่าง PerfView กับ WPA อย่างไร
- ทั้งสองเครื่องมือจัดการ ETW เทรซ แต่จุดแข็งต่างกัน PerfView เข้าใจรันไทม์ .NET ลึก และแข็งที่การสอบสวนเฉพาะแอป managed เช่น GC การจัดสรร และ JIT WPA เหมาะกับการอ่าน CPU ดิสก์ ไฟล์ I/O พลังงาน และอื่น ๆ ทั้ง OS ข้ามกราฟและตาราง และเป็นตัวเลือกแรกเมื่อ "ไม่ใช่แอปเฉพาะ แต่พีซีทั้งเครื่องช้า" "มีหลายโปรเซสเกี่ยวข้อง" หรือ "สงสัยสิ่งนอกแอป (แอนติไวรัส ไดรเวอร์ โปรเซสอื่น)" กฎง่าย ๆ คือ PerfView สำหรับความช้าของแอป .NET ของตัวเองเพียงอย่างเดียว WPR/WPA สำหรับความช้าของทั้งระบบ
- รัน WPR ในสภาพแวดล้อมโปรดักชันของลูกค้าได้หรือไม่
- การจับสั้นเป็นเรื่องปกติในสนาม แต่ไม่ปลอดภัยโดยไม่มีเงื่อนไข ETW เบา แต่การบันทึกอีเวนต์ปริมาณมากพร้อมสแตกก็กิน CPU และหน่วยความจำระดับหนึ่ง พับข้อพิจารณา เช่น เริ่มก่อนขั้นตอนทำซ้ำเล็กน้อยและหยุดทันทีหลัง เก็บการจับในไม่กี่นาที และรันตอนที่ผลกระทบต่อธุรกิจน้อย เข้าสู่กระบวนการอนุมัติเดียวกับการเปลี่ยนแปลงทั่วไป นอกจากนี้ ไฟล์ ETL มีข้อมูลภายในระบบ เช่น ชื่อโปรเซส เส้นทางไฟล์ และข้อมูลเอ็กซีคิวเทเบิล จึงควรวางไว้ล่วงหน้าว่าจะจัดการอย่างไรหากออกจากบริษัท (ลดขนาด ระยะเก็บ ลบ)