Fırat Esmer

ANLATILAN SENİN HİKAYENDİR - KARL MARX

CSS Sprite Kullanımı (HTTP İstek Sayısını Azaltarak Performans Artışı Sağlama)

Yeni bir ASP.NET performans makalesi ile karşınızdayım. Bu makalede, web uygulamamızdaki bir image üzerinden css koordinat (sprite) yöntemiyle nasıl birden fazla image'e yol verilir ve bu yöntemin avantajları nedir, kısaca açıklamalar yapacağım.

Facebook'ta bulunan küçük resimlerin  (durum, bağlantı, fotoğraf gibi) kaynağını incelediğinizde karşınıza şöyle bir resim çıkacak :

Facebook Resimleri

Gördüğünüz gibi tek büyük bir resim var. Bu tek büyük resim üzerinden parçalar alınarak, Facebook'ta bulunan diğer kesitlere image yolları veriliyor. Yapılan işlem aslında çok basit ve bir o kadar da kazançlı. Yöntem, tek resim üzerinden x ve y koordinatları verilerek diğer resimlere yol verilmesi işleminden ibaret aslında. Bu işlemi uygulayan tek şirket Facebook değil. Google Reader, Ask, µTorrent,Telerik bunlara örnek. Gelelim önemli iki noktaya. Neden böyle bir yola başvuruyoruz ve nasıl yapıyoruz?

Neden?

Sunucuya gönderilen istek sayısı azalıyor.

Eğer her resim için tek tek yol verseydiniz, bu her yol için sunucuya istek gönderilecekti. Ancak bir resim üzerinden koordinat yöntemiyle birden fazla resme yol verirseniz, sadece tek istek (büyük resim için) gidecekti. Sunucuya giden her istek tepki süresinin uzaması ve kullanıcının beklemesi demektir. Belki de koordinat yöntemiyle sunucuya giden istek sayısını azaltarak en kolay performans artışını sağlayacağız.


HTML Diğer
Yahoo! %10 %90
Google %25 %75
MySpace %9 %91
MSN %5 %95
eBay %5 %95
Amazon %38 %62
Youtube %9 %91
CNN %15 %85

Yahoo! User Interface Blog sitesinin, "Performance Research, Part 1: What the 80/20 Rule Tells Us about Reducing HTTP Requests" adlı makalesinden alıntıdır. Not : Yukarıdaki değerler, cache varsayılmadan ve ortalama 2.5 Mbps internet bağlantı hızının test sonuçlarıdır.

Yukarıdaki tablo popüler bir kaç web sitesinin sayfaları oluşturulurken harcadıkları zamanı gösteriyor. HTML belgesinin indirilmesi %5 ile %38 arasında zaman alırken, diğer parçaları (resimler, script ve style dosyaları) yüklemek %62 ile %95 arasında değişiyor. Yani HTTP istek sayısının azaltılmasıyla, gözle görünür seviyede performans artışı yaşayabiliriz. (İstatistiki bilgiler kullanıcının tarayıcı modeline ve gönderilen isteğe göre değişebilir.)

Tek resim daha az yer kaplıyor.

Birden fazla resmin kullanımı, tek bir resmin kullanımından daha dezavantajlıdır. Bunun en somut örneği; tek resmin boyutunun, diğer parçalar halinde kullanılan resimlerin boyutundan küçük olmasıdır. Böylece sayfayı yüklemek isteyen kullanıcılar daha az indirme işlemi yapıcak ve daha az bekleyeceklerdir.

Nasıl?

İşlemi 2'ye böleceğim. İlkinde resimlerin yolunu tek tek resimlerden çağırıp, sonucu inceleyeceğiz. İkincisinde ise resimlerin yollarını tek bir resimden çekip inceleyeceğiz. İncelemenin sonunda ne kazanıp, ne kaybettiğimizi analiz edip, konuyu kapatacağız (:

İLK HALİ

Bir adet table içerisine yaklaşık 9 tane kolon yerleştireceğim ve bu her kolonun içerisine CSS dosyasından resim ekleyeceğim. CSS dosyamız kısaca şöyle görünecek :

#koordinat a.item1

{

/*Direkt olarak resmin yolunu veriyoruz.*/

background-image: url(../image/image_1.png);

background-repeat: no-repeat;

margin-bottom: 30px;

}

#koordinat a.item2

{

background-image: url(../image/image_2.png);

background-repeat: no-repeat;

margin-bottom: 30px;

}

