2009-03-17 26 views
18

Nhóm chúng tôi có chủ trương thực hiện khai thác gỗ nhưKêu gọi các cuộc gọi để gỡ lỗi() trong if isDebugEnabled(): một chính sách tốt?

if (LOGGER.isDebugEnabled()) { 
    LOGGER.debug("model[" + model + "]"); 
} 

thay vì chỉ đơn giản là gọi phương thức khai thác gỗ như thế này:

LOGGER.debug("model[" + model + "]"); 

thực hành này có khả năng dẫn đến một số performance improvement, nhưng mặt khác nó làm cho codebase phức tạp hơn. Ứng dụng của chúng tôi không có vấn đề về hiệu năng, có lẽ sẽ không bao giờ, đối số cho việc giới thiệu chính sách chỉ đơn giản là thực hành tốt, vì vậy nó sẽ được sử dụng mỗi khi chúng tôi đang ghi nhật ký.

Bạn có nghĩ đó là chính sách tốt không?

Trả lời

7

Tôi đồng ý với câu nói nổi tiếng của Michael A. Jackson:

Nguyên tắc đầu tiên của Tối ưu hóa chương trình: Đừng làm điều đó.

Quy tắc tối ưu hóa chương trình thứ hai - Chỉ dành cho các chuyên gia: Chưa thực hiện.

Tôi nghĩ rằng trong phần lớn các trường hợp, nó không đáng để làm cho codebase phức tạp hơn mà không chắc chắn rằng hiệu suất đạt được sẽ đáng chú ý/đáng kể.

Tôi biết về cải thiện hiệu suất, nhưng tôi nghĩ rằng đó là trách nhiệm của lập trình viên cá nhân để quyết định xem có nên thêm các dòng mã bổ sung đó vào một trường hợp cụ thể hay không. Trong hầu hết các trường hợp, các đường bổ sung chỉ thêm độ phức tạp mà không có bất kỳ mức tăng đáng chú ý nào về phía hiệu suất.

+1

Rõ ràng là nếu tác giả đã đặt câu hỏi này thì đó là lời kêu gọi anh ta thực hiện tối ưu hóa. I E. khi bạn được yêu cầu tối ưu hóa một đoạn mã, bạn không trả lời bằng hai dấu ngoặc kép ở trên. Hiểu bạn đến từ đâu nhưng nó không giúp đỡ trong tình huống này. –

+0

-1 từ tôi. tôi ghét câu thần chú "không làm tối ưu hóa" này. Nó là thiếu sót nghiêm trọng - nếu tối ưu hóa của bạn * sẽ cho kết quả (thậm chí tầm thường) và nó gần như là * free * (vì đây là, 'if' statement là tầm thường) và nó không phức tạp (và gói một câu lệnh log trong một nếu chỉ là tầm thường nhất) sau đó chỉ cần đi trước và làm điều đó. – bharal

+1

Không đồng ý, điều này nằm trong tĩnh mạch của một hoạt động kiểm tra để tránh rắc rối, có thể dễ dàng được truyền đạt tới một nhà phát triển cơ sở, để họ sẽ không tự động giới thiệu một số lỗi. – ammianus

16

Đó là chính sách tốt cho những trường hợp chuỗi đăng nhập bạn đang xây dựng thực sự ảnh hưởng đến hiệu suất đáng kể. Đây có thể là vì hai lý do:

  • Rất nhiều công việc cần phải đi vào xây dựng chuỗi (ví dụ như nó có để làm tra cứu, hoặc xây dựng một chuỗi rất lớn từ rất nhiều mảnh rất nhỏ)
  • Đó là trong một vòng lặp mà không làm nhiều công việc khác (nhưng được gọi là rất thường xuyên), do đó tỷ lệ thời gian dành xây dựng thậm chí là một chuỗi log đơn giản là cao hơn

Nó không phải là một quy tắc chăn và tôi mong đợi cả hai tình huống này là tương đối hiếm. Tất nhiên, những gì chúng tôi thực sự muốn là có thể nói, "Gọi phương thức gỡ lỗi, đi qua một đối số không phải là chuỗi gỡ lỗi, nhưng là cái gì đó biết cách xây dựng chuỗi gỡ lỗi , nếu và chỉ khi cần thiết. " Điều này sẽ là xấu trong Java mà không có đóng cửa ngắn gọn. (Ngay cả trong một ngôn ngữ có đóng cửa dưới dạng các biểu thức lambda, việc nắm bắt các biến có liên quan có thể có ý nghĩa trong một số trường hợp, tùy thuộc vào cách ngôn ngữ xử lý việc chụp.)

+2

SLF không có các tùy chọn định dạng chuỗi trong các phương thức đăng nhập của nó? –

+0

Tôi luôn luôn chủ trương sử dụng quy tắc này luôn, bởi vì nhà phát triển không cần phải suy nghĩ về chi phí xây dựng chuỗi (tham số). Đôi khi, cần phải xây dựng các tham số bổ sung để gỡ lỗi ghi nhật ký, như 'getEntryDebugString()'. Tốt hơn là có thêm một vài dòng và mã dễ bị lỗi hơn là xin lỗi bởi những vấn đề hiếm gặp. – xmedeko

