ตรวจสอบโปรไฟล์ประสิทธิภาพและประสิทธิภาพของโค้ด

เสร็จสมบูรณ์เมื่อ

ในการพัฒนาซอฟต์แวร์ ประสิทธิภาพเป็นคุณสมบัติ โปรแกรมอาจทํางานได้ถูกต้อง แต่ถ้าช้าเกินไปหรือใช้ทรัพยากรมากเกินไปผู้ใช้จะหงุดหงิดและโอกาสทางธุรกิจอาจสูญเสียไป

พิจารณาข้อสังเกตของอุตสาหกรรมต่อไปนี้:

  • สําหรับแพลตฟอร์มอีคอมเมิร์ซ เวลาแฝงที่เพิ่มขึ้นทุกๆ 100 มิลลิวินาทีอาจมีค่าใช้จ่ายในการขายประมาณ 1% ในสถานการณ์ที่มีปริมาณมาก แม้แต่เสี้ยววินาทีก็อาจทําให้สูญเสียรายได้หลายล้านดอลลาร์
  • การทําให้ผลการค้นหาช้าลงเพียงครึ่งวินาทีสามารถลดการเข้าชมได้ 20% ผู้ใช้คาดหวังการตอบสนองที่รวดเร็ว หากแอปพลิเคชันของคุณล่าช้า อาจเปลี่ยนไปใช้ทางเลือกอื่น

ข้อสังเกตเหล่านี้เน้นย้ําความจริงพื้นฐาน: ซอฟต์แวร์ที่รวดเร็วมอบประสบการณ์การใช้งานที่ดีขึ้นและมักจะสัมพันธ์โดยตรงกับตัวชี้วัดความสําเร็จ (ยอดขาย การมีส่วนร่วม การรักษาลูกค้า) สําหรับระบบภายในหรือระบบแบ็กเอนด์ ประสิทธิภาพจะแปลเป็นประสิทธิภาพ (เช่น การจัดการธุรกรรมต่อวินาทีมากขึ้นหรือลดต้นทุนระบบคลาวด์)

อย่างไรก็ตาม การบรรลุประสิทธิภาพสูงไม่ได้เกี่ยวกับการคาดเดาอย่างดุเดือดหรือการเพิ่มประสิทธิภาพโค้ดทุกบรรทัดอย่างหมกมุ่น มันเกี่ยวกับการค้นหาพื้นที่เฉพาะที่สําคัญและปรับปรุง นั่นคือที่มาของการสร้างโปรไฟล์ประสิทธิภาพ

โปรไฟล์ประสิทธิภาพคืออะไร

การทําโปรไฟล์ประสิทธิภาพเป็นกระบวนการวิเคราะห์โปรแกรมเพื่อทําความเข้าใจว่าทรัพยากรถูกใช้อย่างไร – ส่วนใหญ่คือเวลา CPU, หน่วยความจํา, ดิสก์/เครือข่าย I/O เป็นต้น ตัวสร้างโปรไฟล์ (หรือเทคนิคการทําโปรไฟล์) ช่วยตอบคําถามประเภทต่อไปนี้:

  • ฟังก์ชันหรือการดําเนินการใดที่ใช้เวลามากที่สุด
  • การใช้หน่วยความจําพุ่งสูงขึ้นที่ไหน?
  • รหัสนี้เรียกกี่ครั้ง? มีการดําเนินการซ้ําซ้อนหรือไม่?
  • แอปพลิเคชันกําลังรอทรัพยากรภายนอก (เช่น ฐานข้อมูลหรือระบบไฟล์) หรือไม่

การทําโปรไฟล์เป็นงานสืบสวนเกี่ยวกับพฤติกรรมรันไทม์ของโค้ดของคุณ แทนที่จะเดาว่าการชะลอตัวจะอยู่ที่ใด คุณรวบรวมข้อมูลเพื่อระบุตําแหน่ง

ในฐานะนักพัฒนา คุณอาจมีลางสังหรณ์เกี่ยวกับสิ่งที่ช้า แต่สัญชาตญาณอาจทําให้เข้าใจผิดได้ กล่าวอีกนัยหนึ่ง:

  • อย่าใช้ความพยายามในการเพิ่มประสิทธิภาพโค้ดที่ไม่ใช่ปัญหาคอขวด ("97%" ของโค้ดที่ไม่สําคัญต่อเวลา)
  • เพิ่มประสิทธิภาพ "3%ที่สําคัญ" ซึ่งเป็นส่วนของโค้ดที่การทําโปรไฟล์แสดงให้เห็นว่าเป็นฮอตสปอตประสิทธิภาพ

