2010-02-09 3 views
10

Chúng tôi biết chúng tôi có thể cấu hình log4j để tắt đăng nhập vào các địa điểm cụ thể (lớp hoặc gói trong Java) thông qua tệp thuộc tính/cấu hình của nó. Câu hỏi của tôi được theo sau:log4j thực sự làm gì khi bật hoặc tắt một số địa điểm đăng nhập?

  1. log4j thực sự làm gì cho những lá cờ đó?
  2. là báo cáo nhật ký trong log4j vẫn được gọi nhưng không được ghi vào tệp hoặc bảng điều khiển vì cờ đó? vì vậy vẫn có tác động hiệu suất?
  3. giống như #ifdef trong C++ có hiệu lực vào thời gian biên dịch sau đó có thể giới hạn tác động hiệu suất không?

cảm ơn,

Trả lời

16

Vâng, những điều khoản đăng nhập sẽ vẫn được thực thi. Đây là lý do tại sao nó là một mô hình tốt để kiểm tra mức độ đăng nhập đầu tiên: một cái gì đó giống như

if (log.isInfoEnabled()) { 
    log.info("My big long info string: " + someMessage); 
} 

Điều này là để tránh việc phân bổ lại không gian cho các thông tin String khi mức độ ghi không hỗ trợ INFO báo cáo.

Không phải bất kỳ thứ gì như #ifdef - #ifdef là chỉ thị của trình biên dịch, trong khi cấu hình Log4J được xử lý khi chạy.

Chỉnh sửa: Tôi ghét bị downmodded do thiếu hiểu biết, vì vậy, đây là một bài viết sao lưu câu trả lời của tôi.

Từ http://surguy.net/articles/removing-log-messages.xml:

Trong Log4J, nếu bạn đăng nhập một thông báo ở mức DEBUG, và appender hiện được thiết lập để chỉ đăng thông điệp của INFO cấp trên, sau đó được thông báo sẽ không được hiển thị. Hiệu suất phạt để gọi phương thức nhật ký chính nó là tối thiểu - một vài nano giây. Tuy nhiên, có thể mất nhiều thời gian hơn để đánh giá các đối số cho phương thức đăng nhập . Ví dụ:

logger.debug ("Đối tượng lớn là " + largeObject.toString());

Đánh giá largeObject.toString() có thể được làm chậm, và nó được đánh giá trước cuộc gọi đến logger, vì vậy logger không thể ngăn chặn nó được đánh giá, mặc dù nó sẽ không được sử dụng.

Chỉnh sửa 2: từ sổ tay log4j bản thân (http://logging.apache.org/log4j/1.2/manual.html):

Người dùng cần phải nhận thức các vấn đề hiệu suất sau.

  1. Hiệu suất ghi nhật ký khi tắt nhật ký. Khi đăng nhập bị tắt hoàn toàn hoặc chỉ cho một tập hợp các cấp, chi phí của yêu cầu nhật ký bao gồm lời gọi phương thức cộng với so sánh số nguyên. Trên máy Pentium II 233 MHz, chi phí này thường nằm trong khoảng 5 đến 50 nano giây.

    Tuy nhiên, lời gọi phương thức liên quan đến chi phí "ẩn" của việc xây dựng tham số.

    Ví dụ, đối với một số mèo logger, văn bản,

    logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); 
    

    phải gánh chịu chi phí xây dựng các thông số tin nhắn, tức là chuyển đổi cả số nguyên i, nhập cảnh [i] vào một String, và concatenating dây trung gian, không phân biệt cho dù tin nhắn có được đăng nhập hay không. Chi phí xây dựng tham số này có thể khá cao và phụ thuộc vào kích thước của các tham số liên quan.

    Để tránh những thông số chi phí xây dựng ghi:

    if(logger.isDebugEnabled() { 
        logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); 
    } 
    

    này sẽ không phải chịu chi phí xây dựng tham số nếu gỡ lỗi bị vô hiệu hóa. Mặt khác, nếu trình ghi nhật ký được kích hoạt gỡ lỗi, nó sẽ phải chịu gấp đôi chi phí đánh giá liệu trình ghi nhật ký có được bật hay không: một lần trong debugEnabled và một lần trong gỡ lỗi. Đây là một chi phí không đáng kể bởi vì việc đánh giá một logger mất khoảng 1% thời gian cần để thực sự đăng nhập.

