लकड़हारा slf4j स्ट्रिंग संयोजन के बजाय {} के साथ स्वरूपण के फायदे


100

क्या {}स्ट्रिंग संघनन के बजाय उपयोग करने का कोई फायदा है ?

Slf4j से एक उदाहरण

logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);

के बजाय

logger.debug("Temperature set to"+ t + ". Old temperature was " + oldT);

मुझे लगता है कि यह गति अनुकूलन के बारे में है क्योंकि मापदंडों का मूल्यांकन (और स्ट्रिंग संघनन) एक कॉन्फ़िगर फ़ाइल के आधार पर रनटाइम में बचा जा सकता है। लेकिन केवल दो पैरामीटर संभव हैं, फिर कभी-कभी स्ट्रिंग संघनन के अलावा कोई अन्य विकल्प नहीं होता है। इस मुद्दे पर विचार की आवश्यकता है।

जवाबों:


74

यह है स्ट्रिंग संयोजन प्रदर्शन के बारे में। यदि आपके घने लॉगिंग स्टेटमेंट हैं, तो यह संभावित रूप से महत्वपूर्ण है।

(SLF4J 1.7 से पहले) लेकिन केवल दो पैरामीटर संभव हैं

क्योंकि लॉगिंग स्टेटमेंट के विशाल बहुमत में 2 या उससे कम पैरामीटर हैं, इसलिए SLF4J API संस्करण 1.6 तक (केवल) उपयोग के मामलों को कवर करता है। एपीआई डिजाइनरों ने एपीआई संस्करण 1.7 के बाद से वेरगेज मापदंडों के साथ अतिभारित तरीके प्रदान किए हैं।

उन मामलों के लिए जहां आपको 2 से अधिक की आवश्यकता होती है और आप प्री-1.7 एसएलएफ 4 जे के साथ फंस गए हैं, तो बस या तो स्ट्रिंग संयोजन का उपयोग करें या new Object[] { param1, param2, param3, ... }। उनमें से कुछ पर्याप्त होना चाहिए कि प्रदर्शन उतना महत्वपूर्ण नहीं है।


2
अप्रयुक्त स्ट्रिंग संघनन (यानी डिबगिंग स्टेटमेंट) से बचा जाना चाहिए। (अति क्रियात्मक लेकिन कुशल) लॉग-लेवल चेक या (स्लिमर, लेकिन शायद मामूली ओवरहेड) ऑब्जेक्ट सरणी पैरामीटर का उपयोग करें। (मैं बाद वाली, सभी चीजों को बराबर पसंद करना चाहता हूं।) यह कहना मुश्किल है कि स्ट्रिंग कॉनैट महत्वपूर्ण नहीं होगा / प्रदर्शन को प्रभावित नहीं करेगा। वस्तु सरणी निर्माण सिद्धांत रूप में झुका और दूर अनुकूलित किया जा सकता है और "वास्तव में" कोई फर्क नहीं पड़ता (बनाम इच्छाधारी सोच)। (यह समय से पहले अनुकूलन नहीं है, यह केवल पहली बार कुछ सही / बेहतर करने की बात है।)
माइकल

Overfed संशोधनों को System.out.println () के लिए slf4j के लकड़हारे के समान पालन करने के लिए क्यों नहीं किया जाता है, ताकि वह स्ट्रिंग समाप्ती से बचा जा सके?
a3.14_Infinity

44

लघु संस्करण: हाँ यह कम कोड के साथ तेज़ है!

स्ट्रिंग संघनन यह जानने के बिना बहुत काम करता है कि क्या इसकी आवश्यकता है या नहीं (पारंपरिक "डीबगिंग सक्षम है" लॉग 4 जे से ज्ञात परीक्षण), और यदि संभव हो तो बचा जाना चाहिए, क्योंकि {} स्ट्रींग () कॉल और स्ट्रिंग निर्माण में देरी करने की अनुमति देता है यह तय करने के बाद कि क्या इवेंट को कैप्चरिंग की आवश्यकता है या नहीं। लकड़हारा प्रारूप होने से एक भी कोड मेरी राय में क्लीनर बन जाता है।

आप कोई भी तर्क दे सकते हैं। ध्यान दें कि यदि आप sljf4j के पुराने संस्करण का उपयोग करते हैं और आपके पास दो से अधिक तर्क हैं {}, तो आपको new Object[]{a,b,c,d}एक सरणी पास करने के लिए सिंटैक्स का उपयोग करना होगा । उदाहरण देखें http://slf4j.org/apidocs/org/slf4j/Logger.html#debug(java.lang.String, java.lang.Object [])

