Web Sitesi Performans İyileştirmeleri

Yakın zamanda telvee‘nin biraz daha hızlı yüklenebilmesi için django_compressor kullanarak ve arkaplan resimlerini düzenleyerek iyileştirmeler yaptım. İşin güzel yanı bunları gerçekleştirirken geliştirme ortamında veya tasarımda köklü değişiklikler yapmamın gerekmemesiydi. Detaylardan aşağıda bahsedeceğim. Daha önce konunun teorik kısmına kısaca değinmek istiyorum.

Takip ettiğim ve büyük zevkle okuduğum bloglardan biri Steve Souders’in High Performance Web Sites isimli blogu. İtiraf etmeliyim ki ilk okuduğumda pek aklıma yatmamıştı; yüklenecek resimleri birleştirmek, tarayıcıların kendilerine özgü yükleme davranışları… Bana erken iyileştirme gibi gelmişti. Fakat okumaya devam ettiğimde bu endişelerin yanlış olduğunu anladım. Steve Souders yüksek performanslı web siteleri konusunda bir uzman ve anlattıkları da çoğunlukla testlerle desteklenmiş, gerçekçi teknikler. Eğer takip etmiyorsanız, web uygulamaları geliştirmeseniz bile, RSS okuyucunuza eklemenizi öneririm.

İyileştirme Teknikleri

İyileştirme tekniklerini iki grupta toplayabiliriz:

  1. Yüklenecek verinin boyutunu azaltmaya yönelik teknikler.
    • Minifying: CSS ve JavaScript dosyalarında yorumları ve gerekmeyen boşlukları yok ederek dosya boyutunu azaltmaya dayanıyor. Hatta YUI Compressor ve Closure daha da ileri giderek JavaScript kodunda, işleyişi aynı kalmak kaydıyla, düzenlemeler yapabiliyor.
    • Gzip Sıkıştırma: Web tarayıcıları uzun zamandır gzip ile sıkıştırılmış içeriği kabul edebiliyor. Biraz önce, deneme amacıyla 13 KB’lık bir metin dosyasını sıkıştırdım, sonuç 4 KB oldu. Üçte ikilik sıkıştırma oranı hiç de fena değil.
  2. HTTP isteklerini azaltmaya yönelik teknikler.
    • Birleştirme: CSS ve JavaScript dosyaları, sıraları bozulmamak şartıyla, arka arkaya eklenerek tek bir dosya, dolayısıyla tek bir HTTP isteği haline getirilebilir. Birleştirilmiş dosyalarda gzip sıkıştırma da daha iyi sonuç verebilir. Benzer şekilde arkaplan resimleri de bir dosyada toplanıp, oluşturulan sprite üzerindeki koordinatları kullanarak istenen resim tekrar elde edilebilir.
    • Data URI’ler: Kullanılan resimleri (veya başka tür dosyaları), CSS (veya JavaScript veya HTML) içine gömmek için data: URI‘ler kullanılabilir. Böylece gömülü dosyalar için HTTP isteği yapılması gerekmez.

Tüm bu iyileştirmeleri yapmak güzel ama, JavaScript dosyalarımı birleştirip üzerine bir de minify ettikten sonra bir değişiklik yapmak istediğimde ne olacak diye düşünüyor olabilirsiniz. Yukarıda saydığım teknikleri körü körüne uygulamak yerine mantıklı bir yol izlemekte fayda var:

  • Her şeyden önce otomatikleştirilebilecek her şeyi otomatikleştirmek ilkesi geliyor. Yukarıdaki örnekten hareketle betik dosyaları ayrı ayrı, sıkıştırılmamış olarak düzenlenip uygulama yayınlanacağı zaman birleştirme ve sıkıştırma uygulanabilir. Hatta daha da ileri gidilerek yazılımın değişen dosyaları fark ederek gerekli işlemleri kendi kendine uygulaması sağlanabilir. (django_compressor böyle yapıyor)
  • Arkaplan resmi birleştirmede endişe ettiğim konu tasarımın düzenlenmesi aşamasında işlerin karışma olasılığıydı. Fakat sprite’ların hangi resimlerden oluşturulacağının dikkatlice seçilmesi durumunda, aksine düzenleme yapmanın daha da kolaylaşabileceğini gördüm. İşe aynı tasarım elemanına ait resimleri birleştirmeyle başlayın. Karmaşık yerleştirme düzenlerinden kaçının, mümkün olduğu kadar sadece yan yana veya alt alta yerleştirin. Resim aralarına ve sprite çevresine transparan boşluk koymayı ihmal etmeyin. Mümkün olduğu kadar aynı sayfada yüklenecek resimleri birleştirin, yarısı kullanılacak diye tüm bir sprite yüklenmesin. Tüm resimler sprite olsun diye zorlamayın, zaten bu saydığım noktalara dikkat ederseniz olmayacaktır.
  • İyileştirme yaparken elinizin altındaki araçları kullanmayı ihmal etmeyin. Genel analiz için YSlow‘u, resim birleştirme için SpriteMe‘yi, farklı iyileştirme programlarınının kendi betikleriniz üzerindeki başarısını karşılaştırmak için de CompressorRater‘i kullanabilirsiniz. İlk iki uygulamayı Steve Souders’ın geliştirdiğini de belirteyim.

