Gỡ lỗi so với hiệu suất phát hành


132

Tôi đã gặp đoạn văn sau:

Cài đặt Debug so với Phát hành trong IDE khi bạn biên dịch mã của mình trong Visual Studio hầu như không có sự khác biệt nào đối với hiệu suất. Mã được tạo gần như giống nhau. Trình biên dịch C # không thực sự làm bất kỳ tối ưu hóa. Trình biên dịch C # chỉ cần bật IL IL và trong thời gian chạy, JITer thực hiện tất cả tối ưu hóa. JITer có chế độ Gỡ lỗi / Phát hành và điều đó tạo ra sự khác biệt lớn đối với hiệu suất. Nhưng điều đó không tắt dù bạn chạy cấu hình Gỡ lỗi hay Phát hành dự án của bạn, điều đó sẽ tắt nếu trình gỡ lỗi được đính kèm.

Nguồn ở đây và podcast ở đây .

Ai đó có thể hướng tôi đến một bài viết của Microsoft thực sự có thể chứng minh điều này?

Googling " C # gỡ lỗi so với hiệu suất phát hành " chủ yếu trả về kết quả cho biết " Debug có rất nhiều hiệu năng ", " phát hành được tối ưu hóa " và " không triển khai gỡ lỗi để sản xuất ".


có thể trùng lặp về sự khác biệt
Hans Passant

Với .Net4 trên Win7-x86, tôi có một chương trình giới hạn CPU mà tôi đã viết chạy nhanh hơn gần 2 lần so với gỡ lỗi không có xác nhận / etc trong vòng lặp chính.
Bengie

Ngoài ra, nếu bạn quan tâm đến việc sử dụng bộ nhớ, có thể có sự khác biệt lớn. Tôi đã thấy một trường hợp trong đó một dịch vụ Windows đa luồng được biên dịch ở chế độ Gỡ lỗi đã sử dụng 700MB cho mỗi luồng, so với 50 MB cho mỗi luồng trong bản dựng Phát hành. Bản dựng Debug nhanh chóng hết bộ nhớ trong các điều kiện sử dụng thông thường.
o. nate

@Bengie - bạn đã xác minh rằng nếu bạn đính kèm trình gỡ lỗi vào bản dựng phát hành, nó vẫn chạy nhanh hơn gấp 2 lần? Lưu ý rằng trích dẫn ở trên nói rằng tối ưu hóa JIT bị ảnh hưởng bởi việc trình gỡ lỗi có được đính kèm hay không.
ToolmakerSteve

Câu trả lời:


99

Một phần đúng. Trong chế độ gỡ lỗi, trình biên dịch phát ra các ký hiệu gỡ lỗi cho tất cả các biến và biên dịch mã theo nguyên trạng. Trong chế độ phát hành, một số tối ưu hóa được bao gồm:

  • các biến không sử dụng không được biên dịch
  • một số biến vòng lặp được trình biên dịch đưa ra khỏi vòng lặp nếu chúng được chứng minh là bất biến
  • mã được viết theo chỉ thị #debug không được bao gồm, v.v.

Phần còn lại là tùy thuộc vào JIT.

Danh sách đầy đủ các tối ưu hóa ở đây lịch sự của Eric Lippert .


10
Và đừng quên Debug.Asserts! Trong bản dựng DEBUG, nếu chúng thất bại, chúng sẽ tạm dừng chuỗi và bật lên một hộp thông báo. Trong bản phát hành, chúng không được biên dịch. Điều này áp dụng cho tất cả các phương thức có [ConditableAttribution].
Ivan Zlatanov

13
Trình biên dịch C # không thực hiện tối ưu hóa cuộc gọi đuôi; jitter nào. Nếu bạn muốn có một danh sách chính xác những gì trình biên dịch C # thực hiện khi bật công tắc tối ưu hóa, hãy xem blog.msdn.com/ericlippert/archive/2009/06/11/ Kẻ
Eric Lippert

63

Không có bài viết nào "chứng minh" bất cứ điều gì về một câu hỏi về hiệu suất. Cách để chứng minh một khẳng định về tác động hiệu suất của một thay đổi là thử cả hai cách và kiểm tra nó trong các điều kiện thực tế nhưng được kiểm soát.

Bạn đang hỏi một câu hỏi về hiệu suất, vì vậy rõ ràng bạn quan tâm đến hiệu suất. Nếu bạn quan tâm đến hiệu suất thì việc cần làm là đặt ra một số mục tiêu hiệu suất và sau đó tự viết cho mình một bộ kiểm tra theo dõi tiến trình của bạn so với các mục tiêu đó. Khi bạn có một bộ kiểm tra như vậy, bạn có thể dễ dàng sử dụng nó để tự kiểm tra tính trung thực hoặc giả của các câu như "quá trình gỡ lỗi chậm hơn".