गति के बारे में: कैकी ने एक सूची में से कुछ समय पहले एक बेंचमार्क पोस्ट किया था।


6
ध्यान दें: नवीनतम जावाडोक शो नए वर-आर्ग वाक्य रचना, debug(String format, Object... arguments)Slf4j.org/faq.html#logging_performance
माइकल

का उल्लेख करने के कारण upto .totring () मूल्यांकन प्रदर्शन के अलावा मूल्यांकन। यह कुछ ऐसा है जो लकड़हारे और लकड़हारे के अंदर होता है, यह तय कर सकता है कि उस विधि को लागू करना आवश्यक है या नहीं। यह नहीं होता है अगर लॉगिंग स्तर बार पूरा नहीं हुआ है।
चेतन नरसुदे

6

चूंकि, स्ट्रिंग जावा में अपरिवर्तनीय है, इसलिए बाएं और दाएं स्ट्रिंग को संयोजन के प्रत्येक जोड़े के लिए नए स्ट्रिंग में कॉपी करना होगा। तो, बेहतर है कि प्लेसहोल्डर के लिए जाएं।


2
एकल जोड़ी होने पर यह सही है, लेकिन आम तौर पर गलत है, क्योंकि संकलक स्ट्रिंग-बिल्डर कॉल में संघनन करता है, जिसके परिणामस्वरूप बहुत तेज कोड होता है जो उतना आवंटन नहीं करता है।
cdeszaq

3

एक और विकल्प है String.format()। हम इसे jcabi-log (slf4j के आसपास स्थिर उपयोगिता आवरण) में उपयोग कर रहे हैं ।

Logger.debug(this, "some variable = %s", value);

यह बहुत अधिक रखरखाव योग्य और विस्तार योग्य है। इसके अलावा, अनुवाद करना आसान है।


3
मुझे नहीं लगता कि यह अधिक रखरखाव योग्य है। यदि प्रकार valueबदलता है, तो आपको वापस जाना होगा और लॉगिंग स्टेटमेंट को भी बदलना होगा। ऐसा कुछ जो आईडीई आपकी मदद नहीं करेगा। लकड़हारे को डिबगिंग में सहायता करनी चाहिए और उसके रास्ते में नहीं आना चाहिए। :-)
चेतन नरसुदे

3
@ChetanNarsude IntelliJ 2016 कम से कम मुझे बताता है कि जब प्रारूप स्ट्रिंग स्वरूपण तर्क फिट नहीं होता है। उदाहरण के लिए: String.format("%d", "Test")IntelliJ चेतावनी का उत्पादन करता है Argument type 'String' does not match the type of the format specifier '%d'.। हालांकि, मुझे यकीन नहीं है कि यह अभी भी उपरोक्त समाधान के साथ काम करते समय यह बुद्धिमान प्रतिक्रिया प्रदान करने में सक्षम होगा।
क्रश करें

इसकी गति क्या है?
थोरबजोरन रावन एंडरसन

@ ThorbjørnRavnAndersen यह बहुत अंदर से आदिम है, लेकिन निश्चित रूप से यह एक स्थिर
लकड़हारे

रैपिंग slf4j? कि slf4j का उपयोग करने के उद्देश्य को हराने नहीं करता है? इसके अलावा, मैंने कई लोगों को String.format का दुरुपयोग करते देखा है जैसे कि लॉग स्तर का मूल्यांकन करने से पहले स्ट्रिंग को स्वरूपित कर दिया जाता है, जैसे: logger.info (String.format ("hello% s", username)।
जुआन Bustamante

2

मुझे लगता है कि लेखक के दृष्टिकोण से, मुख्य कारण स्ट्रिंग संघनन के लिए ओवरहेड को कम करना है। मैं सिर्फ लकड़हारा के दस्तावेज को पढ़ता हूं, आप निम्नलिखित शब्द पा सकते हैं:

/**
* <p>This form avoids superfluous string concatenation when the logger
* is disabled for the DEBUG level. However, this variant incurs the hidden
* (and relatively small) cost of creating an <code>Object[]</code> before 
  invoking the method,
* even if this logger is disabled for DEBUG. The variants taking
* {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two}
* arguments exist solely in order to avoid this hidden cost.</p>
*/
*
 * @param format    the format string
 * @param arguments a list of 3 or more arguments
 */
public void debug(String format, Object... arguments);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.