เคล็ดลับคือการ ระบุ 3%ที่สําคัญ และนั่นคือสิ่งที่เครื่องมือและเทคนิคการทําโปรไฟล์ช่วยให้คุณทําได้

เครื่องมือสร้างโปรไฟล์ประสิทธิภาพ

ในการสร้างโปรไฟล์แอปพลิเคชันของคุณอย่างมีประสิทธิภาพ มีเครื่องมือสร้างโปรไฟล์ที่หลากหลาย ตั้งแต่คลาสในตัวที่เรียบง่ายไปจนถึงเครื่องมือและโซลูชันอุตสาหกรรมที่ซับซ้อน

นาฬิกาจับเวลาสําหรับการวัดเวลาพื้นฐาน

System.Diagnostics.Stopwatchคลาสใน .NET เป็นวิธีง่ายๆ ในการวัดเวลาดําเนินการ เหมาะอย่างยิ่งสําหรับการวัดที่รวดเร็วและตรงเป้าหมาย:

var stopwatch = Stopwatch.StartNew();
// Code to measure
stopwatch.Stop();
Console.WriteLine($"Execution time: {stopwatch.ElapsedMilliseconds} ms");

แม้ว่านาฬิกาจับเวลาจะมีประโยชน์สําหรับการจับเวลาพื้นฐาน แต่ก็ไม่ได้ให้ข้อมูลเชิงลึกโดยละเอียดเกี่ยวกับการใช้หน่วยความจําหรือการแจกแจงประสิทธิภาพระดับวิธีการ

BenchmarkDotNet สําหรับการเปรียบเทียบที่ครอบคลุม

BenchmarkDotNet เป็นไลบรารี .NET อันทรงพลังที่ออกแบบมาเพื่อการเปรียบเทียบประสิทธิภาพที่แม่นยํา จัดการข้อผิดพลาดในการเปรียบเทียบทั่วไปโดยอัตโนมัติ เช่น การคอมไพล์แบบทันเวลา (JIT) การรบกวนการเก็บขยะ และความแม่นยําในการวัด:

[MemoryDiagnoser]
public class MyBenchmark
{
    [Benchmark]
    public void Method1() => // Implementation
    
    [Benchmark]
    public void Method2() => // Implementation
}

BenchmarkDotNet ให้การวิเคราะห์ทางสถิติ การติดตามการจัดสรรหน่วยความจํา และสามารถเปรียบเทียบการใช้งานหลายรายการแบบเคียงข้างกัน ทําให้เหมาะอย่างยิ่งสําหรับการตรวจสอบความพยายามในการเพิ่มประสิทธิภาพ

Note

โมดูลการฝึกอบรมนี้ไม่ครอบคลุมวิธีการใช้เครื่องมือการสร้างโปรไฟล์ อย่างไรก็ตาม เครื่องมือสร้างโปรไฟล์จะกล่าวถึงในรายละเอียดเพิ่มเติมในภายหลังในโมดูลนี้ และแอปพลิเคชันตัวอย่างที่ใช้ในแบบฝึกหัดจะสาธิตวิธีใช้เครื่องมือ Stopwatch และ BenchmarkDotNet

พิจารณาประสิทธิภาพของโค้ดตลอดกระบวนการพัฒนา

ทางที่ดีควรรวมการพิจารณาด้านประสิทธิภาพตลอดวงจรการพัฒนา

ขั้นตอนการออกแบบ

คิดเกี่ยวกับอัลกอริทึมที่มีประสิทธิภาพและโครงสร้างข้อมูลที่เหมาะสมสําหรับปัญหาของคุณ หากคุณคาดว่าจะจัดการระเบียนหลายล้านรายการ โซลูชัน O(n²) อาจเป็นปัญหา การตัดสินใจระดับสูงในช่วงต้น (ตัวอย่างเช่น การใช้ฐานข้อมูลเทียบกับการประมวลผลในหน่วยความจํา หรือการเลือกระหว่างรายการและชุดแฮชสําหรับการค้นหา) มีนัยยะด้านประสิทธิภาพอย่างมีนัยสําคัญ

