ฉันจะปรับปรุงประสิทธิภาพของแอปพลิเคชันที่ใช้การดำเนินการ JAXBContext.newInstance ได้อย่างไร

ฉันใช้การดำเนินการ JAXBContext.newInstance ในเว็บแอปพลิเคชันที่ใช้ JBoss ของฉัน อย่างที่ฉันเข้าใจการดำเนินการนี้มีน้ำหนักมาก ฉันต้องการเพียงสองอินสแตนซ์ที่ไม่ซ้ำกันของคลาส Marshaller

ข้อเสนอเริ่มต้นของฉันคือการมีบล็อก Initializer แบบคงที่ที่จะเริ่มต้นอินสแตนซ์ทั้งสองนี้เพียงครั้งเดียวเมื่อโหลดคลาส:

public class MyWebApp {
    private static Marshaller requestMarshaller;
    private static Marshaller responseMarshaller;

    static {
        try {
            // one time instance creation
            requestMarshaller = JAXBContext.newInstance(Request.class).createMarshaller();
            responseMarshaller = JAXBContext.newInstance(Response.class).createMarshaller();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    private void doSomething() {
            requestMarshaller.marshall(...);
            responseMarshaller.marshall(...);
            ...
    }

}

หากนี่เป็นวิธีแก้ปัญหาที่สมเหตุสมผล ฉันเดาว่าฉันจะตอบคำถามของฉันเองแล้ว แต่ฉันอยากรู้ว่านี่เป็นวิธีที่ถูกต้องในการทำเช่นนี้หรือไม่


person ryan    schedule 18.05.2011    source แหล่งที่มา


คำตอบ (5)


การใช้งาน JAXB (Metro, EclipseLink MOXy, Apache JaxMe ฯลฯ) โดยทั่วไป เริ่มต้นข้อมูลเมตาระหว่างการโทร JAXBContext.newInstance เครื่องมือ OXM ทั้งหมดจำเป็นต้องเริ่มต้นข้อมูลเมตาของการแมป ณ จุดใดจุดหนึ่ง และพยายามลดต้นทุนของการดำเนินการนี้ให้เหลือน้อยที่สุด เนื่องจากเป็นไปไม่ได้ที่จะทำโดยไม่มีค่าใช้จ่าย ควรทำเพียงครั้งเดียวเท่านั้น อินสแตนซ์ของ JAXBContext นั้นปลอดภัยต่อเธรด ดังนั้นคุณจึงต้องสร้างมันขึ้นมาเพียงครั้งเดียวเท่านั้น

จากข้อกำหนด JAXB 2.2 ส่วนที่ 4.2 บริบท JAXB:

เพื่อหลีกเลี่ยงค่าใช้จ่ายที่เกี่ยวข้องกับการสร้างอินสแตนซ์ JAXBContext เราขอแนะนำให้แอปพลิเคชัน JAXB ใช้อินสแตนซ์ JAXBContext ซ้ำ การใช้งานคลาสนามธรรม JAXBContext จำเป็นต้องมีเธรดที่ปลอดภัย ดังนั้น หลายเธรดในแอปพลิเคชันสามารถแชร์อินสแตนซ์ JAXBContext เดียวกันได้

อินสแตนซ์ของ Marshaller และ Unmarshaller ไม่ปลอดภัยสำหรับเธรด และจะต้องไม่ถูกแชร์ระหว่างเธรด เนื่องจากสร้างได้ง่าย

person bdoughan    schedule 18.05.2011

JAXBContext ควรเป็นแบบคงที่เสมอ จึงปลอดภัยสำหรับเธรด

Marshallers และ Unmarshallers มีราคาถูกและไม่ปลอดภัยต่อเธรด คุณควรสร้าง JAXBContext หนึ่งครั้ง และสร้าง marshallers/unmarshallers สำหรับทุกการดำเนินการ

public class MyWebApp {
    private static JAXBContext jaxbContext;

    static {
        try {
            // one time instance creation
            jaxbContext = JAXBContext.newInstance(Request.class, Response.class);
        } catch (JAXBException e) {
            throw new IllegalStateException(e);
        }
    }

    private void doSomething() {                
            jaxbContext.createMarshaller().marshall(...);
            ...
    }

}

ใช้ marshaller เดียวกันเพื่อจัดเรียงทุกอย่าง (เพิ่มคลาสทั้งหมดเมื่อคุณสร้างบริบท)

person cocorossello    schedule 03.07.2014
comment
เพียงแค่แสดงความคิดเห็น: คุณไม่ควรใช้ marshallers/unmarshallers ซ้ำ พวกมันไม่ปลอดภัยสำหรับเธรด แค่สร้างมันขึ้นมาในแต่ละครั้งก็เร็วมาก - person cocorossello; 03.06.2015
comment
ฉันคิดว่าวิธีแก้ปัญหาที่แนะนำที่นี่ตรงประเด็นและมีประโยชน์มาก แต่ฉันไม่เชื่อว่าตัวอย่างโค้ดจะแสดงให้เห็นถึงประเด็นที่เกิดขึ้นในข้อความที่คุณไม่ควรเรียก JAXBContext.newInstance() ทุกครั้งที่คุณต้องการ Marshaller . บรรทัดใน doSomething() ไม่ควรเป็น requestMarshaller = jaxbContext.createMarshaller(); ใช่หรือไม่ - person rscarter; 23.09.2015

ฉันเพิ่งทำการทดสอบประสิทธิภาพด้วย JAXBContext.newInstance และผลลัพธ์ได้รับการบันทึกไว้ที่นี่

http://app-inf.blogspot.com/2012/10/Performance-tuning-logging-right-way.html

เมื่อเรียกโดยเธรดเดียว โดยใช้สคีมาที่ค่อนข้างใหญ่ซึ่งสร้างคลาส ~195 คลาส จะใช้เวลาประมาณ ~400ms จึงจะเสร็จสิ้น เมื่อเรียกใช้ 20 เธรดพร้อมกัน ทำให้เกิดการขัดแย้งของ CPU และใช้เวลาประมาณ ~5,000ms จึงจะเสร็จสิ้น การสร้าง marshaller และการทำให้เป็นอนุกรมของวัตถุของวัตถุขนาดเล็กเพียง ~14ms เท่านั้น

person user1738754    schedule 11.10.2012

หนึ่งสามารถใช้ javax.xml.bind.JAXB มันมีวิธีการแบบจอมพลโดยตรงและแบบไม่จอมพล ดังนั้นคุณจึงไม่ต้องกังวลกับการสร้างอินสแตนซ์ของ JAXB

เช่น. JAXB.unmarshal(inputStream/inputFile, outputClassExpected) หรือ JAXB.marshal(jaxbObject, xmlOutputFile/xmlOutputStream)

person sandeep kale    schedule 28.03.2016
comment
คุณเห็นสิ่งนี้ใน javadoc ของคลาส javax หรือไม่ .xml.bind.JAXB? โดยทั่วไปแล้ว ประสิทธิภาพไม่จำเป็นต้องเหมาะสมที่สุดเสมอไป เป็นที่คาดหวังกันว่าผู้ที่จำเป็นต้องเขียนโค้ดที่มีความสำคัญต่อประสิทธิภาพจะใช้ JAXB API ที่เหลือโดยตรง - person Thomas Fritsch; 11.09.2017
comment
@ThomasFritsch ใช่ ประสิทธิภาพอาจเป็นข้อกังวลสำหรับโครงการที่สำคัญ เรื่องนี้ต้องตรวจสอบก่อนว่าใช่หรือไม่ อาจจะเขียน marshaller/un-marshaller ของตัวเองมาช่วยก็ได้ - person sandeep kale; 14.09.2017
comment
ในกรณีของฉัน JAXB.marshall ใช้แคชของตัวเองในบริบท Oracle JDK 8 ปรากฎว่าเร็วกว่าเมื่อใช้ Jaxb API และไม่แคชบริบท - person Filip; 14.03.2019

คุณควรสร้างวัตถุ JAXBContext เดี่ยวต่อคลาส bean ดูสิ่งนี้

person Nitin    schedule 10.04.2018