การแก้ไขข้อบกพร่องเทียบกับประสิทธิภาพการเปิดตัว


133

ฉันพบย่อหน้าต่อไปนี้:

“ การแก้จุดบกพร่องเทียบกับการตั้งค่ารีลีสใน IDE เมื่อคุณคอมไพล์โค้ดของคุณใน Visual Studio แทบจะไม่แตกต่างกับประสิทธิภาพ…โค้ดที่สร้างขึ้นเกือบจะเหมือนกัน คอมไพเลอร์ C # ไม่ได้ทำการปรับให้เหมาะสม คอมไพเลอร์ C # เพียงแค่พ่น IL ... และที่รันไทม์เป็น JITer ที่ทำหน้าที่เพิ่มประสิทธิภาพทั้งหมด JITer มีโหมด Debug / Release ซึ่งสร้างความแตกต่างอย่างมากให้กับประสิทธิภาพ แต่นั่นไม่ได้สำคัญว่าคุณจะเรียกใช้การกำหนดค่าการดีบักหรือรีลีสของโปรเจ็กต์ของคุณหรือไม่นั่นคือกุญแจสำคัญว่าจะแนบดีบักเกอร์หรือไม่

แหล่งที่มาที่นี่และพอดคาสต์เป็นที่นี่

ใครช่วยแนะนำบทความของ Microsoft ที่สามารถพิสูจน์สิ่งนี้ได้จริง

Googling " C # debug vs release performance " ส่วนใหญ่จะแสดงผลลัพธ์ว่า " Debug has a lot of performance hit ", " release is optimized " และ " don't deploy debug to production "



ด้วย. Net4 บน Win7-x86 ฉันมีโปรแกรม จำกัด CPU ที่ฉันเขียนว่าทำงานได้เร็วกว่าการดีบักเกือบ 2 เท่าโดยไม่มีการยืนยัน / etc ในลูปหลัก
Bengie

นอกจากนี้หากคุณสนใจเกี่ยวกับการใช้หน่วยความจำอาจมีความแตกต่างกันมาก ฉันเคยเห็นกรณีที่บริการ Windows แบบมัลติเธรดที่คอมไพล์ในโหมดดีบักใช้ 700MB ต่อเธรดเทียบกับ 50MB ต่อเธรดในรุ่น Release การดีบักบิวด์หน่วยความจำหมดอย่างรวดเร็วภายใต้เงื่อนไขการใช้งานทั่วไป
o. nate

@Bengie - คุณตรวจสอบแล้วหรือยังว่าถ้าคุณแนบ debugger เข้ากับ release build มันยังทำงานเร็วขึ้น 2 เท่า? โปรดทราบว่าคำพูดข้างต้นระบุว่าการเพิ่มประสิทธิภาพ JIT ได้รับผลกระทบจากการแนบดีบักเกอร์หรือไม่
ToolmakerSteve

คำตอบ:


100

จริงบางส่วน ในโหมดดีบักคอมไพลเลอร์จะปล่อยสัญลักษณ์การดีบักสำหรับตัวแปรทั้งหมดและคอมไพล์โค้ดตามที่เป็นอยู่ ในโหมดเผยแพร่การเพิ่มประสิทธิภาพบางอย่างรวมอยู่ด้วย:

  • ตัวแปรที่ไม่ได้ใช้จะไม่ถูกคอมไพล์เลย
  • ตัวแปรลูปบางตัวจะถูกนำออกจากลูปโดยคอมไพเลอร์หากพิสูจน์แล้วว่าเป็นค่าคงที่
  • ไม่รวมโค้ดที่เขียนภายใต้คำสั่ง #debug เป็นต้น

ส่วนที่เหลือขึ้นอยู่กับ JIT

รายการเต็มรูปแบบของการเพิ่มประสิทธิภาพที่นี่มารยาทของเอริค Lippert