Và hơn nữa, bạn sẽ có thể nhận được kết quả có ý nghĩa. "Chậm" là vô nghĩa vì không rõ là chậm hơn một phần triệu giây hay chậm hơn hai mươi phút. "10% chậm hơn trong điều kiện thực tế" có ý nghĩa hơn.

Dành thời gian bạn sẽ dành để nghiên cứu câu hỏi này trực tuyến để xây dựng một thiết bị trả lời câu hỏi. Bạn sẽ nhận được kết quả chính xác hơn theo cách đó. Bất cứ điều gì bạn đọc trực tuyến chỉ là một phỏng đoán về những gì có thể xảy ra. Lý do từ các sự kiện bạn tự thu thập, không phải từ những người khác đoán về cách chương trình của bạn có thể hoạt động.


2
Tôi nghĩ rằng bạn có thể quan tâm đến hiệu suất nhưng vẫn có mong muốn sử dụng "gỡ lỗi". Ví dụ: nếu hầu hết thời gian của bạn đang chờ đợi phụ thuộc, tôi không nghĩ việc xây dựng ở chế độ gỡ lỗi sẽ tạo ra sự khác biệt lớn, tuy nhiên bạn có thêm lợi ích của việc lấy số dòng trong dấu vết ngăn xếp, điều này có thể giúp sửa lỗi nhanh hơn và thực hiện người dùng hạnh phúc hơn. Vấn đề là bạn phải cân nhắc những ưu và nhược điểm, và một câu lệnh "chạy trong gỡ lỗi chậm hơn, nhưng chỉ khi bạn bị ràng buộc CPU" là đủ để đưa ra quyết định.
Josh Mouch

11

Tôi không thể nhận xét về hiệu suất nhưng lời khuyên không nên triển khai gỡ lỗi cho sản xuất. Vẫn giữ đơn giản vì mã gỡ lỗi thường làm một vài điều khác biệt trong các sản phẩm lớn. Đối với một điều, bạn có thể có các công tắc gỡ lỗi hoạt động và đối với một điều khác có thể sẽ có thêm kiểm tra vệ sinh dự phòng và đầu ra gỡ lỗi không thuộc mã sản xuất.


Tôi đồng ý với bạn về vấn đề đó, nhưng điều này không trả lời câu hỏi chính
sagie 15/03/2016

5
@sagie: vâng, tôi biết điều đó nhưng tôi nghĩ rằng vấn đề vẫn còn đáng làm.
Konrad Rudolph

6

Từ xã hội

Nó không phải là tài liệu tốt, đây là những gì tôi biết. Trình biên dịch phát ra một thể hiện của System.Diagnostics.DebuggableAttribution. Trong phiên bản gỡ lỗi, thuộc tính IsJitOptimizerEnables là True, trong phiên bản phát hành là Sai. Bạn có thể thấy thuộc tính này trong tệp kê khai lắp ráp với ildasm.exe

Trình biên dịch JIT sử dụng thuộc tính này để vô hiệu hóa tối ưu hóa khiến việc gỡ lỗi trở nên khó khăn. Những cái mà di chuyển mã xung quanh như cẩu vòng bất biến. Trong các trường hợp được chọn, điều này có thể tạo ra một sự khác biệt lớn trong hiệu suất. Không thường xuyên mặc dù.

Ánh xạ các điểm dừng đến các địa chỉ thực thi là công việc của trình gỡ lỗi. Nó sử dụng tệp .pdb và thông tin được tạo bởi trình biên dịch JIT cung cấp lệnh IL để ánh xạ địa chỉ mã. Nếu bạn sẽ viết trình gỡ lỗi của riêng mình, bạn sẽ sử dụng ICorDebugCode :: GetILToNativeMapping ().

Về cơ bản việc triển khai gỡ lỗi sẽ chậm hơn do tối ưu hóa trình biên dịch JIT bị vô hiệu hóa.


3

