Alelade Hikayeler – I: Küçük Bir Performans Problemi

Yazılım dünyasında en sık yaşanan problemlerden birisi de, “performans” genellemesiyle anılan bir dizi problemdir. Problem bazen bir işlemin yapılmasının uzun sürmesidir, bazen son derece hızlı olan işlemlerin zaman zaman, muhtemelen sistemin yüküne bağlı olarak yavaşlamasıdır, bazen fazla bellek kullanımıdır, bazen de veri tabanından sorguların çok yavaş gelmesidir vs. Bu tür performans problemlerini çözmek bana daima en tatmin edici işlerden gelmiştir.

Bir gün ofisimde çalışırken, bir yazılım evi sahibi ve yöneticisi, feveran içinde bana ulaştı. Müşterileri için geliştirdikleri sisteme en son yaptıkları değişiklikleri devreye aldıklarında yaşadıkları ve kendilerini bir hayli zora koyan bir performans problemini çözecek kişiyi araştırırken bana ulaşmıştı. Bana telefonda söylediği şey, yeni yaptıkları deploymenttan sonra 10-15 dakika içinde sistem cevap veremez hale geliyor ve nihayetinde de çöküyordu. Sistem, Tomcat üzerinde çalışan ve tabi olarak Java ile geliştirilmiş, web arayüzlü ve kurum içinde, intranette pek çok kullanıcısı olan operasyonel bir bilgi sistemiydi.  Bundan dolayı sistemi kullanan müşterilerine karşı çok zor durumda kalmışlardı ve kendini çaresiz hissediyordu. Sistemin de tabi olarak kullanıcıları vardı ve eski sürüme dönerek hiç olmazsa işlerin devam etmesini sağlıyorlardı.

Bu konuşmadan yaklaşık 15-20 dakika kadar sonra, yaptığımız telefon görüşmeleri sayesinde, sıkıntılı olan sisteme erişmiş haldeydim. Ayrıca bu sistemin koduna da erişim sağladı müşterim. Sistem yöneticisi yardımıyla kabaca ne olup bittiğini anladıktan sonra bir-iki ufak ayar ile Tomcat’i tekrar başlattım ve ertesi sabah, kullanıcıların gelip sistemi kullanmaya başlamalarını bekledik. Tabi, ertesi sabah, çalışma saatini müteakip 10-15 dakika içinde sistem yine çalışamaz hale geldi ve JVM de bize bir dump üretti.

Elimdeki JVM dumpı ve sistemin Java kodlarına erişimim sayesinde yaklaşık 15-20 dakikada, hadi abarttım diyeyim, yarım saat içinde problemin sebebini, koddaki satırını hatta çözümünü belirlemiştim. Nihayetinde gözden kaçan çok basit bir kodlama hatasından kaynaklanıyordu problem. Kodun o parçası sonsuz döngüye giriyor ve her döngüde üretilen yeni nesneler GC tarafından toplanamadığından, çünkü nesneler bir torbaya (collection) konuyordu, belleği şişiriyordu.

Müşteriye durumu açıkladım, yapılması gerekeni de belirttim ve onlar da sistemi sorunsuz bir şekilde devreye aldılar. Onların derdi çözüldü, beni keyfim arttı ve para da kazandım.

Ama sanırım bu kısa hikayede göze çarpan başka noktalar da var. Neler mesela?

Bu hikayeden yazılım geliştirme ile ilgili olarak çıkarılabilecek olan dersler şunlardır:

  1. Eğer kodunuzu daha sakin kafayla, ne yaptığınızı düşünerek yazarsanız, çok yüksek ihtimalle böyle bir hata yapmazsınız.
  2. Eğer yazdığınız kodun birim testini yaparsanız, bu türden problemleri asla yaşamazsınız.
  3. Yazdığınız kodu makinanıza deploy edip, biraz doğru düzgün bir veri ile çalıştırsanız ki biz buna smoke test diyoruz, bu problemi yakalarsınız.
  4. Eğer kod gözden geçirmeleri (review) yaparsanız, sizin gözünüzden kaçsa bile, yorgundunuz, aile-sosyal hayatta stresleriniz vardı, vs., muhtemelen arkadaşlarınızın, daha tecrübeli olanların gözünden kaçmaz.
  5. Eğer sistemin entegrasyon testini yaparsanız, bu türden problemlerler çok daha az karşılaşırsınız.
  6. Eğer sistemin fonksiyonel testini yaparsanız, testerlarınızla, bu türden problemlerleri muhtemelen müşteri karşısına çıkmadan yakalarsınız.
  7. Yukarıdaki üç testi ve gözden geçirmeleri yaparsanız, herhangi bir test ya da tamamen informal bir gözden geçirme yapılsa bile, kesinlikle bu problem müşterinin önüne gelmez ve nerede bulduğunuza göre çok daha ucuza çözersiniz.

Bunlar, yazılım süreçlerini doğru işletmekle ilgili olarak yapılabilecek çıkarımlar. Genel prensipler açısından ise şöyle çıkarımlarda bulunabiliriz:

Belki 40-50 kişilik developer ve sistem yöneticisinden oluşan bir yazılım ve sistem ekibine sahip bir yazılım evinin ürettiği yüzbinlerce belki bir kaç milyon satırlık koddaki bir performans problemini bulmak yarım saati geçmeyen bir sürede başarılabiliyorsa, bu durumun sistemsel bir problem olduğu açıktır. Çok sıklıkla yaptığımız gibi, zeka ya da yetenek ile açıklayamayız bu farkı. Bu fark, sistemi tasarlayan, kodlayan ve deploy eden takımın içinde hiç bir şekilde bir performans farkındalığının olmamasıyla açıklanabilir. Ayrıca bu durum, bu takımda merak edip Java’nın performans problemlerini araştıran, etrafındakileri bilgilendiren meraklı kişilerin olmadığı şeklinde de okunabilir. Bu fark, sistemi tek tek developerların geliştirdiği ama kesinlikle “bir takımın” geliştirmediği şeklinde de okunabilir. Ve bu durum, gerekli temel bilgiye ve problemi bulup, analiz edip, çözme yetkinliklerine sahip bir kişinin, pek çok insanın günlerce, bilinçsizce problemle cebelleşmelerinden çok daha etkin bir şekilde sonuca ulaşabileceğini de gösterir.

Kıssadan hisse: İyi bir teoriden daha pratik bir şey yoktur. (There’s nothing more practical than a good theory. (Kurt Lewin))

Toplam görüntülenme sayısı: 746