2011-09-13 12 views
73

सवाल थोड़ा सैद्धांतिक है, JAXB संदर्भ, marshaller और unmarshaller बनाने की लागत क्या है?JAXB संदर्भ बनाने और marshallers लागत

मुझे पता चला है कि मेरा कोड एक ही जेएक्सबी संदर्भ और संभावित रूप से एक ही मार्शलर को सभी मार्शलिंग पर संदर्भ और मार्शलर बनाने के बजाय सभी मार्शलिंग ऑपरेशंस के लिए लाभ प्राप्त कर सकता है।

तो JAXB संदर्भ और marshaller/unmarshaller बनाने की लागत क्या है? क्या प्रत्येक मार्शलिंग ऑपरेशन के लिए संदर्भ + मार्शलर बनाना ठीक है या इससे बचने के लिए बेहतर है?

उत्तर

154

नोट: मैं EclipseLink JAXB (MOXy) नेतृत्व और JAXB 2 (JSR-222) विशेषज्ञ समूह का सदस्य हूँ।

JAXBContext सुरक्षित थ्रेड है और केवल एक बार बनाया और मेटाडाटा को कई बार आरंभ की लागत से बचने के लिए पुन: उपयोग किया जाना चाहिए। Marshaller और Unmarshaller धागे सुरक्षित नहीं हैं, लेकिन प्रति ऑपरेशन बनाने के लिए हल्के वजन बनाए जा सकते हैं।

+5

महान उत्तर। मैं अब JAXB पर लीड के रूप में अपने अनुभव के आधार पर आत्मविश्वास रख सकता हूं। – Vladimir

+6

मैं आपको भरोसा करता हूं, लेकिन क्या यह कहीं दस्तावेज़ीकरण में पाया जा सकता है? – Hurda

+2

यह आरआई के लिए प्रलेखित है: https://jaxb.java.net/guide/Performance_and_thread_safety.html (लेकिन मोक्सी AFAIK नहीं) – Caoilte

9

यह एक दयालुता है कि यह विशेष रूप से जावाडोक में वर्णित नहीं है। मैं जो कह सकता हूं वह यह है कि स्प्रिंग एक वैश्विक जेएक्सबीएनएन्टेक्स्ट का उपयोग करता है, जो धागे के बीच साझा किया जाता है, जबकि यह प्रत्येक मार्शेलिंग ऑपरेशन के लिए एक नया मार्शलर बनाता है, जिसमें javadoc comment कोड में कहा गया है कि जेएक्सबी मार्शलर्स जरूरी नहीं हैं।

ही इस पेज पर कहा गया है: http://jaxb.java.net/guide/Performance_and_thread_safety.html

मैं, लगता है कि एक JAXBContext बनाने एक महंगा ऑपरेशन है, क्योंकि यह एनोटेशन के लिए स्कैनिंग वर्गों और संकुल शामिल है। लेकिन यह मापने का सबसे अच्छा तरीका है।

+0

हाय @ जेबी, महान जवाब विशेष रूप से मापने पर आपकी टिप्पणियां और क्यों JAXBContext महंगा है। – Vladimir

+1

जैवडोक हमेशा _lifecycle_ के महत्वपूर्ण तथ्यों पर कमजोर रहा है। यह निश्चित रूप से हमें संपत्ति गेटर्स और सेटर्स की छोटी पुनरावृत्ति देता है, लेकिन यह जानने के लिए कि कैसे/कहां प्राप्त करें या कहां प्राप्त करें, उत्परिवर्तन और थ्रेड-सुरक्षा .. ऐसा लगता है कि यह उन सबसे महत्वपूर्ण कारकों को पूरी तरह से याद करता है। Sigh :) –

29

आदर्श रूप से, आपके पास सिंगलटन JAXBContext और Marshaller और Unmarshaller के स्थानीय उदाहरण होना चाहिए। जबकि Marshaller और Unmarshaller उदाहरण हैं

JAXBContext उदाहरणों धागा सुरक्षित हैं नहीं धागे की सुरक्षित और धागे भर में कभी नहीं साझा किया जाना चाहिए।

+0