Telvee Deneyi

Telvee için başlangıçta performansı hiç düşünmemiştim. Çok sayıda CSS dosyası ve yine çok sayıda resim yükleniyordu. İyileştirmelerden önce aldığım ölçümler aşağıdaki gibiydi:

 İstek #Veri boyutu (KB)
Anasayfa25~85
Fincan Detay48~80

Daha sonra projeye django_compressor‘u ekledim ve gerekli ayarlamaları yaptım. Hem JavaScript hem de CSS için YUI Compressor’u kullandım. Sprite’ları elle hazırlayıp, CSS dosyalarında gerekli değişiklikleri yaptım1. Daha sonra değişiklikleri sunucuya yükleyip tekrar ölçtüm:

 İstek #Veri boyutu (KB)
Anasayfa12~70 (~160)
Fincan Detay14~64

Anasayfanın veri boyutu kolonunda yazan parantez içindeki değer gerçek sonuç. Ancak bu güncellemeyle anasayfanın tasarımı da değişti ve daha önce yüklenmeyen 90 KB’lık bir dosya eklendi. Bu nedenle sonucu 70 KB olarak kabul etmek yanlış olmayacaktır. İyileştirmelerin sonucu aşağıdaki gibi:

 İstek #Veri boyutu (KB)
Anasayfa%52%17
Fincan Detay%70%19

Django_compressor ve Data URI’ler

Christian Metts tarafından geliştirilen django_compressor yukarıda bahsettiğim iyileştirmeleri Django projelerinize kolayca uygulamanızı sağlıyor. Birkaç değişik çatalı birleştirip ufak eklemeler yaptığım depoya buradan ulaşabilirsiniz.

Bu depoda data-uri branşındaki compressor.filters.datauri.CssDataUriFilter filtresini kullanarak bağlantılı dosyalarınızı CSS dosyalarınızın içine gömebilirsiniz. Varsayılan ayarlara göre sadece 1024 Byte (1 KB) veya daha küçük boyuttaki dosyalar gömülecek, diğerleri bağlantılı olarak kalacaktır. COMPRESS_DATA_URI_MIN_SIZE ayarını kullanarak gömülecek dosyaların sınırını değiştirebilirsiniz.

Dosyalarınızı data: URI‘lere dönüştürürken dikkat etmeniz gereken birkaç nokta var. Her şeyden önce dosya içeriği base64 kodlanıyor, yani veri boyutu yaklaşık üçte bir oranında artacaktır. Bant genişliği ile HTTP istek adedi arasındaki dengeyi düşünerek karar vermek size kalıyor2. Sorun yaratabilecek bir diğer şey; aynı dosyaya birden fazla kereler atıfta bulunulursa tüm dosya her seferinde tekrar tekrar gömülecektir. Bu sorunun çözümü tüm atıfları birleştirip tek bir bağlantıda toplamak3 ancak bunun da CSS dosyalarınızı tasnif ettiğiniz sistemi bozma ihtimali var.

