XML: The Performance Killer
Bu yazımın esas amacı aslında Java uygulamarında XML kullanmanın getirdiği maliyetleri ve Dennis Sosnoski amcamızın meşhur XML Model Benchmark Test'lerini tanıtmak.
XML teknolojisi yazılım dünyasının işlerini bir çok noktada kolaylaştıran ama bir o kadar da zorlaştıran bir teknoloji. Özellikle Java ile uygulama geliştiriyorsanız XML'den olabildiğince uzak durmak gerekiyor. XML parsing & generating operasyonları sırasında çok fazla String işlemi olduğu için JVM memory ve CPU kullanımı korkunç artıyor. XML'e performance killer diye boşu boşuna dememişler.
XML'in performance killer 'dan nasıl project killer 'a dönüşebileceğine bakmadan evvel öncelikle neden uygulamalarımızda XML kullanmak zorunda kaldığımıza bir bakalım.
XML kullanımı, özellikle Java dünyasında Web Service'lerin yaygınlaşması ile artmaya başladı. Web Service kullanımını arttıran da hepimizin yakından bildiği SOA (Service Oriented Architecture) oldu. 2000'li yılların başında SOA'nın moda olmaya başlamasıyla, dünyaca ünlü vendor'larımız her zaman yaptıkları gibi bu kavramı da hemen suistimal etmeye başladılar. Bir metodoloji çok tuttuğunda vendor'larımızın ilk yaptığı şey, satabilmek için ortaya zorlama bir ürün çıkarmaktır. SOA'nın bu ürünü de Web Servis implemantasyonları oldu. Web Service ailesi (XML-RPC , REST, SOAP) içinde de en fazla öne çıkarılan SOAP mesajları oldu.
Halbuki SOA'nın felsefisinde tüm servis hizmetlerinin web servisler aracılığı ile verilmesi diye bir zorunluluk yoktur. SOA'da bir servise dış veya iç sistemden erişim ihtiyacı varsa öncelikle servis hizmetini veren (server) ile alanın (client) ortamlarına bakmak gerekir.
1. Durum Servis hizmetini veren ve alanın aynı java container'ında olması.
2. Durum Servis hizmetini verenin ve alanın farklı java container'larında olması
3. Durum Servis hizmetini verenin java fakat alanın farklı bir dile (ASP,C#,vs.) ait container'da olması.
1. Durumda istemci ve sunucu aynı JVM'de olduğu için zaten web servis kullanmaya gerek yoktur. Fakat dikkat edilmesi gereken konu, SOA'nın şartlarından biri olan servisler arası bağımsızlığın (loose coupling) korunmasıdır. Spring Framework 'unun da kullandığı Inversion of Control diye adlandırılan patterni bu duruma güzel bir örnektir.
2. Durumda istemci ve sunucu farklı container'da olmasına rağmen iki taraf da java olduğu için yine web servis kullanmaya gerek yoktur. İlk bakışta servis çağırmak için RMI kullanmak en mantıklı çözüm gibi gözüksede, RMI teknolojisinin http protokolü kullanmaması nedeniyle firewall ve proxy'lerde problem yaşaması, farklı java versiyonları kullanan istemci/sunucu mimarilerinde sorun yaşanması gibi sebeplerden pek tercih edilmemektedir.
Bunun yerine en mantıklı çözüm serialized java objects kullanmaktır. Serializable java nesnelerini aynı web servis mantığı ile örnekteki gibi byte array'e çevirip container'lar arasında http üzerinden transfer edebilirsiniz. Objelerin serialVersionUID 'lerini değiştirmediğiniz sürece JDK 1.3 - 1.5 arasındaki container'lar arasında bile servis çağırabilirsiniz. Serialization&DeSerialization, XML parsing'e göre çok daha hızlı, daha az memory kullanan, binary olduğu için daha az data büyüklüğü oluşturan bir işlemdir. Vakti zamanında yaptığımız testlerde özellikle büyük datalarda 30 kata yakın performans elde etmiştik. Eğer bu konuda daha yetenekli, productionda kullanmaya hazır bir API'ye ihtiyaç duyarsanız JBoss Remoting 'e bir göz atabilirsiniz.
3. Durumda istemci java'dan başka bir container olduğunda web servis kullanmaktan başka bir çare yok. Fakat bu konuda da alınabilecek önlemler var. Eğer standart web servis implementasyonlarından herhangi birini seçme imkanınız var ise SOAP'dan kesinlike uzak durun derim. SOAP çok genel amaçlar için tasarlanmış ve sistem performansını en çok düşüren bir XML protokolüdür.
XML'in sisteminizin performansına olan etkisini belirleyen 3 önemli unsur vardır:
1. XML'in yapısı
Varsayalım elimizde 100KB. büyüklüğünde 2 farklı yapıda XML dosyası olsun. Birincisinin ağaç yapısında aşağıdaki örnekteki gibi olduğunu varsayalım:
<service name="GET_CUSTOMER_INFO">
<input>
<param name="CUSTOMER_ID"></param>
</input>
<output>
<param name="CUSTOMER_NAME">MUSTAFA</param>
<param name="CUSTOMER_SURNAME">MUSTAFA</param>
........................................................................
</output>
</service>
İkincinin ise tek nod'dan oluştuğunu varsayalım:
<data name="CUSTOMER_INFO">asdjhadhadas89789adjkahsdjk........sdhjh567sdf</param>
Herhangi bir XML parser ile (DOM, SAX, PULL farketmez) yukarıdaki aynı büyüklükteki 2 farklı yapıdaki dosyayı parse ettiğinizde çok farklı sonuçlar (hız, cpu ve memory kullanımı) elde ettiğinizi göreceksiniz. Birazdan bahsedeceğimiz XML Parser'in seçimi ile XML'in yapısı arasında çok yakından bir ilişki vardır.
2. XML'in büyüklüğü
XML data'sı büyüdükçe sistem performansı doğal olarak düşer. Fakat XML verisinin büyüklüğü ile sistem performansı arasındaki oran logaritmiktir. Bunun sebebi ise XML'in daha evvel bahsettiğimiz gibi çok fazla memory ve cpu kullanmasıdır. Bir JVM'de aynı anda çok fazla XML parsing işlemi olduğunda CPU bu işlemleri sıraya koymaya başlıyacak, sırada bekleyen XML nesneleri çok fazla memory kullandığından heap'i doldurmaya başlıyacak, JVM heap'in dolduğunu görünce sık sık GC (Garbage Collector) çalıştırmaya başlıyacak, GC çalışırken çok fazla CPU kullandığı ve tüm sistemi çalıştığı sürece suspend ettiği için tüm sistem tabir yerinde ise ağır çekimde ilerleyecektir. Tabii bu durum son kullanıcıya program çöktü olarak yansıyacaktır.
3. XML Model
Buraya kadar anlattıklarımıza rağmen data alışverişlerinde hala XML kullanmaya kararlı iseniz o zaman yapmanız gereken doğru XML parseri seçmek. Aynı zamanda bir SOA danışmanı olan Dennis Sosnoski 'nin eski ama hala meşhur XML Model Benchmark sonuçlarını incelerseniz, farklı test tipleri için meşhur XML API'lerin nasıl değişik test sonuçları verdiğini görebilirsiniz.
Ben genelde parser olarak çok daha hızlı olan ve az memory kullanan PULL parser'ları tercih ediyorum. Bu konuda size de XPP3 'i önerebilirim. Fakat son yıllarda VTD-XML isminde XML datasını String olarak değilde byte olarak işleyen çok hızlı bir XML parser ön plana çıktı. (world's fastest XML processor benchmark results).
Sonuç
Buraya kadar anlattıklarımızı özetlersek çok çok mecbur kalmadıkça konfigürasyon dosyası dışında XML kullanmayın derim. (Bu konfigürasyon dosyalarını okumak için de lütfen kendiniz bir API yazmaya kalkmayın, Apache Commons Configuration'ı kullanın.) Diyelimki çok mecbur kaldınız o zaman aşağıdaki önerilere kulak asmanızda fayda var:
1) SOAP'tan uzak durun ve XML'in yapısını oldukça basit tutun. XML'in yapısı ne kadar basit ise o kadar hızlı işlenir.
2) Farklı yapılarda XML veriniz var ise hepsi için aynı XML Model'ini kullanmayan. Hatta process etmeden evvel, XML'in büyüklüğüne ve yapısına bakıp en uygun XML Model'ini seçen generic bir API bile yazabilirsiniz.
3) Veri büyüklüğünün üst sınırını bilemediğiniz servislerinizi XML ile sunmayın ya da limit koyun. Test ortamlarında ortalama 100Kb.'lık datalar ile çalışırken, production'da bir servis sonucu 10MB.'lık bir XML oluşursa çok ciddi üzülürsünüz :)
4) XML operasyonlarını servisi hazırladığınız veya karşıladığınız katmanda yapın ve XML objelerini hemen basit java objelerine çevirin. Business metodları içine XML objelerini geçirmeyin.
5) Vendorların her söylediğine hemen kanmayın (hatta şüphe ile yaklaşın). Unutmayın onların hedefi daha fazla ürün satmak, sizin hedefiniz ise projenin başarılı olması.
Bu aralar AJAX'ın çok moda olması nedeniyle XML konusunda bir hatırlatma daha yapmak istiyorum. Bildiğiniz gibi AJAX 'da client/server arasındaki data alışverişini mecburen XML ile yapıyor. Developer'lar AJAX kullanırken XML yüzünden sisteme binen yükün farkında değiller. Konu açılmışken AJAX'a henüz giriş yapmayanlar Sezer Yeşiltaş'ın AJAX konusundaki blog'una bir göz atabilirler
Performans katili, projenizin katili olmasın.
İyi çalışmalar...
XML teknolojisi yazılım dünyasının işlerini bir çok noktada kolaylaştıran ama bir o kadar da zorlaştıran bir teknoloji. Özellikle Java ile uygulama geliştiriyorsanız XML'den olabildiğince uzak durmak gerekiyor. XML parsing & generating operasyonları sırasında çok fazla String işlemi olduğu için JVM memory ve CPU kullanımı korkunç artıyor. XML'e performance killer diye boşu boşuna dememişler.
XML'in performance killer 'dan nasıl project killer 'a dönüşebileceğine bakmadan evvel öncelikle neden uygulamalarımızda XML kullanmak zorunda kaldığımıza bir bakalım.
XML kullanımı, özellikle Java dünyasında Web Service'lerin yaygınlaşması ile artmaya başladı. Web Service kullanımını arttıran da hepimizin yakından bildiği SOA (Service Oriented Architecture) oldu. 2000'li yılların başında SOA'nın moda olmaya başlamasıyla, dünyaca ünlü vendor'larımız her zaman yaptıkları gibi bu kavramı da hemen suistimal etmeye başladılar. Bir metodoloji çok tuttuğunda vendor'larımızın ilk yaptığı şey, satabilmek için ortaya zorlama bir ürün çıkarmaktır. SOA'nın bu ürünü de Web Servis implemantasyonları oldu. Web Service ailesi (XML-RPC , REST, SOAP) içinde de en fazla öne çıkarılan SOAP mesajları oldu.
Halbuki SOA'nın felsefisinde tüm servis hizmetlerinin web servisler aracılığı ile verilmesi diye bir zorunluluk yoktur. SOA'da bir servise dış veya iç sistemden erişim ihtiyacı varsa öncelikle servis hizmetini veren (server) ile alanın (client) ortamlarına bakmak gerekir.
1. Durum Servis hizmetini veren ve alanın aynı java container'ında olması.
2. Durum Servis hizmetini verenin ve alanın farklı java container'larında olması
3. Durum Servis hizmetini verenin java fakat alanın farklı bir dile (ASP,C#,vs.) ait container'da olması.
1. Durumda istemci ve sunucu aynı JVM'de olduğu için zaten web servis kullanmaya gerek yoktur. Fakat dikkat edilmesi gereken konu, SOA'nın şartlarından biri olan servisler arası bağımsızlığın (loose coupling) korunmasıdır. Spring Framework 'unun da kullandığı Inversion of Control diye adlandırılan patterni bu duruma güzel bir örnektir.
2. Durumda istemci ve sunucu farklı container'da olmasına rağmen iki taraf da java olduğu için yine web servis kullanmaya gerek yoktur. İlk bakışta servis çağırmak için RMI kullanmak en mantıklı çözüm gibi gözüksede, RMI teknolojisinin http protokolü kullanmaması nedeniyle firewall ve proxy'lerde problem yaşaması, farklı java versiyonları kullanan istemci/sunucu mimarilerinde sorun yaşanması gibi sebeplerden pek tercih edilmemektedir.
Bunun yerine en mantıklı çözüm serialized java objects kullanmaktır. Serializable java nesnelerini aynı web servis mantığı ile örnekteki gibi byte array'e çevirip container'lar arasında http üzerinden transfer edebilirsiniz. Objelerin serialVersionUID 'lerini değiştirmediğiniz sürece JDK 1.3 - 1.5 arasındaki container'lar arasında bile servis çağırabilirsiniz. Serialization&DeSerialization, XML parsing'e göre çok daha hızlı, daha az memory kullanan, binary olduğu için daha az data büyüklüğü oluşturan bir işlemdir. Vakti zamanında yaptığımız testlerde özellikle büyük datalarda 30 kata yakın performans elde etmiştik. Eğer bu konuda daha yetenekli, productionda kullanmaya hazır bir API'ye ihtiyaç duyarsanız JBoss Remoting 'e bir göz atabilirsiniz.
3. Durumda istemci java'dan başka bir container olduğunda web servis kullanmaktan başka bir çare yok. Fakat bu konuda da alınabilecek önlemler var. Eğer standart web servis implementasyonlarından herhangi birini seçme imkanınız var ise SOAP'dan kesinlike uzak durun derim. SOAP çok genel amaçlar için tasarlanmış ve sistem performansını en çok düşüren bir XML protokolüdür.
XML'in sisteminizin performansına olan etkisini belirleyen 3 önemli unsur vardır:
1. XML'in yapısı
Varsayalım elimizde 100KB. büyüklüğünde 2 farklı yapıda XML dosyası olsun. Birincisinin ağaç yapısında aşağıdaki örnekteki gibi olduğunu varsayalım:
<service name="GET_CUSTOMER_INFO">
<input>
<param name="CUSTOMER_ID"></param>
</input>
<output>
<param name="CUSTOMER_NAME">MUSTAFA</param>
<param name="CUSTOMER_SURNAME">MUSTAFA</param>
........................................................................
</output>
</service>
İkincinin ise tek nod'dan oluştuğunu varsayalım:
<data name="CUSTOMER_INFO">asdjhadhadas89789adjkahsdjk........sdhjh567sdf</param>
Herhangi bir XML parser ile (DOM, SAX, PULL farketmez) yukarıdaki aynı büyüklükteki 2 farklı yapıdaki dosyayı parse ettiğinizde çok farklı sonuçlar (hız, cpu ve memory kullanımı) elde ettiğinizi göreceksiniz. Birazdan bahsedeceğimiz XML Parser'in seçimi ile XML'in yapısı arasında çok yakından bir ilişki vardır.
2. XML'in büyüklüğü
XML data'sı büyüdükçe sistem performansı doğal olarak düşer. Fakat XML verisinin büyüklüğü ile sistem performansı arasındaki oran logaritmiktir. Bunun sebebi ise XML'in daha evvel bahsettiğimiz gibi çok fazla memory ve cpu kullanmasıdır. Bir JVM'de aynı anda çok fazla XML parsing işlemi olduğunda CPU bu işlemleri sıraya koymaya başlıyacak, sırada bekleyen XML nesneleri çok fazla memory kullandığından heap'i doldurmaya başlıyacak, JVM heap'in dolduğunu görünce sık sık GC (Garbage Collector) çalıştırmaya başlıyacak, GC çalışırken çok fazla CPU kullandığı ve tüm sistemi çalıştığı sürece suspend ettiği için tüm sistem tabir yerinde ise ağır çekimde ilerleyecektir. Tabii bu durum son kullanıcıya program çöktü olarak yansıyacaktır.
3. XML Model
Buraya kadar anlattıklarımıza rağmen data alışverişlerinde hala XML kullanmaya kararlı iseniz o zaman yapmanız gereken doğru XML parseri seçmek. Aynı zamanda bir SOA danışmanı olan Dennis Sosnoski 'nin eski ama hala meşhur XML Model Benchmark sonuçlarını incelerseniz, farklı test tipleri için meşhur XML API'lerin nasıl değişik test sonuçları verdiğini görebilirsiniz.
Ben genelde parser olarak çok daha hızlı olan ve az memory kullanan PULL parser'ları tercih ediyorum. Bu konuda size de XPP3 'i önerebilirim. Fakat son yıllarda VTD-XML isminde XML datasını String olarak değilde byte olarak işleyen çok hızlı bir XML parser ön plana çıktı. (world's fastest XML processor benchmark results).
Sonuç
Buraya kadar anlattıklarımızı özetlersek çok çok mecbur kalmadıkça konfigürasyon dosyası dışında XML kullanmayın derim. (Bu konfigürasyon dosyalarını okumak için de lütfen kendiniz bir API yazmaya kalkmayın, Apache Commons Configuration'ı kullanın.) Diyelimki çok mecbur kaldınız o zaman aşağıdaki önerilere kulak asmanızda fayda var:
1) SOAP'tan uzak durun ve XML'in yapısını oldukça basit tutun. XML'in yapısı ne kadar basit ise o kadar hızlı işlenir.
2) Farklı yapılarda XML veriniz var ise hepsi için aynı XML Model'ini kullanmayan. Hatta process etmeden evvel, XML'in büyüklüğüne ve yapısına bakıp en uygun XML Model'ini seçen generic bir API bile yazabilirsiniz.
3) Veri büyüklüğünün üst sınırını bilemediğiniz servislerinizi XML ile sunmayın ya da limit koyun. Test ortamlarında ortalama 100Kb.'lık datalar ile çalışırken, production'da bir servis sonucu 10MB.'lık bir XML oluşursa çok ciddi üzülürsünüz :)
4) XML operasyonlarını servisi hazırladığınız veya karşıladığınız katmanda yapın ve XML objelerini hemen basit java objelerine çevirin. Business metodları içine XML objelerini geçirmeyin.
5) Vendorların her söylediğine hemen kanmayın (hatta şüphe ile yaklaşın). Unutmayın onların hedefi daha fazla ürün satmak, sizin hedefiniz ise projenin başarılı olması.
Bu aralar AJAX'ın çok moda olması nedeniyle XML konusunda bir hatırlatma daha yapmak istiyorum. Bildiğiniz gibi AJAX 'da client/server arasındaki data alışverişini mecburen XML ile yapıyor. Developer'lar AJAX kullanırken XML yüzünden sisteme binen yükün farkında değiller. Konu açılmışken AJAX'a henüz giriş yapmayanlar Sezer Yeşiltaş'ın AJAX konusundaki blog'una bir göz atabilirler
Performans katili, projenizin katili olmasın.
İyi çalışmalar...
Etiketler: java, performance, SOAP, webservis, XML
3 Yorum:
YazılımMühendisliğindeki yazınızdan sonra geldim bu yazıaya.
Aslında keşke XML'in faydaları da yazının biryerlerinde olsaydı da konudan habersizler bu yazıyı okuyunca XML'den korkmamış olurlardı.
XML konusunda bence en önemli kriter kullandığınız ayrıştırıcı ve dosya boyutu.Kapasiteniz sınırlıysa DOM'a bulaşmamak lazım.
Yalnız bazen o performasn katili dediğiniz XML hayat kurtarıcı olabiliyor. Mesela bir arama motoru projemizde veirleri SQL SERVER 2005 'den XML'e taşımıştık ve performansımız kat kat artmıştı.
Ajax konusundaki durum bizdeki hemen her noktada geçerli yani DENGE konusu. AJax sayesinde client-server arasındaki trafik azalıyor.Bu gayet güzel çünkü istekler standart httprequest yerine xmlhttp requestler halinde sıkıştırılıp gönderiliyor. Bu defa da bu sıkıştırılmış verinin açılıp yani xml içinden çekilip değerlendirilmesi gerekiyor.Bu da trafik ile performans arasında bir denge kurmayı gerektiriyor. Bazne görüyorum bazı vatandaşlar olur olmaz yerde AJAX kullanıyorlar. Halbuki teknolojinin fazlası da göz çıkarabilir...
Emin olun XML'in faydası konusunda çıkan yazıların sayısı, risklerinden bahsedenlerden kat kat fazla.
Bu arada XML konusunda güncel bir yazı daha:
href="http://www-128.ibm.com/developerworks/java/library/x-xjavaforum1.html?ca=drs-">What's
XML really good for?
Yorumlarınız için teşekkürler.
Selamlar Mustafa Abi;
Blogunu her ziyaret edişimde bu yazıyı bir kere okuyorum. Hem en çok okunanlar listesinde başı çektiği için hem de tanışmamıza vesile olduğu için.
XML perfomansı konusundaki sıkıntının nedeni aslında hep aynı noktaya dayanıyor: HIGH LEVEL DİLLERİ SİHİRLİ DEĞNEK GİBİ KULLANIOYORUZ.
Yani bir noktaya basıyoruz önümüze metod deryası çıkıoyr. Ondan sonra da o tip senin bu tip benim diyerekten tipleri biribirine dönüştürüyoruz. Ohh ne güzel oldu bir metod çağırdık bir satır kodla işi hallettik. Ama arka planda kaç satır kod çağırdık Allah bilir :)
XML ile çalışırken özellikle text formatında olan veriler nispeten daha iyi ama veriyi alıp stringden başka hallere dönüştürüyorsanız vay halinize. O nedenle bu tip bir işe kalkışmadan evvel veri setimizi biraz analiz etmek güzel olacaktır.
SOAP konusundaki perişanlığı ben de bitirme projemde bizzat gördüm. Aynı makinadaki veriyi alıp web servisi ile veritabanına kaydetmem çok uzun zaman aldı.O nedenle Web servisi ve service oriented olmak konusunda da ciddi ciddi düşünmek gerekiyor.
Hem .NETciler hem de JAVAcılar için birkaç link vermek istiyorum:
Comparing Web service perfomance:
http://msdn2.microsoft.com/en-us/vstudio/aa700840.aspx
Checklist web service performance:
http://msdn2.microsoft.com/en-us/library/ms979173.aspx
Comparing Web sErvice performance (2):
http://www.sosnoski.com/presents/cleansoap/comparing.html
Ve Sun 'ın cevabı :
http://java.sun.com/performance/reference/whitepapers/WS_Test-1_0.pdf
Selamlar..
Yorum Gönder
Kaydol: Kayıt Yorumları [Atom]
<< Ana Sayfa