ขั้นตอนการนําไปใช้

เขียนโค้ดของคุณอย่างชัดเจนและมีประสิทธิภาพในระหว่างการพัฒนาเบื้องต้น อย่าเพิ่มประสิทธิภาพขนาดเล็กก่อนเวลาอันควร แต่ระวังความไร้ประสิทธิภาพอย่างโจ่งแจ้ง ตัวอย่างเช่น หากคุณต้องการตรวจสอบการเป็นสมาชิกบ่อยๆ การใช้ a HashSet แทนการสแกนรายการซ้ําๆ จะชัดเจนขึ้นในเจตนาและเร็วขึ้น

ขั้นตอนการทดสอบโค้ดและการสร้างโปรไฟล์

เมื่อโค้ดหรือฟีเจอร์ของคุณใช้งานได้ ให้วัดประสิทธิภาพการทํางาน สร้างพื้นฐาน (เร็วแค่ไหน? ใช้หน่วยความจําเท่าไหร่?) หากเป็นไปตามเป้าหมายของคุณ (เช่น รายงานสร้างขึ้นภายใน 2 วินาที หรือการใช้งานมีหน่วยความจําต่ํากว่า 1 GB) ก็ดีมาก หากไม่เป็นเช่นนั้น ให้ใช้โปรไฟล์เพื่อตรวจสอบ

การเพิ่มประสิทธิภาพและการทําซ้ํา

มุ่งเน้นไปที่ส่วนที่ช้าที่สุดก่อน บ่อยครั้งที่การปรับปรุงคอขวดหนึ่งหรือสองข้อให้ประโยชน์มหาศาล เป็นเรื่องปกติที่ 80% ของเวลาในการดําเนินการจะใช้ไปกับโค้ด 20% (หรือน้อยกว่า) ซึ่งเป็นตัวแปรของหลักการ Pareto ในซอฟต์แวร์ การทําโปรไฟล์ช่วยค้นหาว่าวิกฤต 20% หลังจากทําการเปลี่ยนแปลงแล้ว ให้ทดสอบอีกครั้งเพื่อตรวจสอบการปรับปรุงและตรวจสอบให้แน่ใจว่าไม่มีสิ่งใดเสียหาย

การตรวจสอบอย่างต่อเนื่อง

ในการผลิตหรือในวงกว้าง ให้จับตาดูตัวชี้วัดประสิทธิภาพ ใช้เครื่องมือตรวจสอบแอปพลิเคชัน (เช่น Application Insights หากคุณใช้ Azure หรืออื่นๆ) เพื่อจับประสิทธิภาพการถดถอย การใช้งานในโลกแห่งความเป็นจริงอาจเผยให้เห็นฮอตสปอตที่แตกต่างกัน (เช่น เมื่อปริมาณข้อมูลเพิ่มขึ้นหรือรูปแบบการใช้งานเปลี่ยนไป)

ข้อผิดพลาดด้านประสิทธิภาพทั่วไป (ไม่ใช่ GUI)

ปัญหาด้านแบ็กเอนด์หรือประสิทธิภาพของโค้ดทั่วไปจํานวนมากเป็นที่รู้จักกันดี