Django_compressor’un Data: URI desteğini test edip, görüş ve önerilerinizi bana iletirseniz sevinirim. Eğer uygulamadıysanız yazıda belirttiğim teknikleri sitelerinize uygulamanızı tavsiye ederim. Özellikle, django_compressor sayesinde, Django projelerinde bu iyileştirmeleri yapmak çok basit. Sonuçta, teknoloji meraklıları olarak, performans artışının hoşunuza gideceğinden de eminim.


1: İleride django_compressor’a sprite’ları otomatik oluşturma özelliğini eklemeyi düşünüyorum.

2: Modern Internet bağlantıları söz konusu olduğunda 1~2 KB’lık artışın karşılığında HTTP isteklerini bir azaltmak daha avantajlı görünüyor.

3: http://meiert.com/en/blog/20090401/why-css-needs-no-variables/

Tags: , , , ,

Cuma, Şubat 19th, 2010 Internet Sektörü, Yazılım Yorumlar kapalı

Etohum’un 2010 Yılında Destekleyeceği 15 Girişim Açıklandı

Etohum‘da bu yıl desteklenecek 15 girişimin ilan edildiği haftasonu toplantısı bugün Bahçeşehir Üniversitesi’nin Beşiktaş’taki kampüsünde gerçekleştirildi. Yapılan sunumları, özellikle Airties’ın kurucusu Ziya Boyacıgiller’in sunumunu, biryerlerden bulup izlemenizi tavsiye ederim.

Açıklanan 15 girişim içerisinde benim ilgimi çeken 2 tanesi hakkında birşeyler yazmak istedim.

Dressar.com

Bir artırılmış gerçeklik uygulaması olan Dressar.com, çok basit bir ifadeyle canlı yayında üzerinize sanal bir elbise giydiriyor. Hareketlerinizi takip eden bir kamera ve ayna gibi yerleştirilmiş bir ekrana seçtiğiniz giysiler eklenmiş halde görüntünüz yansıtılıyor. Siteyi ziyaret ederseniz oradaki görseller daha iyi anlatabilir.

Bu girişimin seçilmesi beni mutlu etti; çünkü bir teknoloji girişimi. Ama aynı zamanda çok başarılı olabilecek, çok geniş kitlelerin kullanabileceği bir uygulama. Düşünün ki kabine girip, üzerinizdekileri çıkarıp, deneyeceklerinizi giyip, sonra bunları tekrarlamak yerine ekranda birkaç yere tıkladıktan sonra giysilerin üzerinizde nasıl duracağını görebileceksiniz. Alışveriş fobisi olan biri olarak benim yaşam standartımı yükselteceği kesin :D

Nefius.com

Aslında Nefius.com’u henüz anlayabilmiş değilim. İddiası çok fazla buzzword içerdiği için burada tekrarlamak istemiyorum. Siteye girip siz anlamaya çalışın, sonra bana da anlatırsınız.

Ama bu dönemde takip edeceğim ikinci girişim Nefius olacaktır. Kurucusu Fatih Bugan kısa ama güzel bir sunum yaptı, ben ne yaptığını bildiği izlenimini edindim. Umarım kısa zamanda amaçladıklarını gerçekleştirir. Bir teknoloji girişiminin başarılı olmasından büyük mutluluk duyarım.

Bunların dışında sağlam proje olarak Filoline.net var. Filoline.net’in sitesini biraz inceledim, buradan küçük bir öneride bulunmak istiyorum. Uygulamalarının küçük resimlerine tıklandığında açılacak ekran görüntülerini koyarlarsa herhangi birşey kaybetmeyecekleri gibi sosyal medya anmaları gibi kazançları olur.

Tüm etohum girişimlerine başarılar diliyorum.

Tags: , , ,

Cumartesi, Ocak 30th, 2010 Internet Sektörü Yorumlar kapalı

Django: Bir Güncelleme Hikayesi

Internet üzerinde MVC web çerçeveleri kullanılarak sıfırdan uygulamalar geliştirmek üzerine bir çok makale var. Ben bu yazıda Django ile geliştirilmiş ve çevrimiçi olan bir siteye yeni özellik eklemeyi detaylı olarak anlatmak istiyorum. Amacım Django’nun mevcut uygulamalar üzerinde değişiklik yaparken sağladığı esneklik hakkında fikir vermek. Bir yandan da, küçük de olsa, gerçek hayatta kullanılan bir parça kodu göstermek.