Những gì bạn đọc là khá hợp lệ. Phát hành thường gọn hơn do tối ưu hóa JIT, không bao gồm mã gỡ lỗi (#IF DEBUG hoặc [Có điều kiện ("DEBUG")]), tải biểu tượng gỡ lỗi tối thiểu và thường không được xem là lắp ráp nhỏ hơn sẽ giảm thời gian tải. Hiệu suất khác nhau rõ ràng hơn khi chạy mã trong VS vì PDB rộng hơn và các ký hiệu được tải, nhưng nếu bạn chạy độc lập, sự khác biệt về hiệu suất có thể ít rõ ràng hơn. Một số mã nhất định sẽ tối ưu hóa tốt hơn các mã khác và nó đang sử dụng cùng một phương pháp tối ưu hóa giống như trong các ngôn ngữ khác.

Scott có một lời giải thích tốt về tối ưu hóa phương pháp nội tuyến ở đây

Xem bài viết này đưa ra một lời giải thích ngắn gọn tại sao nó khác trong môi trường ASP.NET cho cài đặt gỡ lỗi và phát hành.


3

Một điều bạn cần lưu ý, liên quan đến hiệu suất và liệu trình gỡ lỗi có được đính kèm hay không, điều gì đó khiến chúng tôi ngạc nhiên.

Chúng tôi đã có một đoạn mã, liên quan đến nhiều vòng lặp chặt chẽ, dường như mất nhiều thời gian để gỡ lỗi, nhưng vẫn chạy khá tốt. Nói cách khác, không có khách hàng hoặc khách hàng nào gặp sự cố, nhưng khi chúng tôi gỡ lỗi, nó dường như chạy như mật mía.

Thủ phạm là một Debug.WriteLinetrong những vòng lặp chặt chẽ, nhổ ra hàng ngàn thông điệp tường trình, còn lại từ một phiên gỡ lỗi một lúc trước. Có vẻ như khi trình gỡ lỗi được đính kèm và lắng nghe đầu ra như vậy, có liên quan đến chi phí làm chậm chương trình. Đối với mã cụ thể này, nó tự chạy theo thời gian 0,2-0,3 giây và hơn 30 giây khi trình gỡ lỗi được đính kèm.

Giải pháp đơn giản, chỉ cần loại bỏ các thông báo gỡ lỗi không còn cần thiết.


2

Trong trang web msd ...

Cấu hình phát hành so với gỡ lỗi

Trong khi bạn vẫn đang làm việc với dự án của mình, bạn sẽ thường xây dựng ứng dụng của mình bằng cách sử dụng cấu hình gỡ lỗi, vì cấu hình này cho phép bạn xem giá trị của các biến và kiểm soát thực thi trong trình gỡ lỗi. Bạn cũng có thể tạo và kiểm tra các bản dựng trong cấu hình phát hành để đảm bảo rằng bạn chưa đưa ra bất kỳ lỗi nào chỉ xuất hiện trên một loại bản dựng hoặc loại khác. Trong lập trình .NET Framework, các lỗi như vậy rất hiếm, nhưng chúng có thể xảy ra.

Khi bạn sẵn sàng phân phối ứng dụng của mình cho người dùng cuối, hãy tạo một bản phát hành, nó sẽ nhỏ hơn nhiều và thường sẽ có hiệu suất tốt hơn nhiều so với cấu hình gỡ lỗi tương ứng. Bạn có thể đặt cấu hình bản dựng trong ngăn Xây dựng của Trình thiết kế dự án hoặc trong thanh công cụ Xây dựng. Để biết thêm thông tin, xem Cấu hình xây dựng.


1

Ở một mức độ lớn, điều đó phụ thuộc vào việc ứng dụng của bạn có bị ràng buộc tính toán hay không và không phải lúc nào cũng dễ dàng để nói, như trong ví dụ của Lasse. Nếu tôi có câu hỏi nhỏ nhất về những gì nó đang làm, tôi sẽ tạm dừng nó một vài lần và kiểm tra ngăn xếp. Nếu có thêm điều gì đó xảy ra mà tôi không thực sự cần, thì nó sẽ phát hiện ra ngay lập tức.


1

Gần đây tôi gặp phải một vấn đề về hiệu suất. Danh sách đầy đủ các sản phẩm đã mất quá nhiều thời gian, khoảng 80 giây. Tôi đã điều chỉnh DB, cải thiện các truy vấn và không có sự khác biệt nào. Tôi quyết định tạo TestProject và tôi phát hiện ra rằng quy trình tương tự đã được thực hiện trong 4 giây. Sau đó, tôi nhận ra dự án ở chế độ Gỡ lỗi và dự án thử nghiệm ở chế độ Phát hành. Tôi đã chuyển dự án chính sang chế độ Phát hành và danh sách đầy đủ các sản phẩm chỉ mất 4 giây để hiển thị tất cả các kết quả.

Tóm tắt: Chế độ gỡ lỗi chậm hơn nhiều so với chế độ chạy vì nó tiếp tục gỡ lỗi thông tin. Bạn nên luôn luôn triển khai trong chế độ Relase. Bạn vẫn có thể có thông tin gỡ lỗi nếu bạn bao gồm các tệp .PDB. Bằng cách đó, bạn có thể đăng nhập lỗi với số dòng chẳng hạn.


Theo "chế độ chạy", bạn có nghĩa là "Phát hành"?
Ron Klein

Đúng chính xác. Phát hành không có tất cả các chi phí gỡ lỗi.
Francisco Goldenstein

1

Chế độ gỡ lỗi và phát hành có sự khác biệt. Có một công cụ Fuzzlyn : đó là một fuzzer sử dụng Roslyn để tạo các chương trình C # ngẫu nhiên. Nó chạy các chương trình này trên lõi .NET và đảm bảo rằng chúng cho kết quả tương tự khi được biên dịch ở chế độ gỡ lỗi và phát hành.

Với công cụ này, nó đã được tìm thấy và báo cáo rất nhiều lỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.