उत्तर के लिए धन्यवाद। दुर्भाग्यवश मुझे केवल एक उत्तर चुनना है :-) – Vladimir

0

मैं आमतौर पर एक ThreadLocal वर्ग पैटर्न के साथ इस तरह की समस्याओं को हल। इस तथ्य को देखते हुए कि आपको प्रत्येक कक्षा के लिए एक अलग मार्शलर की आवश्यकता है, आप इसे singleton -map पैटर्न के साथ जोड़ सकते हैं।

आपको 15 मिनट का काम बचाने के लिए। जैक्सब मार्शलर्स और अनमारशैलर्स के लिए थ्रेड-सुरक्षित फैक्ट्री के कार्यान्वयन के बाद यहां दिया गया है।

यह आपको निम्नानुसार उदाहरणों तक पहुंचने की अनुमति देता है ...

Marshaller m = Jaxb.get(SomeClass.class).getMarshaller(); 
Unmarshaller um = Jaxb.get(SomeClass.class).getUnmarshaller(); 

और कोड आप की आवश्यकता होगी एक छोटे से JAXB वर्ग कि इस प्रकार दिखाई देता है:

public class Jaxb 
{ 
    // singleton pattern: one instance per class. 
    private static Map<Class,Jaxb> singletonMap = new HashMap<>(); 
    private Class clazz; 

    // thread-local pattern: one marshaller/unmarshaller instance per thread 
    private ThreadLocal<Marshaller> marshallerThreadLocal = new ThreadLocal<>(); 
    private ThreadLocal<Unmarshaller> unmarshallerThreadLocal = new ThreadLocal<>(); 

    // The static singleton getter needs to be thread-safe too, 
    // so this method is marked as synchronized. 
    public static synchronized Jaxb get(Class clazz) 
    { 
    Jaxb jaxb = singletonMap.get(clazz); 
    if (jaxb == null) 
    { 
     jaxb = new Jaxb(clazz); 
     singletonMap.put(clazz, jaxb); 
    } 
    return jaxb; 
    } 

    // the constructor needs to be private, 
    // because all instances need to be created with the get method. 
    private Jaxb(Class clazz) 
    { 
    this.clazz = clazz; 
    } 

    /** 
    * Gets/Creates a marshaller (thread-safe) 
    * @throws JAXBException 
    */ 
    public Marshaller getMarshaller() throws JAXBException 
    { 
    Marshaller m = marshallerThreadLocal.get(); 
    if (m == null) 
    { 
     JAXBContext jc = JAXBContext.newInstance(clazz); 
     m = jc.createMarshaller(); 
     marshallerThreadLocal.set(m); 
    } 
    return m; 
    } 

    /** 
    * Gets/Creates an unmarshaller (thread-safe) 
    * @throws JAXBException 
    */ 
    public Unmarshaller getUnmarshaller() throws JAXBException 
    { 
    Unmarshaller um = unmarshallerThreadLocal.get(); 
    if (um == null) 
    { 
     JAXBContext jc = JAXBContext.newInstance(clazz); 
     um = jc.createUnmarshaller(); 
     unmarshallerThreadLocal.set(um); 
    } 
    return um; 
    } 
} 
+8

थ्रेडलोकल लाभ के बिना अन्य उपनिवेश समस्याओं का परिचय देगा। बस एक एकल JAXBContext (यह महंगा हिस्सा है) रखें और जब भी आवश्यक हो तो एक नया Unmarshaller बनाएं। – ymajoros

4

मैं साझा धागा सुरक्षित JAXBContext का उपयोग कर और स्थानीय संयुक्त राष्ट्र/marschallers थ्रेड इस समस्या का समाधान (इसलिए सैद्धांतिक रूप से, un/marshaller उदाहरण होंगे क्योंकि थ्रेड जो उन्हें एक्सेस करते हैं) वाई वें सिंक्रनाइज़ेशन केवल un/marshaller की शुरुआत पर।