10
และอย่าลืมเกี่ยวกับ Debug.Asserts! ในการสร้าง DEBUG หากล้มเหลวพวกเขาจะหยุดเธรดและเปิดกล่องข้อความขึ้นมา ในการเปิดตัวพวกเขาไม่ได้รวบรวมเลย ใช้กับวิธีการทั้งหมดที่มี [ConditionalAttribute]
Ivan Zlatanov

13
คอมไพเลอร์ C # ไม่ทำการเพิ่มประสิทธิภาพการโทรหาง กระวนกระวายใจทำ หากคุณต้องการรายการที่ถูกต้องของสิ่งที่คอมไพลเลอร์ C # ทำเมื่อเปิดสวิตช์เพิ่มประสิทธิภาพโปรดดูblogs.msdn.com/ericlippert/archive/2009/06/11/…
Eric Lippert

64

ไม่มีบทความใดที่ "พิสูจน์" เกี่ยวกับคำถามด้านประสิทธิภาพ วิธีพิสูจน์การยืนยันเกี่ยวกับผลกระทบด้านประสิทธิภาพของการเปลี่ยนแปลงคือลองทั้งสองวิธีและทดสอบภายใต้เงื่อนไขที่เป็นจริง แต่ควบคุมได้

คุณกำลังถามคำถามเกี่ยวกับประสิทธิภาพดังนั้นคุณจึงสนใจเรื่องประสิทธิภาพอย่างชัดเจน หากคุณสนใจเรื่องประสิทธิภาพสิ่งที่ควรทำคือตั้งเป้าหมายประสิทธิภาพบางอย่างจากนั้นเขียนชุดทดสอบด้วยตัวคุณเองเพื่อติดตามความคืบหน้าของคุณกับเป้าหมายเหล่านั้น เมื่อคุณมีชุดทดสอบดังกล่าวแล้วคุณสามารถใช้ชุดทดสอบดังกล่าวเพื่อทดสอบความจริงหรือความเท็จของข้อความเช่น "การสร้างการแก้ปัญหาช้ากว่า"

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

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


2
ฉันคิดว่าคุณสามารถดูแลเกี่ยวกับประสิทธิภาพได้ แต่ก็ยังต้องการใช้ "debug" ตัวอย่างเช่นหากเวลาส่วนใหญ่ของคุณกำลังรอการอ้างอิงฉันไม่คิดว่าการสร้างในโหมดดีบักจะสร้างความแตกต่างได้มาก แต่คุณมีประโยชน์เพิ่มเติมในการรับหมายเลขบรรทัดในสแต็กเทรซซึ่งอาจช่วยแก้ไขข้อบกพร่องได้เร็วขึ้นและทำให้ ผู้ใช้มีความสุขมากขึ้น ประเด็นคือคุณต้องชั่งน้ำหนักข้อดีข้อเสียและคำสั่ง "ทำงานในการดีบักโดยทั่วไปจะช้ากว่า แต่ถ้าคุณใช้ CPU ผูกพัน" ก็เพียงพอที่จะช่วยในการตัดสินใจได้
Josh Mouch

11

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


ฉันเห็นด้วยกับคุณในประเด็นนั้น แต่นี่ไม่ได้ตอบคำถามหลัก
sagie

5
@sagie: ใช่ฉันรู้เรื่องนั้น แต่ฉันคิดว่าประเด็นนั้นยังคุ้มค่าที่จะทำ
Konrad Rudolph

6

จากmsdn โซเชียล

มีเอกสารไม่ดีนี่คือสิ่งที่ฉันรู้ คอมไพเลอร์ปล่อยอินสแตนซ์ของ System.Diagnostics.DebuggableAttribute ในเวอร์ชันดีบักคุณสมบัติ IsJitOptimizerEnabled เป็น True ในเวอร์ชันที่วางจำหน่ายจะเป็น False คุณสามารถดูแอ็ตทริบิวต์นี้ในรายการแอสเซมบลีด้วย ildasm.exe

