2011-02-03 32 views
8

Tôi đã viết một lớp log và một chức năng như trong đoạn mã sau:MethodBase.GetCurrentMethod() Hiệu suất?

Log(System.Reflection.MethodBase methodBase, string message) 

Mỗi lần tôi đăng một cái gì đó tôi cũng đăng nhập tên lớp từ methodBase.Name và methodBase.DeclaringType.Name.

Tôi đã đọc bài đăng sau Using Get CurrentMethod và tôi nhận thấy rằng phương pháp này chậm.

Tôi có nên sử dụng this.GetType() thay vì System.Reflection.MethodBase hoặc tôi nên đăng nhập thủ công tên lớp/phương thức trong nhật ký của mình, ví dụ: Log ("ClassName.methodName", "đăng tin nhắn)? Các thực hành tốt nhất là gì?

+0

@loannis, câu hỏi tương tự được hỏi tại đây. Kiểm tra liên kết http://stackoverflow.com/questions/1466740/using-getcurrentmethod-in-supposedly-high-performance-code – RameshVel

+0

Từ daniels trả lời "this.GetType() yêu cầu 2,5 ns cho mỗi cuộc gọi trong khi MethodBase.GetCurrentMethod() .DeclaringType yêu cầu 2490 ns cho mỗi cuộc gọi - vì vậy bạn có tốc độ tăng khoảng 1200. " – RameshVel

+0

@Ramesh: Bạn có nhận thấy đó chính xác là (các) câu hỏi mà anh ta đã liên kết trong câu hỏi không? –

Trả lời

9

Nó thực sự phụ thuộc.

Nếu bạn sử dụng cách tiếp cận this.GetType() bạn sẽ mất những thông tin phương pháp, nhưng bạn sẽ có một lớn Bạn có thể đạt được hiệu suất tốt hơn, nhưng điều này làm cho API của bạn kém thân thiện hơn (ví dụ: Log("ClassName.MethodName", "log message")). nhà phát triển cuộc gọi phải cung cấp tên lớp và tên phương thức)

2

Tôi biết đây là một câu hỏi cũ, nhưng tôi figured tôi muốn ném ra một giải pháp đơn giản mà dường như hoạt động tốt và duy trì hiệu

static void Main(string[] args) 
    { 
     int loopCount = 1000000; // 1,000,000 (one million) iterations 
     var timer = new Timer(); 

     timer.Restart(); 
     for (int i = 0; i < loopCount; i++) 
      Log(MethodBase.GetCurrentMethod(), "whee"); 
     TimeSpan reflectionRunTime = timer.CalculateTime(); 

     timer.Restart(); 
     for (int i = 0; i < loopCount; i++) 
      Log((Action<string[]>)Main, "whee"); 
     TimeSpan lookupRunTime = timer.CalculateTime(); 

     Console.WriteLine("Reflection Time: {0}ms", reflectionRunTime.TotalMilliseconds); 
     Console.WriteLine(" Lookup Time: {0}ms", lookupRunTime.TotalMilliseconds); 
     Console.WriteLine(); 
     Console.WriteLine("Press Enter to exit"); 
     Console.ReadLine(); 

    } 

    public static void Log(Delegate info, string message) 
    { 
     // do stuff 
    } 

    public static void Log(MethodBase info, string message) 
    { 
     // do stuff 
    } 

    public class Timer 
    { 
     private DateTime _startTime; 

     public void Restart() 
     { 
      _startTime = DateTime.Now; 
     } 

     public TimeSpan CalculateTime() 
     { 
      return DateTime.Now.Subtract(_startTime); 
     } 
    } 

Chạy mã này mang lại cho tôi kết quả như sau:

Reflection Time: 1692.1692ms 
    Lookup Time: 19.0019ms 

Press Enter to exit 

Đối với một triệu lần lặp lại, điều đó không tệ ở tất cả, đặc biệt là so với phản xạ thẳng lên. Nhóm phương thức đang được truyền đến một loại đại biểu, bạn duy trì một liên kết tượng trưng tất cả các cách vào khai thác gỗ. Không có dây ma thuật ngốc nghếch.

+1

Nếu bạn đang tính toán chính xác mã bạn đăng, không có gì thực sự xảy ra trong chính phương thức Đăng nhập, bạn sẽ không mong đợi tuyến đại biểu sử dụng ít thời gian hơn, bởi vì nó Bạn có thực sự có thể lấy tên của phương thức mà bạn đang chuyển sang phương thức 'Log (Delegate info ...'? – Zack

+1

Như @Zack mong đợi, truy cập vào thuộc tính Name trong Log-method hay không Tôi đã sửa đổi chúng để trả về 'MethodBase.Name' và' Delegate.Method.Name', tương ứng. Kết quả của tôi sau đó trở thành 'Thời gian phản chiếu: 1178,6813ms Thời gian tra cứu: 482,2953ms'. Tuy nhiên," Tra cứu "- cách tiếp cận dẫn đến thực thi nhanh hơn. –