private final ThreadLocal<Unmarshaller> unmarshallerThreadLocal = new ThreadLocal<Unmarshaller>() { 
    protected synchronized Unmarshaller initialValue() { 
     try { 
      return jaxbContext.createUnmarshaller(); 
     } catch (JAXBException e) { 
      throw new IllegalStateException("Unable to create unmarshaller"); 
     } 
    } 
}; 
private final ThreadLocal<Marshaller> marshallerThreadLocal = new ThreadLocal<Marshaller>() { 
    protected synchronized Marshaller initialValue() { 
     try { 
      return jaxbContext.createMarshaller(); 
     } catch (JAXBException e) { 
      throw new IllegalStateException("Unable to create marshaller"); 
     } 
    } 
}; 

private final JAXBContext jaxbContext; 

private MyClassConstructor(){ 
    try { 
     jaxbContext = JAXBContext.newInstance(Entity.class); 
    } catch (JAXBException e) { 
     throw new IllegalStateException("Unable to initialize"); 
    } 
} 
+6

थ्रेडलोकल बिना लाभ के अन्य उपनिवेश समस्याओं का परिचय देगा। बस एक एकल JAXBContext (यह महंगा हिस्सा है) रखें और जब भी आवश्यक हो तो एक नया Unmarshaller बनाएं। – ymajoros

1

इससे भी बेहतर !! उपर्युक्त पद से अच्छे समाधान के आधार पर, कन्स्ट्रक्टर में संदर्भ केवल एक बार बनाएं, और कक्षा के बजाय इसे सहेजें।

लाइन बदलें: तो getMarshaller/getUnmarshaller में आप निकाल सकते हैं

private Jaxb(Class clazz) 
    { 
    this.jc = JAXBContext.newInstance(clazz); 
    } 

:

private Class clazz; 

इस एक के साथ:

private JAXBContext jc; 

और मुख्य निर्माता इस एक साथ यह पंक्ति:

JAXBContext jc = JAXBContext.newInstance(clazz); 

इस सुधार करता है, मेरे मामले में, कि संसाधन समय 60 ~ 70ms से सिर्फ 5 ~ 10ms

+0

आप जिस XML फ़ाइल को पार्स कर रहे थे वह कितनी बड़ी थी। क्या आप बहुत बड़ी एक्सएमएल फाइलों के साथ महत्वपूर्ण सुधार देखते हैं? – John

+0

यह वास्तव में बड़ी एक्सएमएल फाइलों का मामला नहीं है (खान केवल 2-3 केबी से +6 एमबी तक जाती है), लेकिन इसके बजाय बड़ी संख्या में एक्सएमएल फाइलों की बात है (हम प्रति मिनट लगभग 10,000 xml अनुरोधों की बात कर रहे हैं) ; उस मामले में संदर्भ बनाने के बाद केवल उन छोटे एमएस प्राप्त करने में एक बड़ा अंतर होता है – tbarderas

2

JAXB 2.2 (JSR-222) यह कहना है करने के लिए, अनुभाग में चला जाता है "4.2 JAXBContext":

JAXBContext उदाहरण बनाने में शामिल ओवरहेड से बचने के लिए, JAXB एप्लिकेशन को JAXBContext इंस्टेंस का पुन: उपयोग करने के लिए प्रोत्साहित किया गया है। अमूर्त वर्ग JAXBContext का कार्यान्वयन थ्रेड-सुरक्षित होना आवश्यक है, इस प्रकार, किसी एप्लिकेशन में एकाधिक थ्रेड समान JAXBContext उदाहरण साझा कर सकते हैं।

[..]

JAXBContext वर्ग अपरिवर्तनीय है और इस तरह threadsafe होने के लिए बनाया गया है। जेएक्सबीसी कॉन्टैक्ट का नया उदाहरण बनाते समय संभावित रूप से स्थान ले जाने वाली गतिशील प्रसंस्करण की मात्रा को देखते हुए, यह की अनुशंसा की जाती है कि एक JAXBContext उदाहरण धागे में साझा किया जाए और के रूप में पुन: उपयोग किया जाए ताकि आवेदन प्रदर्शन में सुधार हो सके।

दुर्भाग्य से, विनिर्देश Unmarshaller और Marshaller के धागे की सुरक्षा के संबंध में कोई दावा नहीं करता है। तो यह मानना ​​सबसे अच्छा है कि वे नहीं हैं।

संबंधित मुद्दे