Nakliyeci Rehberi, nakliye sektörüne hizmet veren bir firma rehberi. Ayrıca söktörel haberler ve ilanlara da yer veriliyor. Fakat ana özellik firma rehberi. Aşağıda anlatacağım güncellemede firmaların listelendiği sayfaların altına, arama motoru optimizasyonu için, açıklayıcı yazılar yerleştirilmek istendi. Bu yazıların dinamik olarak, sadece istenen şehirler için, eklenip çıkarılabilmesi gerekiyordu. Bir örnek için İstanbul Evden Eve Nakliyat Firmaları sayfasına bakabilirsiniz.

Plan basitçe iki maddede özetlenebilir:

  • Girdi: tanıtıcı yazı için bir model oluşturulması ve admin uygulamasıyla entegrasyonu.
  • Çıktı: bir şablon komutu (template tag) ile istenen tanıtıcı yazının çağrılması.

Model ve Admin

Modelimiz oldukça basit. Her bir şehir ve kategori için yalnızca bir tane tanıtım yazısı yaratılabilsin diye unique_together kullandım.

import datetime
from django.db import models


CATEGORY_CHOICES = (
    ('domestic', u'Evden Eve Nakliyat'),
    ('commercial', u'Nakliye ve Lojistik'),
)


class IntroductoryText(models.Model):
    city = models.CharField(u'Şehir', blank=False, unique=True)
    category = models.CharField(u'Kategori',
                                choices=CATEGORY_CHOICES,
                                max_length=20)
    introduction = models.TextField(u'Tanıtım Yazısı', blank=False)
    creation_timestamp = models.DateTimeField(u'Yaratılma Tarihi',
                                default=datetime.datetime.now, editable=False)
    class Meta:
        verbose_name = u'Şehir Tanıtımı'
        verbose_name_plural = u'Şehir Tanıtımları'
        unique_together = (('city', 'category'),)
        ordering = ('city',)

    def __unicode__(self):
        return u'%s %s tanıtımı' % (self.get_city_display(),
                                    self.get_category_display())

    @models.permalink
    def get_absolute_url(self):
        return ('catalogue-city-category',
                (),
                {'city_slug': slugify(self.get_city_display()),
                 'category_slug': slugify(self.get_category_display())})

Burada Türkçe karakterleri de destekleyen kendi slugify fonksiyonumu kullanıyorum.

Daha sonra admin.py içine IntroductoryText için gerekli tanımları ekledim:

from django.contrib import admin
from models import IntroductoryText


class IntroductoryTextAdmin(admin.ModelAdmin):
    list_display = ('city', 'category', 'creation_timestamp')
    list_filter= ('category', 'city')
    radio_fields = {'category': admin.VERTICAL}
admin.site.register(IntroductoryText, IntroductoryTextAdmin)

Böylelikle güncellemenin girdi kısmı tamamlandı.

Şablon Düzenlemeleri

Tanıtım yazılarını göstermek için çok baist bir şablon kumutu tanımlam yeterli oldu:

from django import template
from django.contrib.markup.templatetags.markup import markdown
from catalogue.models import Company, IntroductoryText


register = template.Library()


@register.simple_tag
def city_introduction(city_id, category_id):
    try:
        i = IntroductoryText.objects.get(city=city_id, category=category_id)
    except IntroductoryText.DoesNotExist:
        return u''
    return markdown(i.introduction)

Eğer verilen parametreler için tanıtım yazısı bulunamazsa, ki daha önce belirttiğim gibi her şehir için tanıtım yazısı olmayabilir, şablona boş metin döndürülüyor.

Tanıtım yazılarını görüntülemek için catalogue/company_list.html şablonuna aşağıdaki kodu ekledim:

<div>{% city_introduction city_id category_id %}</div>

Sonuç

Bu çok basit güncellemeyi mevcut kodlar üzerinde hiçbir değişiklik yapmadan sadece yeni kodları ekleyerek gerçekleştirdim. Bu yeni kodları sunucuya yükledikten sonra veritabanında IntroductoryText ile ilgili tablonun yaratılması için son olarak syncdb komutunu çalıştırdım.

