2010-04-12 17 views
5

Tôi đang tìm kiếm đăng nhập C# và tôi không muốn thông điệp tường trình của mình dành bất kỳ thời gian xử lý nào nếu thông báo nằm dưới ngưỡng ghi nhật ký. Điều tốt nhất tôi có thể thấy log4net là kiểm tra ngưỡng SAU KHI đánh giá các tham số nhật ký.Thủ thuật hiệu suất cho C# Đăng nhập

Ví dụ:

_logger.Debug("My complicated log message " + thisFunctionTakesALongTime() + " will take a long time") 

Thậm chí nếu ngưỡng là trên Debug, thisFunctionTakesALongTime sẽ vẫn được đánh giá.

Trong log4net bạn có nghĩa vụ phải sử dụng _logger.isDebugEnabled do đó bạn kết thúc với

if(_logger.isDebugEnabled) 
    _logger.Debug("Much faster") 

Tôi muốn biết nếu có một giải pháp tốt hơn cho .net khai thác gỗ mà không liên quan đến một tấm séc mỗi khi tôi muốn để đăng nhập.

Trong C++ tôi được phép làm

LOG_DEBUG("My complicated log message " + thisFunctionTakesALongTime() + " will take no time") 

từ vĩ mô LOG_DEBUG của tôi không mức độ log kiểm tra riêng của mình. Điều này giải phóng cho tôi để có một tin nhắn đăng nhập 1 dòng trong suốt ứng dụng của tôi mà tôi rất thích. Bất cứ ai biết một cách để nhân rộng hành vi này trong C#?

Trả lời

8

Nếu bạn có thể nhắm mục tiêu .NET 3.5 (C# 3.0), bạn có thể sử dụng extension methods để bọc các câu hỏi if.

vì vậy bạn có thể làm các "vĩ mô" tương đương:

logger.Log_Debug("Much faster"); 

logger.Log_Debug(() => { "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" }); 

bằng cách gói kiểm tra trong phương pháp này:

public class Log4NetExtensionMethods { 
    // simple string wrapper 
    public void Log_Debug(this log4net.ILog logger, string logMessage) { 
     if(logger.isDebugEnabled) { 
      logger.Debug(logMessage); 
     } 
    } 

    // this takes a delegate so you can delay execution 
    // of a function call until you've determined it's necessary 
    public void Log_Debug(this log4net.ILog logger, Func<string> logMessageDelegate) { 
     if(logger.isDebugEnabled) { 
      logger.Debug(logMessageDelegate()); 
     } 
    } 
} 
+0

Nhưng nếu tôi đánh giá các chức năng để nhận thông báo tường trình, điều này có thể làm chậm không? Tôi muốn tránh tất cả các đánh giá chức năng nếu mức nhật ký thấp hơn ngưỡng của tôi. – Charles

+1

Bạn đúng là bạn sẽ cần phải trì hoãn việc đánh giá chức năng.Xem bản cập nhật của tôi sử dụng một đại biểu ẩn danh. –

+1

D'oh, đó cũng là câu trả lời của tôi. Tôi nên cảnh báo bạn rằng nếu bạn đang tìm kiếm tốc độ, bạn không muốn sử dụng các đại biểu. Bạn chỉ nên lấy hit và sử dụng nếu 'if (logger.isDebugEnabled)' xung quanh bất cứ thứ gì đắt tiền. Không có giải pháp nào vừa hiệu quả vừa tao nhã. – bobbymcr

-2

Nếu không có một Preprocessor bạn SOL. Tất nhiên không có gì ngăn cản bạn sử dụng nó trước khi đưa mã của bạn vào trình biên dịch C#.

+0

đại biểu ẩn danh và các lớp học bổ sung - wow rất nhiều việc đánh máy. – blammo

1

Vấn đề ở đây là tất cả các tham số phương pháp phải được đánh giá trước khi phương thức được gọi. Không có cách nào xung quanh điều này, với cú pháp bạn đang sử dụng. Vì C# không có tiền xử lý thực hoặc macro, bạn không thể làm bất cứ điều gì như "LOG_DEBUG". Điều tốt nhất bạn có thể làm là sử dụng if (logger.isDebugEnable) như được đề xuất.

Điều duy nhất tôi có thể nghĩ là có thể sử dụng một cái gì đó giống như biểu thức lambda để trì hoãn việc đánh giá. Nhưng tôi sẽ cảnh báo bạn rằng điều này gần như chắc chắn sẽ có nhiều hit hiệu suất hơn vào cuối.

internal class Sample 
{ 
    private static void Main(string[] args) 
    { 
     DelayedEvaluationLogger.Debug(logger,() => "This is " + Expensive() + " to log."); 
    } 

    private static string Expensive() 
    { 
     // ... 
    } 
} 

internal static class DelayedEvaluationLogger 
{ 
    public static void Debug(ILog logger, Func<string> logString) 
    { 
     if (logger.isDebugEnabled) 
     { 
      logger.Debug(logString()); 
     } 
    } 
} 
+0

Biểu thức lambda có đắt không? – Charles

+2

@Charles: lambdas là tương đối rẻ tiền như xa như ràng buộc muộn đi, nhưng đến nay đắt hơn một kiểm tra boolean và một cuộc gọi phương thức. Trong thử nghiệm đơn giản của tôi trên một tỷ lần lặp (mã ở đây: http://pastebin.com/aRtMtsxz), tôi đo khoảng 25% chi phí cho lambda so với kiểm tra boolean khi đăng nhập không được kích hoạt. Với một lambda lưu trữ (lưu lambda vào một trường để nó không được tái tạo mỗi lần), có một chút chi phí thấp hơn (một lứa dưới 20%). – bobbymcr

2

17.4.2 Các thuộc tính Conditional

Thuộc tính có điều kiện cho phép định nghĩa các phương pháp có điều kiện. Thuộc tính Conditional cho biết một điều kiện bằng cách kiểm tra một biểu tượng biên dịch có điều kiện. Các cuộc gọi đến một phương thức có điều kiện được bao gồm hoặc bỏ qua tùy thuộc vào việc biểu tượng này được xác định tại điểm của cuộc gọi hay không. Nếu biểu tượng được xác định, cuộc gọi được bao gồm; nếu không, cuộc gọi (bao gồm cả việc đánh giá các tham số của cuộc gọi) sẽ bị bỏ qua.

[ Conditional("DEBUG") ] 
public static void LogLine(string msg,string detail) 
{ 
    Console.WriteLine("Log: {0} = {1}",msg,detail); 
} 

public static void Main(string[] args) 
{ 
    int Total = 0; 
    for(int Lp = 1; Lp < 10; Lp++) 
    { 
     LogLine("Total",Total.ToString()); 
     Total = Total + Lp; 
    } 
} 
+0

Điều này thật thú vị, tôi sẽ nghiên cứu thêm về nó. MSDN: http://msdn.microsoft.com/en-us/library/aa664622%28VS.71%29.aspx – Charles

+1

Tôi cho rằng các thư viện ghi nhật ký tốt hơn đã sử dụng kỹ thuật này. – blammo

+1

chỉ vì bạn đang gọi phương thức "logger.debug" không có nghĩa là bạn đang thực sự chạy trong chế độ gỡ lỗi. Tên "debug" thực sự chỉ là tên phương thức cho một ngưỡng tùy ý như được định nghĩa bởi nhà phát triển ứng dụng. Tôi sẽ ngạc nhiên nếu Log4Net, EnterpriseLibrary, vv ... thực sự sử dụng bất kỳ thuộc tính có điều kiện nào vì thuộc tính dựa trên sự hiện diện của một biểu tượng biên dịch. –

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