+2

Thực ra, không nên bao gồm tất cả các câu lệnh đăng nhập của bạn vào các câu lệnh if. Việc ghi nhật ký phải càng ít càng tốt, đó là lý do tại sao bạn có khung đăng nhập. Ngoài ra, nếu các báo cáo đăng nhập (vô tình) có một tác dụng phụ, bạn sẽ làm cho gỡ lỗi khác nhau từ phát hành. Chỉ khi bạn làm điều này một triệu lần bạn nên thêm nếu. Ngoài ra nó có thể là VM đã tối ưu hóa mã này mà không bao giờ được sử dụng. (Btw, nhận xét rằng nó được đánh giá là tất nhiên chính xác) – Thirler

+1

Xin lỗi, bạn là người không hiểu rõ. VM không thể tối ưu hóa điều này, vì câu lệnh IS EXECUTED mỗi lần. Bạn không cần "một triệu" báo cáo đăng nhập cho một hình phạt hiệu suất, bạn chỉ cần một tuyên bố đăng nhập đó là trong một vòng lặp. Và "khai thác gỗ nên càng ít công việc càng tốt" là một tuyên bố vô nghĩa trong bối cảnh này - đặc biệt là khi OP đặc biệt hỏi về hiệu suất. – danben

+0

Tôi đồng ý với danben, trong một số trường hợp nhất định. Nếu bạn muốn đăng nhập 10 dòng trong một hàng với các chuỗi lớn (hoặc các lệnh toString() phức tạp trong chúng, hãy gói nó trong một ý tưởng hay. Tôi không nghĩ rằng downvote là xứng đáng. – karoberts

1
  1. log4j sẽ xử lý các báo cáo nhật ký, và kiểm tra xem nếu logger cụ thể được kích hoạt ở mức độ khai thác gỗ nói riêng. Nếu không, thì câu lệnh sẽ không được ghi lại.

  2. Các séc này rẻ hơn đáng kể so với ghi thực tế vào đĩa (hoặc bảng điều khiển), nhưng chúng vẫn có tác động.

  3. không, java không có khái niệm như #ifdef (out of the box dù sao, có precompilers java trên mạng)

5

Tôi chạy một chuẩn mực đơn giản để kiểm tra.

for (int j = 0; j < 5; j++) { 
     long t1 = System.nanoTime()/1000000; 
     int iterations = 1000000; 
     for (int i = 0; i < iterations; i++) { 
      int test = i % 10; 
      log.debug("Test " + i + " has value " + test); 
     } 
     long t2 = System.nanoTime()/1000000; 
     log.info("elapsed time: " + (t2 - t1)); 

     long t3 = System.nanoTime()/1000000; 
     for (int i = 0; i < iterations; i++) { 
      int test = i % 10; 
      if (log.isDebugEnabled()) { 
       log.debug("Test " + i + " has value " + test); 
      } 
     } 
     long t4 = System.nanoTime()/1000000; 
     log.info("elapsed time 2: " + (t4 - t3)); 
    } 

elapsed time: 539 
elapsed time 2: 17 
elapsed time: 450 
elapsed time 2: 18 
elapsed time: 454 
elapsed time 2: 19 
elapsed time: 454 
elapsed time 2: 17 
elapsed time: 450 
elapsed time 2: 19 

Với 1.6.0_18, điều này làm tôi ngạc nhiên như tôi đã nghĩ nội tuyến sẽ ngăn chặn điều này. Có lẽ Java 7 với phân tích thoát sẽ.

Tuy nhiên, tôi vẫn sẽ không bao bọc các câu lệnh gỡ lỗi trong mệnh đề if trừ khi thời gian cải thiện thứ tự của một nửa micro giây trở nên quan trọng!