0

Nếu "model" đã được biết, chỉ cần đăng nhập không phải là quá đắt. Nhưng, nếu "mô hình" nên được tìm nạp chỉ để ghi nhật ký như dưới đây, sự đơn giản có thể bị xâm phạm.

LOGGER.debug("model[" + proxy.getModel() + "]"); 
1

Tôi nghĩ rằng việc này sẽ giúp bạn thực hiện cuộc gọi isDebugEnabled() trước khi bạn viết thông điệp tường trình của mình. Hơn bạn có thể dễ dàng cập nhật thông điệp tường trình của mình sau. Chúng tôi sử dụng mã sau để làm cho các thông điệp tường trình linh hoạt hơn.

if (LOGGER.isDebugEnabled()) { 
    String msg = "A Message {0} you can put {1} differet Objects in {2}"; //$NON-NLS-1$ 
    Object[] args = new Object[] {file1.toString(),new Integer(23),anObject}; 
    LOGGER.debug(MessageFormat.format(msg,args)); 
} 

Khi bạn không có câu lệnh if bạn sẽ mất thời gian. Hãy nhớ ... dự án của bạn trở nên lớn hơn và thông điệp tường trình của bạn quá.

Thông báo tường trình không được làm chậm mã của bạn!

+2

Có một giải pháp thay thế rất tiện lợi dựa trên các định dạng tin nhắn: các thông báo được tham số hóa. http://www.slf4j.org/faq.html#logging_performance – pisaruk

21

Bạn nên sử dụng SLF4J và thực hiện log4j việc triển khai của mình. Với SLF4J, bạn có thể loại bỏ hoàn toàn isDebugEnabled() bằng cách sử dụng thông báo được tham số hóa.

Xem section about logging performance in the slf4j FAQ

Hai dòng sau đây sẽ mang lại cùng một đầu ra chính xác. Tuy nhiên, biểu mẫu thứ hai sẽ hoạt động tốt hơn biểu mẫu đầu tiên với hệ số tối thiểu là 30, trong trường hợp có khai báo ghi nhật ký bị vô hiệu hóa.

logger.debug("The new entry is " + entry + ".");

logger.debug("The new entry is {}.", entry);

+1

Định dạng chuỗi không giúp ích khi tham số xây dựng 'mục' là tốn kém. Ví dụ. hãy xem xét một số 'logger.debug (" Mục mới là {}. ", getEntry());' và bạn không biết cách 'getEntry()' tốn kém như thế nào. – xmedeko

2

tôi không thể tìm thấy tài liệu tham khảo trực tuyến (có lẽ tôi đọc nó trong một cuốn sách), nhưng đã có một ví dụ về một số cuộc gọi BIOS đó đã viết một String để màn hình.

Mã đã viết chuỗi vào màn hình được chọn để đảm bảo rằng Chuỗi sẽ không tắt màn hình và sau đó được gọi là một hàm để ghi ra một char vào màn hình.

Chức năng ghi ký tự char vào màn hình được chọn để đảm bảo rằng ký tự đó sẽ không bị xóa khỏi màn hình.

Xóa mã kiểm tra khỏi chức năng đã viết ký tự vào màn hình dẫn đến tăng tốc độ lớn. Đó là vì in mỗi nhân vật đã xảy ra rất thường xuyên. Họ cũng cung cấp một phương pháp đã kiểm tra các trường hợp khi vị trí màn hình không được kiểm tra trước cuộc gọi.

Vì vậy, nếu bạn có thể kiểm tra ở mức cao và tránh kiểm tra ở mức thấp, bạn có thể tăng tốc độ đáng kể.

Trong trường hợp bạn cung cấp, nếu mã là trong một vòng lặp hoặc nếu có rất nhiều báo cáo khai thác gỗ sau đó sẽ có một lợi ích rõ ràng kể từ khi bạn sẽ:

  • loại bỏ việc tạo ra chuỗi (và GC liên quan)
  • giảm số lượng câu lệnh if (mặc dù hotspote rất có khả năng tối ưu hóa chúng).

Tôi sẽ nói rằng, nói chung, bạn không nên thêm bất kỳ thứ gì được biết là tốn kém nếu có công việc dễ dàng. Điều này rõ ràng rơi vào trường hợp đó - việc bổ sung câu lệnh if không phải là khó làm, nó là một nỗi đau để đưa vào sau này, và nó cung cấp một cải thiện tốc độ/bộ nhớ xác định.

Tôi nghĩ rằng sự khác biệt giữa tối ưu hóa này và sớm là điều này được biết là luôn luôn tốn kém, do đó, vấn đề đi xuống đến nó là một chi phí tích lũy bạn muốn thêm vào chương trình hay không? Chi phí là khá nhiều không đổi và nó được biết đến tại thời điểm viết mã.

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