2012-03-22 52 views
11

Dường như không có trình biên dịch hiệu suất .NET miễn phí nào có thể cấu hình trên cơ sở từng dòng. Do đó, tôi đang xem xét sử dụng Đồng hồ bấm giờ để lập hồ sơ.Lập hồ sơ các ứng dụng .NET với Đồng hồ bấm giờ

* miễn phí như tự do, tức là giấy phép bao gồm các ứng dụng thương mại.

EDIT: Để trả lời những người đã nói với tôi "mua một hồ sơ", tôi muốn, nhưng nếu tôi có thể chi tiêu nhiều tiền, tôi sẽ chi tiêu nó vào cái gì khác. Tôi đã cố gắng thuyết phục ông chủ của tôi rằng một hồ sơ có giá trị nó, nhưng không có nhiều may mắn. Câu hỏi này chủ yếu dựa trên sự tò mò. Tôi sẽ không bao giờ xem xét đồng hồ bấm giờ như một sự thay thế cho một hồ sơ thực sự.

Tôi có một ứng dụng thử nghiệm nhỏ (được viết bằng C#) để đo lường sự khác biệt về hiệu suất khi sử dụng Đồng hồ bấm giờ trên cơ sở mỗi dòng. Các mã kiểm tra là:

int n = 100; 
BigInteger f = 1; 
for (int i = n; i > 1; i--) 
{ 
    f *= i; 
} 

Đây là mã đầy đủ: http://pastebin.com/AvbQmT32

Tôi có một Stopwatch cho mỗi dòng mã. Đây là 'profiler' của tôi. Tôi cũng có một Đồng hồ bấm giờ cho toàn bộ chương trình. Đây là 'profiler profiler' của tôi.

Tôi có chương trình được định cấu hình là Chế độ phát hành, CPU bất kỳ (trên máy x64) và tối ưu hóa đã tắt.

Khi tôi chạy chương trình với các hồ sơ bị vô hiệu hóa, tôi nhận được một cái gì đó như thế này:

   Line    | Ticks 
------------------------------|---------- 
           | 
Total time:     |  359 

Khi tôi chạy nó với các hồ sơ được kích hoạt, tôi nhận được một cái gì đó như thế này:

   Line    | Ticks 
------------------------------|---------- 
           | 
int n = 100;     |   3 
BigInteger f = 1;    |  12 
for (int i = n; i > 1; i--) |  325 
{        | 
    f *= i;     |  539 
}        | 
           | 
Total time:     |  1710 
Stopwatch overhead:   |  831 

Lý tưởng nhất , thời gian dành cho mã phải bằng nhau trong cả hai trường hợp, nhưng dường như Đồng hồ bấm giờ có chi phí xuất hiện trong thời gian đã trôi qua của riêng chúng.

Hiện tại, không cần thiết phải lập hồ sơ mọi dòng của chương trình vì nó thường hoạt động tốt hơn với cách tiếp cận phân chia và chinh phục. Bạn thường có thể bắt đầu bằng cách chia nhỏ các đoạn mã và thu hẹp bất kỳ vấn đề hiệu suất nào.

Ngoài ra, trong hầu hết các ứng dụng, dòng mã trung bình sẽ chậm hơn rất nhiều so với các dòng trong chương trình thử nghiệm. Điều này có nghĩa là sẽ có ít chi phí đồng hồ bấm giờ hơn.

Tuy nhiên, vẫn có phí khi sử dụng Đồng hồ bấm giờ, đặc biệt nếu bạn sử dụng nhiều.

Vì vậy, xuống đến câu hỏi:

Cách hiệu quả nhất để sử dụng Đồng hồ bấm giờ để lược tả là gì? Làm thế nào tôi có thể giảm thiểu chi phí? Thậm chí nó có đáng để quấn Đồng hồ bấm giờ xung quanh một tuyên bố đơn lẻ không?

Tôi đánh giá cao phản hồi của bạn.

+6

Cá nhân, các hồ sơ tôi đã mua (ANTS Profiler) đáng giá từng xu. Tôi sẽ không bao giờ nghĩ đến việc "thủ công" một lần nữa. –

+1

Xin lỗi vì đã hỏi, nhưng tại sao không đăng ký sử dụng một số lớp System.Diagnostics? Tôi tin rằng nó có chứa các lớp học để kiểm tra CPU và sử dụng Ram ví dụ. – Eon

+1

Phiên bản miễn phí của Eqatec profiler cho phép sử dụng trong một dự án thương mại: http://www.eqatec.com/Profiler/LicenseTerms.aspx – ken2k

Trả lời

2

Điều đầu tiên đầu tiên: kết quả của bạn không hề ngạc nhiên. Nếu bạn sử dụng một profiler thương mại, bạn sẽ thấy một cái gì đó tương tự: chương trình của bạn sẽ mất nhiều thời gian hơn để chạy khi nó được profiled hơn khi nó không phải là. Bạn càng đặt tiểu sử chi tiết hơn, bạn càng có thể mong đợi lâu hơn. Khi bạn xem xét các câu lệnh như "i> 1" và "i--" có thể được thực hiện dưới dạng các hướng dẫn bộ xử lý đơn, nó trở nên rõ ràng lý do tại sao việc lập thời gian thực hiện của một dòng cụ thể có thể mất nhiều thời gian hơn thực thi chính dòng đó.

Thực tế là việc lập hồ sơ đang tăng thời gian chạy tổng thể của chương trình của bạn không phải là mối quan tâm; như một số người khác đã đề cập, những gì quan trọng không phải là số lượng tuyệt đối của thời gian chương trình chạy, nhưng so sánh thời gian chạy của các bộ phận cá nhân với nhau để tìm nút cổ chai. Nhưng có một mối quan tâm khác. Đồng hồ bấm giờ sẽ sử dụng bộ hẹn giờ tần số cao từ hệ điều hành cơ bản nếu có sẵn; nhưng ngay cả điều đó có thể không đủ cao. Bộ đếm thời gian tần số cao trên Windows 7 64-bit i5-2400 (lõi tứ 3.10 GHz) của chúng tôi 3.020.556 lần mỗi giây. Đó là rất nhiều âm thanh; nhưng ở tốc độ đó, bộ vi xử lý có thể thực hiện một nghìn lệnh giữa các lần đánh dấu. Điều đó có nghĩa là nếu bạn đang cố gắng đo thời gian cần thiết để thực hiện một lệnh duy nhất, bạn đang đi theo con đường dưới hoặc vượt qua.

Bạn sẽ tốt hơn trong việc định hình ở cấp phương thức. Thậm chí sau đó bạn sẽ gặp phải các vấn đề về tần suất, đặc biệt nếu bạn có các phương pháp nhỏ. Nhưng kết quả sẽ đáng tin cậy hơn ở cấp độ dòng; và một khi bạn đã xác định được phương pháp gây ra tắc nghẽn, bạn có thể kiểm tra nó trực tiếp để xác định cách tối ưu hóa nó để thực hiện tốt hơn.

Tất cả điều này để lại một vài cảnh báo đi kèm với lược tả hiệu suất nói chung, nằm ngoài phạm vi của bài đăng này. Hãy chắc chắn rằng bạn làm nghiên cứu bổ sung về chủ đề này để hiểu làm thế nào bạn nên giải thích bất kỳ kết quả bạn nhận được. Như một ví dụ nhanh, hồ sơ của bạn có thể tiết lộ rằng phần lớn thời gian trong chương trình của bạn đang được chi tiêu theo một phương pháp cụ thể; nhưng điều đó có nghĩa là chính phương thức đó là vấn đề hay các phương pháp khác đang gọi nó thường xuyên? Trả lời loại câu hỏi đó là nơi khó khăn thực sự trong việc nói dối.

1

Bạn đã so sánh tổng thời gian mà không cần trình hồ sơ của bạn với thời gian với trình hồ sơ của bạn trong chế độ gỡ lỗi? Dự đoán đầu tiên của tôi là thời gian thêm sẽ xuất hiện vì các câu lệnh bổ sung cho đồng hồ bấm giờ đang ngăn một số tối ưu hóa đăng ký hoặc lặp lại. Vì vậy, thời gian thêm có thể đến từ một tối ưu hóa mất tích và không mất một số thời gian trong nội bộ để đồng hồ bấm giờ.Tuy nhiên, điều đó đang được nói, mặc dù đồng hồ bấm giờ có độ phân giải cao, tôi nghĩ bạn sẽ nhận thấy một số lỗi thời gian đo những thứ nhỏ như một dòng mã. Ví dụ 'int n = 100' là một dòng trong hội đồng, do đó, về mặt kỹ thuật, tôi sẽ nghĩ rằng nó sẽ chỉ có 1 đánh dấu. Bạn nhận thấy có bao nhiêu biến thể trong các con số của bạn từ khi chạy để chạy? Nếu bạn đang nhận được một biến thể là một tỷ lệ phần trăm đáng kể của giá trị trung bình của bạn, thì valu đó thực sự không mang lại cho bạn nhiều thông tin.

+0

Tối ưu hóa bị vô hiệu hóa, do đó sẽ không có vấn đề gì. Đôi khi tôi thấy sự thay đổi của khoảng 1/3 giá trị trung bình, trong cả hai trường hợp. –

+0

Với việc tối ưu hóa bị vô hiệu hóa, việc chuyển sang chế độ gỡ lỗi có thể không tiết lộ sự cố, nhưng vẫn có thể sự chậm lại là do chi phí bổ sung của cuộc gọi đồng hồ bấm giờ. Các cuộc gọi đồng hồ bấm giờ sử dụng một số biến nội bộ mà có thể buộc mã chính của bạn phải làm những việc như tải lại sổ đăng ký sau khi đồng hồ bấm giờ gọi ví dụ. – Sogger

+0

Ồ, và về sự thay đổi 1/3, nó phụ thuộc vào những gì bạn đang cố gắng xác định số, nhưng một biến thể lớn có nghĩa là con số này sẽ chỉ tốt cho thứ tự so sánh độ lớn (về mặt các câu trả lời khác ở đây đang nói, chỉ tốt cho các so sánh tương đối). Hãy suy nghĩ về một người cao 6ft được đo bằng 1/3 lỗi, "Ồ, bạn ở đâu đó cao từ 4 đến 8ft." Một loại lớn. – Sogger

4

Xét rằng chúng ta thường trực giác chương trình bằng cách Single responsibility principle, không chỉ trong lĩnh vực các loại nhưng chức năng quá, tôi sẽ nói không có bất kỳ sence của profiling ứng dụng từng dòng. Bạn sẽ được quan tâm nhiều hơn trong việc định hình một "trách nhiệm duy nhất" sau đó mỗi dòng đơn.

Có một cách tự nhiên, các trường hợp khi bạn cần cũng có thông báo. Nhưng không sử dụng nó trong tất cả các ứng dụng nhưng trong một phần của một chức năng hoặc một chức năng duy nhất. Trong trường hợp này, StopWatch là lựa chọn tốt nhất. Hãy xem xét rằng StopWatch.NET Class vì vậy thậm chí là chi phí tối thiểu. Bạn không nên xem tuyệt đối, nhưng trên tương đối giá trị.

Hy vọng điều này sẽ hữu ích.

2

Bạn không nên nhìn vào các con số chính xác, bạn nên tìm kiếm sự khác biệt tương đối. Để bạn có thể xác định các khu vực có vấn đề. Bạn đang tìm kiếm những nơi để tối ưu hóa sẽ giải quyết vấn đề hiệu suất của bạn.

Nếu bạn đang phát triển mã ở cấp độ nơi hiệu suất thực sự là một vấn đề và bạn cần phải cấu hình nó để tìm mã vi phạm, sau đó mua một công cụ để thực hiện tác vụ này cho bạn sẽ nhiều hơn trả tiền cho chính nó trong thời gian đã lưu. Profiler đi kèm với Visual Studio Premium là những gì tôi muốn giới thiệu.

0

Có lẽ bạn nên nghĩ về thời gian gọi phương thức lược tả và không phải là các dòng đơn lẻ. Sau khi tất cả, một cuộc gọi phương thức thường là một dòng duy nhất trong mã gọi. Cũng là một cách tiếp cận thú vị là sử dụng một thư viện khai thác gỗ để đăng nhập vào phương pháp và lối thoát hiểm, ví dụ như thế này (sử dụng log4net như logger của sự lựa chọn):

public string MyMethod(string arg) 
{ 
    string result = null; 

    if (logger.IsDebugEnabled) logger.Debug("->MyMethod(" + arg + ")"); 

    // do stuff 
    result = "Hello world!"; 

    if (logger.IsDebugEnabled) logger.Debug("<-MyMethod(" + arg + ") = " + result); 

    return result; 
} 

Điều này sẽ tạo ra một file log đó là thực sự hữu ích cho thấy những gì ứng dụng của bạn đang làm, và nó có tiền thưởng của timestamping mỗi dòng được ghi vào nhật ký, vì vậy bạn có thể xem liệu một phương pháp cụ thể có phải mất một thời gian dài hay không. Với log4net, bạn có thể dễ dàng thay đổi cấu hình để tắt đăng xuất, vì vậy khi bạn không cần nó, bạn không phải trả bất kỳ hình phạt nào về hiệu năng.

2

Bạn đã thử xem CInject: http://codeinject.codeplex.com/documentation chưa? Về cơ bản nó đưa mã vào một DLL. Ra khỏi hộp có vẻ như có giám sát hiệu suất, nhưng nó cũng cho phép bạn tạo mã của riêng bạn để tiêm. Có vẻ hoàn hảo cho những gì bạn đang cố gắng làm.

Các vấn đề liên quan