HTML tarafındaki a.item denilen kısım ise aşağıdaki gibi görünecektir.

<a class="item1" href="#" title="Gruplar">Gruplar</a>

İlk olarak buraya tıklayıp demo'yu inceleyin. Kaynak koduna bakın, öğeleri teftiş edin. Hatta HttpWatch adlı programa sahip değilseniz, buradan indirin. HttpWatch adlı program, kullanmak istediğiniz sayfanın sunucu ile ilişkisini bize detaylı bir şekilde gösterir. Bizim burada programı kullanma amacımız sunucuya kaç adet HTTP isteğinin gideceği ve tepki süresinin ne kadar süreceğini göreceğiz.

Demo'nun ekran görüntüsünü, analiziyle beraber görmek için buraya tıklayın!

Resimlerin yolunu tek tek verdiğimizde ortaya çıkan sonuç : 11 HTTP istek, 0.520 saniyelik sayfa yüklenme süresi ve 2,44KB resim dosyası boyutu.

SON HALİ

Şimdi yapacağımız işlemin, diğer örnektekinden farkı ufak dilimlere bölünmüş resim yerine hepsinin yer aldığı tek bir resim kullanmak ve CSS dosyamıda değişiklik yapmak. CSS dosyamızdaki değişiklik şöyle olacak :

#koordinat a

{

/*Bu sefer küçük resimlerin toplandığı büyük resmin yolunu veriyoruz.*/

background-image: url(../image/facebook.png);

background-repeat: no-repeat;

padding: 0 0 0 90px;

display: block;

height: 16px;

font-family:Tahoma;

}

#koordinat a.item1

{

background-position: 30px 0px;

margin-bottom: 30px;

}

#koordinat a.item2

{

/*Aşağıda yazılan css şunu açıklıyor : kesiti alınacak resmin x ve y koordinatlarını veriyoruz. Büyük resmimiz yukarıdan aşağıya olduğu için x koordinatı sabit, y ise belli aralıklarla eksi yönünde gidiyor. */

background-position: 30px -18px;

margin-bottom: 30px;

}

Web uygulamamızın son halinin demosunu görmek için buraya tıklayıp, diğer örnekte olduğu gibi inceleyin. Resimlerin tek bir resimden geldiğini göreceksiniz.

Demo'nun ekran görüntüsünü, analiziyle beraber görmek için buraya tıklayın!

Resimlerin yolunu tek bir resimden çektiğimizde çıkan sonuç : 3 HTTP istek, 0.132 saniyelik sayfa yüklenme süresi ve 1,19KB resim dosyası boyutu.

