Alelade Hikayeler – II: Bir Başka Performans Problemi
Bugünkü hikayemizde yine bir performans problemi var. Problem, Java EE ile geliştirilmiş ve Weblogic AS üzerinde çalışan, transactional, web üzerinden tamamen internete açık ve sorgulama arayüzlerinin yoğun olarak kullanıldığı bir bilgi sistemiydi. Sistem çoğunlukla mesai saatleri içinde kullanılıyordu, sonrasında erişilebilir olsa bile kullanımı çok azdı. Problem ise, tamamen gelişigüzel ya da random olarak seyreden yavaşlıktı. Sistem yöneticileri yaptıkları gözlemlerde zaman zaman, ön taraftaki use caselerle ilişkilendiremedikleri yavaşlamaların sebebinin aşırı bellek tüketimi olduğunu belirlemiş durumdaydılar. Sistem clustered bir ortamda çalıştığından herhangi bir kesinti yaşanmıyordu ama bu problemin de çözülmesi gerekliydi.
Sistem yöneticilerinin verdikleri bilgilerden sonra lider developerlarla görüştüğümde, bazı usual suspect araştırmalarımı yaptım. Örneğin veri tabanı sorgulamaları, sorgulardan dönen verinin mahiyeti, bu verinin uygulama tarafından nesnelerle nasıl yönetildiği, web tarafındaki oturum (session) yönetimi vs. konulardaki yaklaşımlarını öğrenmeye çalıştım. Developerlardan bir şey çıkmadı, dahası her şeyi düşünerek ve iyi bir şekilde yaptıklarını, bundan dolayı da bu bellek problemine anlam veremediklerini söylediler. Biraz da “bizim problemimiz” değil havasındaydılar izlenimi elde ettim.
Sonrasında, sistemin kullanımda olmadığı, gece yarısı gibi bir zamanda, canlı ortamdaki uygulama sunucularının bize daha fazla bilgi verecek şekilde çalıştırılmalarını sağladım. Ben de test amaçlı kullanılan, pre-production sistem üzerinde çalışmaya başladım. Ortama girmek, genel de olsa mimariyi öğrenmek, sistemin ayağa kalkarken kullandığı parametrelerini bulmak vs. nihayetinde böyle ortamlarda sıklıkla yaptıklarımdandır. Sistemler büyüdükçe, onlara dokunmak ve bilgi almak daha da karmaşıklaşır. Erişebilmek bile bir problem haline gelir.
Neyse, test sistemi üzerinde bunları elde ettikten sonra, olabildiğince çok kişinin, sistemi kullanması sağlandı ve ben de JVM içindeki olup biteni gözlemlemeye başladım. Fakat bu çalışma çok da işe yaramadı, çünkü problemli durumu üretmedi. Sebebi, kullanıcı sayısını azlığı yanında, hep bildiğimiz, developerların tester olarak kullanılmasının getirdiği yapaylıktı. Fakat sebebini bilmediğimiz bir problemi ararken, şansımızı olabildiğince arttırmak için yapılabilecek her şeyi yapma eğiliminde oluruz. Hatta bu çalışmalar sırasında, performansla pek de alakası olmayan konularda gözlemler yaptım ve bunları paylaştım. Mesela isimlendirme ile ilgili konulardan tutun da çok karmaşık metot ve sınıflara kadar, cohesion ve coupling problemleri, gerekli gereksiz kullanılmış wrapper sınıflar, çok threadli ortam olmasına rağmen bu göz önüne alınmadan yazılmış kodlar vs. Tonla teknik borç çıkar o sıradaki çalışmalardan ama bunları kim duyar da kulak verir, onu sormayın.
Performans problemlerinin sebebini bulmak çoğu zaman onları düzeltmekten daha zor olabilir. Çok basit bir kod hatası, deadlock ya da sonsuz döngü problemi, hemen hiç bir şekilde koda bakarak anlaşılacak tipten bir problem değildir örneğin. Dolayısıyla o hatayı tekrardan üretemezseniz, probleme yol açan durumu tekrar, kontrollü bir şekilde gözlemleyemezseniz, problemi bulmak için çok da şansınız yoktur. Zamanınız ve imkanınız varsa, sistem üzerinde otomatik test araçlarıyla çalışıp yük üretebilirsiniz ama hala problemi oluşturacak durumu yaratamayabilirsiniz. Örneğin, yüzlerce arayüzün belki de çok basit bir noktasından tetiklenen bir problemdir peşinde koştuğunuz ama siz boş yere farklı use caselere yüklenerek arka tarafta, JVM’in içinde bir bellek problemi, çok uzun süren metot çağrıları, veri tabanından dönmeyen sorgular vs. arar durusunuz. Nitekim burada da öyle oldu.
Ertesi gün çalışmaya devam ederken, canlı ortamdaki uygulama sunucularından birinde benzer bir yavaşlık gözlemlendi ve sonrasında uygulama sunucusunun JVM’inin dumpını alıp üzerinde çalıştığımda, hiç bir filtreden geçmeden dolayısıyla “where” ifadesine sahip olmadan veri tabanına gönderilen bir sorgunun, yüzbinlerce satırı belleğe yüklediğini, JVM’in de heap belleğinin tamamını bu sorgudan dönen satırlardaki nesneleri oluşturmak için kullandığını gözlemledim. Hatta dumptan yola çıkarak o anda sistemde hangi kullanıcıların oturumlarının olduğunu, hangi kullanıcının, web arayüzünde nerede, bu sorguyu çalıştıracak use casei işlettiği vb. verilerin hepsine ulaştım. Bu arada parantezlik ufak bir bilgi: Eğer kritik bilgileri, örneğin şifreleri vs. hashlemezseniz, benim gibi çalışanlar, o anda sistemi kullananların tüm mahrem bilgilerini kolayca görebilirler!
Sonrası iplik söküğü gibi geldi zaten. Ön tarafta, arayüzde ne yapıldığı, arkada hangi metot çağrılarından sonra veri tabanına hangi sql cümlesinin gönderildiği, dönen cevaptaki satır sayısı, her satırdaki bilgi vs. hepsini ortaya koydum. Developerların gözünden kaçan bir durum, kötü bir sql sorgusu oluşturuyor ve joinlerden sonra oluşan yüzbinlerce satır, sorgunun cevabı olarak JVM’e dönülüyordu. Web arayüzünde zaten böyle bir cevap beklemeyen developerlar, herhangi bir paging de uygulamadıklarından, JVM’e, veri tabanından dönen satırlar için tonla nesne yaratmak dışında bir seçenek de bırakmıyorlardı.
Developerlara bu durumu ilettiğimizde, hızlıca gidip web arayüzüne bir kaç kontrol, zorunlu alan vs. filtreleri koydular ve problem ortadan kalktı. Problemi bulmak 2 küsür gün tuttu, çözmek en çok bir saatti! Ah şu developerlar olmasa ne kadar rahat olacak yazılım geliştirmek!
Developerlar eğer yaptıkları işi daha geniş bir perspektiften göremiyor ve “benim makinamda çalışıyor” ya da “ben test ettim, hiç bir problem yok” şeklinde konuşuyorlarsa, lütfen buna güvenmeyin. Bu tavra önem verin, bu tür sözlerin arkasını doldurmaya zorlayın onları ama sadece bu sözlerle ilerlemeyin. Ya da bir başka deyişle, her developerın bunu söyleme hakkı olmadığını bilin. Tam da bu yüzden architect/mimar vb. rollerle, sisteme çok farklı açılardan, yukarıdan, bakabilen, tecrübeli ve sistem anlayışına sahip kişilere ihtiyacımız var.
Kıssadan hisse: Yazılım geliştirme, developerlara bırakılamayacak kadar karmaşık bir iştir!
Toplam görüntülenme sayısı: 714
Gökhan
04 Ekim 2017 @ 16:43
Akın hocam, öğretici ve bilgilendirici yazınız için çok teşekkür ediyorum. Kendimce dersler çıkartmaya çalıştım.
“Yazılım geliştirme, developerlara bırakılamayacak kadar karmaşık bir iştir!”
Bir jr. Developer olarak katıldığım görüştür. Aynı zamanda Yazılım yönetme işi yöneticiye bırakılamayacak kadar kompleks bir iştir. Bir patron şirketinde yazılım işinin harcıâlem iş olarak görüldüğünden dolayı birçok ızdıraplar çekmiştim, 5 ay dayanabildim. (Temel olarak düzeltilmesi çok zor başka sorunlar da vardı.)Testing kavramlarını öğrenmeye çalıştığım bugünlerde artık herhangi bir teknoloji ve programlama dili / framework öğrenmeye çalışmıyorum. Yazılımın bu soyutluluk kavramlarını kafamda oturtmaya ve onu herhangi bir teknolojide gerektiğinde implemente etmeye gayret gösteriyorum, tabii ki kendimi bu konuda çok yetersiz bulmaktayım aynı zamanda derme çatma yazıp geçmeyi de içime sindiremiyorum.
Birde kendimde de zaman zaman bulduğum iyi bir alışkanlık olmayan, yazılımcı iyimserliğini terkedip, eleştirel düşüncelere açık olmak gerektiği görüşündeyim.
Akin
05 Ekim 2017 @ 02:30
Merhaba Gökhan,
Tabi ki, bu anlamda yazılım, sadece tek bir kişinin alıp götürmesiyle basarılabilecek bir sye degildir. Özelikle ülkemizde bu şekilde bir kişinin kararlarına bırakmak yaygın bir uygulamadır ve bu kişi yönetici olduğunda da sıklıkla acı ortaya çıkmaktadır.
SÖylediklerine katılıyorum.
Teşekkür ederim.