./manage.py syncdb

Bu kadarı yeni özelliğin eklenmesi için yeterli olsa da önemli bir eksiklik var; en azından city_introduction şablon komutu için testlerin yazılması gerekiyor. Django ile geliştirme diğer antik geliştirme ortamlarına göre o kadar çevik ki emin olun testleri hazırlamak kazanılan zamanın çok ufak bir kısmını alacaktır.

Umarım bu yazı Django öğrenenlere veya öğrenmek isteyenlere yardımcı olur.

Tags: , ,

Çarşamba, Ekim 21st, 2009 Yazılım Yorumlar kapalı

Internet Girişimcileri Internet Sansürüne Karşı

Dün gerçekleştirilen, yeni sezonun ilk etohum toplantısında konuklar Ortakantin kurucuları ve grou.ps‘dan Emre Sokullu‘ydu.

Ortakantin sunumundan sonra kürsüye çıkan Emre Sokullu kendi konuşmasına başlamadan önce ortaya bir fikir attı. Daha doğrusu bir öneride bulundu:

Teknolojik uçurumun diğer tarafında bulunanların dikkatini Internet yasaklarına çekmek için Google’a karşı bir kapatma davası açalım.1

Sonrasında da yarım saatten uzun sürecek olan bir tartışma başladı. Biz Türkler tartışmayı çok mu seviyoruz yoksa sorumluluk almaktan korktuğumuz için mi tartışmanın hiç bitmemesini istiyoruz karar veremedim. Birçok değişik şey konuşuldu ama kendini tekrarlayan bir kalıp dikkatimi çekti. Sanki konuşulan kelimeler havada değişime uğrayıp benim kulağıma şöyle ulaşıyordu:

Senin önermelerini bütün olarak reddediyorum ve yapıcı öneriler getirmeye çalışmak yerine tartışmayı rayından biraz daha çıkarabileceğini düşündüğüm gereksiz detaylarla konuşmama devam ediyorum.

Bu tabii kendi algılamam, bu konuda yanılmaktan mutlu olurum. Ama söylenenlerin bir kısmı da en katıksız haliyle saçmalıkdı.

Vay efendim Atatürk’e yönelik hakaret içeren videolara karşı hoşgörülü olmadımız için Youtube açılsa bile yine kapattırırmışız. Atatürk’e yönelik hakaretlere hoşgörülü olmamız herhangi bir sorunumuzu çözer mi? Kaldı ki ülkemizin kurucusuna hakaret edilmesini neden hoşgörüyle karşılayalım? Böyle birşeyi elbette kabullenemeyiz. Tepkimizi dile getirmek sorumluluğumuzdur.2

Youtube’u kapatarak da Devletimiz, kanunlar çerçevesinde, tepkisini ifade ediyor. Ama ne yazık ki bunu akla gelebilecek en kötü biçimde gerçekleştiriyor.

  1. Bu cezalandırma şekli suçludan çok mağduru cezalandırıyor. Eğer bir Internet sitesi suç unsurları içeriyorsa o sitenin Internet erişimi engellenir.3 Fakat burada Türk Internet kullanıcısının erişimi engelleniyor ve özgürlüğü kısıtlanıyor. Detay gibi görünse de üzerinde durmamız gereken, herkese anlatmamız gereken esas nokta bu. Bir yaptırım uygulanacaksa kusurlu taraflara uygulanmalı.
  2. Türk Internet kullanıcısının erişimi engellendiği için, örneğin bize yönelik hakaretlere karşılık gerekli cevabı medeni bir biçimde veremiyoruz. Oysa ki, Youtube örneğinde gerek yazacağımız yorumlarla gerek site yetkilileriyle kuracağımız birebir iletişimle daha iyi sonuçlar alabilirdik. Ama biz iletişimsizlik yolunu tercih ettik. Bir anlamda haklı iken haksız duruma düştük. Olgun davranamadık.
  3. Bu yasaklar, yabancıların gözünde bizi küçük düşürüyor. Zaten böyle bir olay olmasa da yabancı medyanın ve siyasilerin büyük çoğunluğu bizi barbar gibi, ne bileyim çölde yaşayan bedeviler gibi görmeye ve göstermeye dünden hazır. Biz de onlara böyle malzeme üretiyoruz.