Gözle görülür şekilde performans artışı bu olsa gerek. Makalede geçen iki demo'nun da tek bir yerde toplanmış halini indirmek istiyorsanız buraya tıklayın (.NET Framework 3.5 ve Visual Studio 2010 ile hazırlandı). Yardımlarını esirgemeyen George'a teşekkürler (:

Yorumlar (12) -

  • George Diril

    29.6.2011 01:50:01 | Yanıtla

    Bize böyle önemli bir konuyu açıkladığın için ben sana teşekkür ederim.

  • Erkan

    26.8.2011 01:13:57 | Yanıtla

    Fırat Bey dün okuduğum bir makale sonucu css sprite ile tanıştım. Sizin örneğinizi de inceledim. Hazırladığım sayfada bu tekniği uygulamak istiyorum ama repeat-x yaptıramadım.
    Aşağıdaki  örnek üzerinde deneme yapıyorum alt_01 ve 03 sabit, alt 02 deki resim x eksini boyunca tekrarlanacak.

    #hea td { background: url(../images/fiximage.png) top left;}
    #hea .alt_01{ background-position: 0 0; width: 22px; height: 85px; }
    #hea .alt_02{ background-position: 0 -90px; width: 10px; height: 85px; }
    #hea .alt_03{ background-position: 0 -180px; width: 18px; height: 85px; }

    <table id="hea" width="100%" border="0" cellspacing="0" cellpadding="0">
      <tr>
        <td width="1%" class="alt_03"></td>
        <td width="97%" align="center"  class="alt_02">deneme</td>
        <td width="2%" class="alt_01"></td>
      </tr>
    </table>

    • Fırat Esmer

      28.8.2011 16:48:14 | Yanıtla

      Merhaba Erkan Bey, öncelikle yazmış olduğunuz yoruma geç cevap verdiğim için özür diliyorum. Sorunuza gelirsek, "alt_02" isimli class'a "background-repeat: x;" cümlesini ekleyip bana sonuç hakkında dönüş yapar mısınız? Ayrıca "fiximage" isimli resmin boyutunu da öğrenebilir miyim? Çünkü background-position'lara boyut vermişsiniz.

      • Erkan

        30.8.2011 13:59:46 | Yanıtla

        Fırat Bey rica ederim.
        fiximage 390X1000 px boyutunda.   alt_02 nin width değerini kaldırıp denedim yükseklik ve alçaklık değerini kaldırınca arkaplan resmi bozuluyor. Ayrıca background-repeat: repeat-x;  ile tekrarlamasını istedim. Tekrarlıyor fakat  dolgu olarak değil seyrek seyrek oluyor. Biraz araştırdım. ust_02 alanı için imageyi td boyunca uzutmam önerildi  td boyu 500px e yakın olduğundan boyut artacaktı bende vaz geçtim   alt_02 clasına bağımsız background atayım geçtim. Çalışmayı sonlandırdım.

        Fakat hala aklım burda kaldı Smile
        Aşağıdaki örnek bir resim ekledim. Zamanınız olursa bu resimdeki { background-position: 0 0; } daki resmi 500 px lik td boyunca tekrarlatabilir miyiz?
        http://www.erkanerbas.com/a/aciklama/r1.png

        İlginiz için teşekkür ederim. İyi bayramlar.

        • Fırat Esmer

          30.8.2011 16:48:14 | Yanıtla

          Merhaba Erkan Bey,
          İstediğiniz örnek uygulamayı hazırladım. 3 farklı resimden oluşan resmi 500px'lik bir td'de yatay olarak tekrarlattım. Örnek uygulamaya www.firatesmer.com/.../sayfa.htm sayfasından göz atabilirsiniz. Eğer örnek uygulamayı indirmek isterseniz bu sayfayı ziyaret et : www.firatesmer.com/file.axd
          Konuştuğumuz gibi sadece "background-repeat: no-repeat;" ifadesini kaldırdım. Eğer örnek uygulamam kafanızdaki soru işaretlerini gidermez ya da sizi tatmin etmezse lütfen sorun. İlginiz için ben teşekkür ederim, iyi bayramlar. Smile

          • Erkan

            4.9.2011 23:41:51 | Yanıtla

            Örneği inceledim. Tam olarak almak istediğim sonuç   yukarıdaki iletilerde verdiğim r1.png resmi kullanarak
            aşağıdaki resmin  üst kısmı gibi bir sonuç almaktı.
            http://img43.imageshack.us/img43/9171/dolgu.jpg
            Sizin örneğinizde seyrek seyrek gözüküyor ki bu görünüş benim işimi görmüyor.
            Saygılar.

            • George Diril

              7.9.2011 02:48:07 | Yanıtla

              Erkan Bey merhabalar,

              Demek istediğinizi çok iyi anlıyorum. Sunmuş olduğunuz görselin üst kısmındaki koyu alanı arada hiç bir beyazlık kalmadan tekrarlanması istiyorsunuz. Yalnız CSS (2.0 ve 3.0 dahii ) bu konuda ihtiyacınızı karşılamaz. CSS Sprite özelliği; bir görselin istediğiniz bir bölümünü almaya yarar. Ama aldığınız bu kısmı tekrarlatamazsınız. JavaScript'e pek hakim olmamakla beraber bu isteğinizi çözebileceğini düşünüyorum.

              İyi Çalışmalar.

              • Fırat Esmer

                7.9.2011 16:25:47 | Yanıtla

                Yukarıda tekrarlanması için sunulmuş olan resmin sağ tarafında beyazlık olduğu için yaptığım örnekle uyuşmuyor zaten. Aşağıdaki yuvarlak iki resim beyaz boşluğa sebebiyet veriyor.  Tek başına siyah kısmı alabilir ancak tekrarlatamazsınız diye düşünüyorum ben de.

  • Erkan

    12.9.2011 02:27:29 | Yanıtla

    George Diril, Firat Esmer belirttiğiniz gibi css scripte ile istediğim gibi tekrarlatmak mümkün değilmiş. İnşallah css geliştiricileri bu özelliği sonraki sürümlerde dikkate alırlar.
    İlginiz için teşekkür ederim.

Yorum ekle

Loading