คอมไพเลอร์ JIT ใช้แอ็ตทริบิวต์นี้เพื่อปิดใช้งานการเพิ่มประสิทธิภาพที่จะทำให้การดีบักทำได้ยาก คนที่ย้ายรหัสไปรอบ ๆ เช่นการชักรอกแบบวนซ้ำ ในบางกรณีสิ่งนี้สามารถสร้างความแตกต่างอย่างมากในด้านประสิทธิภาพ ไม่ปกติแม้ว่า

การแม็พเบรกพอยต์กับแอดเดรสการดำเนินการเป็นงานของดีบักเกอร์ ใช้ไฟล์. pdb และข้อมูลที่สร้างโดยคอมไพเลอร์ JIT ที่ให้คำสั่ง IL ในการแมปโค้ดแอดเดรส หากคุณจะเขียนดีบักเกอร์ของคุณเองคุณจะต้องใช้ ICorDebugCode :: GetILToNativeMapping ()

โดยทั่วไปการปรับใช้การดีบักจะช้าลงเนื่องจากการปรับแต่งคอมไพเลอร์ JIT ถูกปิดใช้งาน


3

สิ่งที่คุณอ่านค่อนข้างใช้ได้ การเปิดตัวมักจะน้อยกว่าเนื่องจากการเพิ่มประสิทธิภาพ JIT ซึ่งไม่รวมโค้ดดีบัก (#IF DEBUG หรือ [Conditional ("DEBUG")]) การโหลดสัญลักษณ์ดีบักน้อยที่สุดและมักไม่ได้รับการพิจารณาคือการประกอบที่น้อยลงซึ่งจะช่วยลดเวลาในการโหลด ประสิทธิภาพแตกต่างกันชัดเจนมากขึ้นเมื่อรันโค้ดใน VS เนื่องจากมี PDB และสัญลักษณ์ที่มีการโหลดมากขึ้น แต่ถ้าคุณรันโดยอิสระความแตกต่างของประสิทธิภาพอาจไม่ชัดเจน โค้ดบางตัวจะปรับให้เหมาะสมได้ดีกว่าโค้ดอื่น ๆ และใช้การปรับให้เหมาะสมฮิวริสติกเช่นเดียวกับในภาษาอื่น ๆ

Scott มีคำอธิบายที่ดีเกี่ยวกับการเพิ่มประสิทธิภาพวิธีการอินไลน์ที่นี่

ดูบทความนี้ที่ให้คำอธิบายสั้น ๆ ว่าเหตุใดจึงแตกต่างกันในสภาพแวดล้อม ASP.NET สำหรับการตั้งค่าการดีบักและรีลีส


3

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

เรามีโค้ดส่วนหนึ่งซึ่งเกี่ยวข้องกับการวนซ้ำที่แน่นหนาซึ่งดูเหมือนจะใช้เวลาตลอดไปในการดีบัก แต่ก็ทำงานได้ดีด้วยตัวมันเอง กล่าวอีกนัยหนึ่งคือไม่มีลูกค้าหรือลูกค้าที่ประสบปัญหา แต่เมื่อเราแก้ไขจุดบกพร่องดูเหมือนว่าจะทำงานเหมือนกากน้ำตาล

ผู้ร้ายเป็นDebug.WriteLineหนึ่งในลูปที่แน่นซึ่งคายข้อความบันทึกหลายพันข้อความออกจากเซสชันการดีบักในขณะที่ย้อนกลับไป ดูเหมือนว่าเมื่อเชื่อมต่อดีบักเกอร์และรับฟังเอาต์พุตดังกล่าวจะมีค่าใช้จ่ายที่เกี่ยวข้องที่ทำให้โปรแกรมช้าลง สำหรับรหัสเฉพาะนี้เป็นไปตามลำดับของรันไทม์ 0.2-0.3 วินาทีของตัวมันเองและ 30+ วินาทีเมื่อติดดีบักเกอร์

วิธีแก้ปัญหาง่ายๆเพียงแค่ลบข้อความดีบักที่ไม่ต้องการอีกต่อไป


2

ในไซต์msdn ...

การวางจำหน่ายเทียบกับการกำหนดค่าการดีบัก

ในขณะที่คุณยังทำงานในโปรเจ็กต์ของคุณโดยทั่วไปคุณจะสร้างแอปพลิเคชันของคุณโดยใช้การกำหนดค่าการดีบักเนื่องจากการกำหนดค่านี้ช่วยให้คุณสามารถดูค่าของตัวแปรและควบคุมการดำเนินการในดีบักเกอร์ คุณยังสามารถสร้างและทดสอบบิวด์ในคอนฟิกูเรชันรีลีสเพื่อให้แน่ใจว่าคุณไม่ได้นำเสนอบั๊กใด ๆ ที่แสดงเฉพาะในบิลด์ประเภทใดประเภทหนึ่งเท่านั้น ในการเขียนโปรแกรม. NET Framework จุดบกพร่องดังกล่าวเกิดขึ้นน้อยมาก แต่สามารถเกิดขึ้นได้

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


2

ฉันเพิ่งพบปัญหาด้านประสิทธิภาพ รายการผลิตภัณฑ์ทั้งหมดใช้เวลามากเกินไปประมาณ 80 วินาที ฉันปรับ DB ปรับปรุงแบบสอบถามแล้วไม่มีความแตกต่างใด ๆ ฉันตัดสินใจสร้าง TestProject และพบว่ากระบวนการเดียวกันนี้ถูกดำเนินการใน 4 วินาที จากนั้นฉันก็รู้ว่าโครงการอยู่ในโหมดดีบักและโครงการทดสอบอยู่ในโหมดเผยแพร่ ฉันเปลี่ยนโปรเจ็กต์หลักเป็นโหมดรีลีสและรายการผลิตภัณฑ์ทั้งหมดใช้เวลาเพียง 4 วินาทีในการแสดงผลลัพธ์ทั้งหมด

สรุป: โหมดดีบักนั้นช้ากว่าโหมดรันมากเนื่องจากจะเก็บข้อมูลการดีบักไว้ คุณควรปรับใช้ในโหมด Relase เสมอ คุณยังคงมีข้อมูลการดีบักได้หากคุณรวมไฟล์. PDB ด้วยวิธีนี้คุณสามารถบันทึกข้อผิดพลาดด้วยหมายเลขบรรทัดได้เช่น


โดย "run mode" คุณหมายถึง "Release"?
Ron Klein

ใช่แน่นอน Release ไม่มีค่าใช้จ่ายในการแก้ไขข้อบกพร่องทั้งหมด
Francisco Goldenstein

1

ในระดับใหญ่นั้นขึ้นอยู่กับว่าแอปของคุณเชื่อมต่อกับการประมวลผลหรือไม่และไม่ใช่เรื่องง่ายที่จะบอกเหมือนในตัวอย่างของ Lasse ถ้าฉันมีคำถามน้อยที่สุดเกี่ยวกับสิ่งที่ทำฉันหยุดมันสองสามครั้งและตรวจสอบสแตก หากมีอะไรพิเศษเกิดขึ้นที่ฉันไม่ต้องการจริงๆสิ่งนั้นก็จะเห็นทันที


1

โหมด Debug และ Release มีความแตกต่างกัน มีเครื่องมือFuzzlyn : เป็นฟัซเซอร์ที่ใช้ Roslyn เพื่อสร้างโปรแกรม C # แบบสุ่ม โปรแกรมนี้รันโปรแกรมเหล่านี้บน. NET core และทำให้มั่นใจได้ว่าจะให้ผลลัพธ์เดียวกันเมื่อคอมไพล์ในโหมด debug และ release

ด้วยเครื่องมือนี้พบและรายงานข้อบกพร่องจำนวนมาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.