Tartışmalar sürerken birileri “siyasileri de sürecin içine katalım” dedi fakat Emre Sokullu buna şiddetle karşı çıktı. Bunun nedenlerini anlamak çok zor değil. Yine de ben siyasilerle birlikte hareket etmenin çok da kötü bir fikir olmadığını düşünüyorum. Belki büyük ve hantal partiler değil. Ama bireyselliği ön plana çıkaran liberal partilerin bu konuya ciddiyetle yaklaşması gerekiyor. Tabii eğer pankart açıp yürüyüş yapmaktan fırsat bulabilirlerse. Bu tür eylemlerin bir önceki yüzyılda kaldığını artık insanları harekete geçiremediklerini ne zaman anlayacaklar acaba? İşte size gerçek birşeyler başarma fırsatı.

Google’ı kapatmak çözüm olur mu? Bu sorunun cevabını bilmiyorum. Kimsenin de kesin olarak “hayır, hiçbir işe yaramaz” diyebileceğini sanmıyorum. Denememek için hiçbir sebep yok. Basın M.K. cinayetine gösterdiği ilginin onda birini gösterse bile bu çok büyük bir farkındalık yaratabilir, yeter ki kendimizi iyi anlatalım.

Fakat sanıyorum etohum toplantısındaki kitleyi bu konuda harekete geçirmek için sanırım önce FriendFeed‘in kapatılması gerekiyor.


1: Bunlar kendi sözleri değil, benim özetim.

2: Bu görüşü dile getiren bayan 5 yıl Amerika’da yaşadığını üstüne basa basa belirtti. Demek ki 5 yıl hoşgörüsüz düşüncelere de hoşgörülü olunması gerektiğini öğrenmek için yeterli olamayabiliyormuş.

3: Bunun yapılabilirliği ayrı bir tartışma konusu. Yabancı siteler için uluslararası hukuk çerçevesinde çözüm yolları aranabilir. Önemli olan bir hatanın başka bir hata ile giderilmeye çalışılmaması.

Tags: , ,

Cuma, Eylül 25th, 2009 Internet Sektörü Yorumlar kapalı

Django-formfieldset 1.0.0

Django-formfieldset, Django üzerinde formlarınızı admin uygulamasındaki gibi bölümlere (fieldset) ayırarak görüntülemenizi sağlayan bir eklentidir. BSD lisansına sahip yazılımın ilk sürümünü buradan indirip kullanabilirsiniz.

formfieldset eklentisini denemenin en hızlı yolu, depodaki örnek uygulamayı çalıştırmaktır1:

django- formfieldset$ cd example
example$ python manage.py runserver

Bu komutları girdikten sonra örnek uygulama http://localhost:8000/ adresinde çalışmaya başlayacaktır.


1: Örnek uygulama 1.0.0 kaynak pakedine dahi değildir. git://github.com/muhuk/django-formfieldset.git adresindeki git deposunu klonlayarak örnek uygulamayı indirebilirsiniz.

Tags: , , ,

Perşembe, Haziran 4th, 2009 Yazılım Yorumlar kapalı

GeoDjango İle Coğrafik Destekli Web Uygulamaları

GeoDjango, açık kaynaklı coğrafi veri işleme yazılımlarının desteğiyle uygulamalarınızda coğrafik verilerin saklanması, düzenlenmesi ve sunulmasını kolaylaştırıyor.

Örneğin GeoDjango destekli bir model kullanarak bir alanı, diyelim ki Ege Bölgesi, veritabanınızda saklayabilir ve daha sonra istediğiniz formatta yayınlamak üzere çağırabilirsiniz. Hatta admin‘i kullanarak coğrafik verilerinizi görsel olarak (harita üzerinde) düzenlemeniz mümkün.

Daha fazla bilgi için GeoDjango dökümantasyonunu inceleyebilirsiniz.

Tags: , , ,

Çarşamba, Mayıs 20th, 2009 Yazılım Yorumlar kapalı

Merhaba!

Ölçgen Bilişim blogu.

Tags:

Çarşamba, Mayıs 6th, 2009 Internet Sektörü Yorumlar kapalı