รายการต่อไปนี้ให้ภาพรวมโดยย่อ:

  • ความไร้ประสิทธิภาพของอัลกอริทึม: ใช้อัลกอริทึมหรือวิธีการที่มีประสิทธิภาพน้อยกว่าที่จําเป็น ตัวอย่าง: การเรียงลําดับ O(n²) การคํานวณกําลังดุร้ายที่มีสูตรอยู่ ฯลฯ
  • I/O หรือการโทรภายนอกมากเกินไป: การอ่านจากดิสก์ภายในลูปที่แน่นหนา ทําให้การสืบค้นฐานข้อมูลมากเกินไป (ปัญหาการสืบค้น N+1) หรือการบล็อกการเรียกเครือข่ายบนเธรดหลัก
  • รูปแบบการเข้าถึงข้อมูลที่ไม่มีประสิทธิภาพ: ตัวอย่างเช่น การไม่ใช้ดัชนีในการสืบค้นฐานข้อมูล หรือการค้นหารายการซ้ําๆ แทนการใช้โครงสร้างการค้นหา
  • การใช้หน่วยความจําในทางที่ผิด: การสร้างวัตถุขนาดใหญ่หรือวัตถุขนาดเล็กจํานวนมากโดยไม่จําเป็น ซึ่งนําไปสู่การเก็บขยะจํานวนมาก การถือการอ้างอิงนานเกินไป (ทําให้หน่วยความจําบวม) หรือไม่ทิ้งทรัพยากรอาจทําให้ประสิทธิภาพลดลงได้เช่นกัน
  • ขาดการทํางานพร้อมกันหรือความขนาน: เรียกใช้ทุกอย่างตามลําดับเมื่องานสามารถทําได้พร้อมกัน (บนระบบมัลติคอร์หรือรอ I/O แบบอะซิงโครนัส) อีกทางหนึ่ง หลุมพรางตรงกันข้ามคือการใช้การทํางานพร้อมกันในทางที่ผิด ซึ่งค่าใช้จ่ายมีมากกว่าผลประโยชน์หรือทําให้เกิดความขัดแย้ง
  • การดําเนินการบล็อก: การใช้การบล็อกการรอ (Thread.Sleep, I/O แบบซิงโครนัสในบริบทแบบอะซิงโครนัส ฯลฯ) ที่หยุดความคืบหน้า

GitHub Copilot และการทําโปรไฟล์

GitHub Copilot (โดยเฉพาะ GitHub Copilot Agent) เป็นเครื่องมือใหม่ในกล่องเครื่องมือของคุณ ไม่ใช่ตัวสร้างโปรไฟล์ แต่สามารถทําหน้าที่เหมือน โปรแกรมเมอร์คู่ AI ที่มีหน่วยความจํามากมายเกี่ยวกับปัญหาด้านประสิทธิภาพและการแก้ไขทั่วไป เช่น:

  • GitHub Copilot สามารถอธิบายโค้ดให้คุณฟัง: "ฟังก์ชันนี้ทําอะไรไม่มีประสิทธิภาพหรือไม่" อาจชี้ให้เห็นว่าลูปเฉพาะกําลังทําให้ฐานข้อมูลเรียกการทําซ้ําแต่ละครั้ง ซึ่งมีค่าใช้จ่ายสูง
  • GitHub Copilot สามารถแนะนําการปรับปรุง: "ฉันจะเพิ่มความเร็วโค้ดนี้ได้อย่างไร" อาจแนะนําให้ใช้วิธีการอื่น (ตัวอย่างเช่น การใช้ a StringBuilder for string concatenation ในลูป ซึ่งเป็นแนวทางปฏิบัติที่ดีที่สุดด้านประสิทธิภาพที่รู้จักใน C#)
  • GitHub Copilot สามารถสร้างโค้ดที่ปรับโครงสร้างใหม่ได้หากคุณแจ้ง ซึ่งช่วยประหยัดเวลาในการปรับให้เหมาะสม

ลองนึกถึง GitHub Copilot ในฐานะผู้ช่วยที่อ่านฟอรัมนักพัฒนา หน้าเอกสารประกอบ และการอภิปรายของชุมชนเกี่ยวกับประสิทธิภาพนับไม่ถ้วน ไม่ได้แทนที่ความเข้าใจของคุณ แต่สามารถเร่งกระบวนการระบุและใช้การเพิ่มประสิทธิภาพได้

Summary

การสร้างโปรไฟล์ประสิทธิภาพเป็นทักษะที่สําคัญสําหรับนักพัฒนาที่ต้องการสร้างแอปพลิเคชันที่มีประสิทธิภาพและตอบสนอง ด้วยการวัดและวิเคราะห์ประสิทธิภาพของโค้ดอย่างเป็นระบบ คุณจะสามารถระบุปัญหาคอขวดและเพิ่มประสิทธิภาพส่วนที่สําคัญที่สุดได้ การผสานรวมข้อควรพิจารณาด้านประสิทธิภาพตลอดวงจรการพัฒนา ตั้งแต่การออกแบบไปจนถึงการตรวจสอบอย่างต่อเนื่อง ช่วยให้มั่นใจได้ว่าแอปพลิเคชันของคุณไม่เพียงแต่ทํางานได้อย่างถูกต้อง แต่ยังมอบประสบการณ์การใช้งานที่เหนือกว่าให้กับผู้ใช้อีกด้วย