Smarty, PHPTAL ve performans konusunda düşündürdükleri
Baştan belirteyim, bu yazının amacı template engine (şablon motoru) kullanmayalım ya da performans için her türlü işe yarar objelerden, frameworklerden, component ve yaklaşımlardan uzak duralım değildir. Performans önemli bir konudur ama bir web uygulamasının üretilmesi, üretildikten sonra rahat ve esnek bir biçimde geliştirilebilmesi, vb. de ciddi şekilde önemli konulardır.
Fakat en son Facebook ekibinin HipHop ve XHP gibi konuları gündeme getirmesinden sonra PHP kodlarının performansı üzerinde tekrardan düşünmeye başladım. PHP performansı deyince de ilk aklıma gelen konulardan birisi smarty ve PHPTAL gibi şablon motorlarının kullanımı oldu. Acaba bu şablon motorları ne kadar hızlı çalışıyor diye test etmek istedim.
Smarty uzun süredir kullandığım fakat son dönemlerde gerekliliğini ve yeterliliğini sorguladığım bir şablon motoru benim için. Hatta kim bana şimdi “Smarty mi kullanalım, direkt PHP mi yazalım HTML tagleri arasına?” diye sorsa bir saniye bile düşünmeden “PHP yazın” derim. Zira Smarty hakikaten HTML arasında PHP yazmaktan öte çok fazla bir iş yapmıyor. Compile, cache gibi yapıları ise aslında maksimum birkaç saat içinde hem de daha iyi bir şekilde sıfırdan yazabileceğiniz türden şeyler. Bugüne kadar biraz ciddi bir alternatifi olmamasından biraz da back-end kod ve yapılarının tasarımdan ayrılmasına inandığımız için Smarty’i kullanmış idik. Şimdiler de ismi çok duymaya başladığım PHPTAL gibi daha düzgün bir alternatif mevcut. PHPTAL’ı kullananların anlattığı ve kendi dökümanlarına göz attığımda gördüklerim kadar tanıyorum aslında. Yani çok ciddi bir tecrübem yok PHPTAL ile ilgili. Ama bundan sonrasında bir proje için Smarty yerine kullanmayı düşündüğüm bir şablon motorudur. Bu nedenle de Smarty’nin ne kadar hızlı çalıştığını merak ederken PHPTAL’ı da bu merakıma dahil etmiş oldum.
Bu şablon motorlarının, HTML içine PHP kodu yazarak hazırlanan bir sayfayı oluşturma konusunda ne kadar hızlı olduklarını test etmek istedim. Ama öyle ciddi bir test ortamı ve test planı hazırlamadım. Amacım sadece fikir edinmek olduğu için birkaç satır PHP kodu, birkaç satırlık HTML fikir vermek için yeterli olur diye düşündüm. PHP kodunda yapacağım işlem, bir metni boşluk karakterlerinden bölerek bir diziye (array) atmak ve bu dizideki her bir elemanın HTML içinde div içinde bir span olarak oluşturulmasını sağlamaktı. Aşağıda Smarty, PHPTAL için yazdığım şablon (template) kodlarını inceleyebilirsiniz.
Smarty için (test.tpl) :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Test Page</title> </head> <body> {section name=word loop=$words} <div> <span>{$words[word]}</span> </div> {/section} </body> </html>
PHPTAL için (test.xhtml) :
<?xml version="1.0"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Test Page</title> </head> <body> <div tal:repeat="word words"> <span tal:content="word">Word</span> </div> </body> </html>
Şablon motorlarını çağıran PHP kodlarını da aşağıda iletiyorum. En sonda ilettiğim PHP kodu ise şablon motoru kullanmadan aynı kodu üreten bir kod. Bu kodla ilgili sonuçları da “Pure PHP” başlığı ile ileteceğim.
Smarty için PHP kodu (smarty.php) :
<? require './../Smarty-2.6.26/libs/Smarty.class.php'; $smarty = new Smarty; $text = 'Fusce ut faucibus quam. Duis nisl dui, malesuada porta mattis sed, ultricies a odio. Nunc ornare aliquet tortor, eget semper nibh ultricies nec. Aliquam venenatis arcu sed ligula mattis quis aliquam enim ullamcorper. Quisque ligula libero, porttitor sed pellentesque eget, iaculis ac neque. Aliquam erat volutpat. Suspendisse potenti. Quisque elementum vulputate sodales. Sed vel massa sollicitudin erat consectetur porta ut auctor justo. Sed eget hendrerit massa. Mauris magna quam, suscipit convallis adipiscing quis, luctus eu mi.'; $data = explode(' ', $text); $smarty->assign('words', $data); $smarty->display('test.tpl'); ?>
PHPTAL için PHP kodu (phptal.php) :
<? require_once './../PHPTAL-1.2.1/PHPTAL.php'; $template = new PHPTAL('test.xhtml'); $text = 'Fusce ut faucibus quam. Duis nisl dui, malesuada porta mattis sed, ultricies a odio. Nunc ornare aliquet tortor, eget semper nibh ultricies nec. Aliquam venenatis arcu sed ligula mattis quis aliquam enim ullamcorper. Quisque ligula libero, porttitor sed pellentesque eget, iaculis ac neque. Aliquam erat volutpat. Suspendisse potenti. Quisque elementum vulputate sodales. Sed vel massa sollicitudin erat consectetur porta ut auctor justo. Sed eget hendrerit massa. Mauris magna quam, suscipit convallis adipiscing quis, luctus eu mi.'; $data = explode(' ', $text); $template->words = $data; try { echo $template->execute(); } catch (Exception $e){ echo $e; } ?>
Sadece PHP ile çalışacak versiyon için (phptest.php) :
<? $text = 'Fusce ut faucibus quam. Duis nisl dui, malesuada porta mattis sed, ultricies a odio. Nunc ornare aliquet tortor, eget semper nibh ultricies nec. Aliquam venenatis arcu sed ligula mattis quis aliquam enim ullamcorper. Quisque ligula libero, porttitor sed pellentesque eget, iaculis ac neque. Aliquam erat volutpat. Suspendisse potenti. Quisque elementum vulputate sodales. Sed vel massa sollicitudin erat consectetur porta ut auctor justo. Sed eget hendrerit massa. Mauris magna quam, suscipit convallis adipiscing quis, luctus eu mi.'; $data = explode(' ', $text); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Test Page</title> </head> <body> <? foreach ($data as $word) : ?> <div> <span><?= $word?></span> </div> <? endforeach; ?> </body> </html>
Test için kullandığım şablon motorlarının versiyonları : Smarty-2.6.26, PHPTAL-1.2.1.
Web sunucusu olarak lighttpd-1.4.22 + PHP-cgi (mod_fastcgi) kullandım ve PHP versiyonu PHP 5.2.10-2.
Kullandığım bilgisayarın özellikleri ise : Intel(R) Pentium(R) Dual CPU E2180 @ 2.00GHz (1 MB Cache), 2 GB Ram.
İşletim Sistemi : Ubuntu 9.10
Toplamda 2 farklı test yaptım. Test ederken amacım yüksek yoğunluk altında bir performans ölçümü yapabilmek olduğu için keep-alive kullanmadım ve aynı andalık (concurrency) seviyesini 500, test süresini de 30 saniye olarak ayarladım. İlk testte yukarıda $data değişkenini aynen kullanırken, ikinci testte şablon motorlarının ürettiği HTML miktarını ciddi şekilde artırmak için $data değişkeni içindeki metni 15 kez yan yana kopyalayarak $data olarak kullandığım. Yani $data metninin boyutu 15 kat artmış oldu. Dolayısıyla ikinci test için sadece metin boyutunu değiştirmiş oldum. PHP kodunda kullandığım explode işlemi de aslında ikinci testte daha uzun sürüyor olmalı biliyorum ama tüm test edilecek kodlarda aynen geçtiği için süreyi artırsa da sonuçlar arasındaki kıyaslamayı yapmaya engel olmayacaktır.
Test sonuçlarını alırken de her bir testi 3 kez tekrarladım ve en iyi ya da en kötü değeri değil ortadaki değerleri test sonucu olarak aldım. Testi Apache Benchmark (ab) ile, “ab -c 500 -t 30 URL” şeklinde çalıştırarak gerçekleştirdim. Sonuçlar aşağıdaki gibidir:
| Test 1 | |||
| Smarty | PHPTAL | Pure PHP | |
| Completed Req. : | 8530 | 7338 | 50000 |
| Req/sec : | 284.23 | 244.56 | 1808.69 |
| Time/sec [ms] : | 1759.12 | 2044.48 | 276.44 |
| Test 2 | |||
| Smarty | PHPTAL | Pure PHP | |
| Completed Req. : | 3004 | 2620 | 16442 |
| Req/sec : | 100.08 | 87.33 | 547.98 |
| Time/sec [ms] : | 4995.96 | 5725.2 | 912.44 |
Bu sonuçlara baktığımızda HTML kodları içine PHP yazılarak yapılan geliştirmenin şablon motoru kullanılarak yazılanlara oranla en az 5 kat daha hızlı olduğunu görebiliyoruz. Ayrıca 1 sn. içinde sunucunun cevap verebildiği istek sayısında da ciddi bir fark olduğu görülüyor. Sonucun böyle olacağını tahmin ediyordum aslında. Çünkü hiç birşey düşünmesek bile toplamı 10 satırdan oluşan bir PHP kodu ile yüzlerce satırdan oluşan ve tek bir istek için bile onlarca işlem yapan bir şablon motorunun aynı hızda çalışamayacağı aşikardır. Anlaşıldığı üzere bu hız-performans farkı da aslında hiç de azımsanmayacak ölçüde bir fark. Bu durumda bence asıl soru şu hale geliyor: “Kalite standartlarına ve kabul gören metotlara uygun olarak kod yazmak, geliştirme sürecini kısaltan, ileriye dönük olarak kodların bakımını kolaylaştıran kütüphaneleri ve yaklaşımları kullanmak genel-geçer, her zaman ve her durumda doğru olan bir yaklaşım mıdır?”.
Bu soruya cevap aramadan önce rahatlıkla diyebiliriz ki PHP’nin kendi çalışma süresi (eklenen kütüphaneler, kullanılan frameworkler ile birlikte bile) genelde bir web uygulamasının en yavaş çalışan kısmı değildir. Yavaşlığa temel olan genelde başta veritabanı işlemleri olmak üzere PHP’nin bir şekilde bağlandığı yapılardır. Ve aslında birçok durumda; şablon motoru, PHP frameworkleri ve diğer kütüphaneler gibi yapılar çoğu kez performansı dolaylı olarak artırır. Çünkü programcıların belki birçoğu bu hazır imkanlar olmadığında performansa etki edecek hem mimari hem de prosedürel anlamda daha çok hata yaparlar. Bunların haricinde bir uygulamanın geliştirme süresi, daha sonradan bakımın kolay yapılabilmesi performanstan bile daha değerlidir. Ama gene de tüm bunların her durumda ve her proje için yararlı olacağını iddia etmek doğru olmayacaktır.
Donanımın artırılamadığı durumlarda eğer PHP kodunun daha hızlı çalışması konusunda bir ihtiyaç varsa, öncelikle web sunucusu, işletim sistemi ve ilgili konfigürasyonları, cache uygulamaları ve sistemleri (memcache, APC, xcache, vb.) ve varolan kod üzerinde yapılabilecek optimizasyonlar öncelikli olarak yapılmaya çalışılmalıdır. Fakat bütün bunlar yapıldıktan sonra gene sabit bir donanım içinde performans artırmak gerekirse ilk gözden çıkarılabilecek şeyler tüm özelliklerinin kullanılmadığı hazır kütüphaneler olmalıdır. Tabii bu son çareyi denemeden önce eğer isterseniz Facebook’un yaptığı gibi (HipHop) ekstrem çözümler deneyebilirsiniz.
PHP kodunun kendi performansı muhtemelen birçok programcı için bu aktardığım seviyede kritik değildir. Fakat benim gibi belli bir Linode VPS üzerinde birçok siteyi barındırmaya çalışıyorsanız, yeni ve çok ziyaretçisi olacak yeni bir site hazırlıyor ve bir üst VPS paketi için ekstra para ödemek istemiyorsanız, hazırlayacağınız projeyi kodlamaya başlamadan önce bu tür bir test yapmak ve buna göre kod yazmaya başlamak iyi bir tercih olabilir.
Smarty kullananlar için son bir notum olacak : Smarty kullanmayın! Aslında şablon motoru kullanmış olmak için şablon motoru kullanmayın da diyebilirim. Herhangi bir şablon motorununda sadece PHP değişkenlerinin yazılışlarını değiştirmek ve sadece foreach döngüleri ve if/switch ler için bir şablon motoru kullanıyorsanız, bence bir şablon motoru kullanmanıza hiç gerek yok.
Benzer Konular
Tags: performans, PHP, phptal, smarty
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Şubat 17th, 2010 at 1:33 pm
Aslında konuyla Symfony’den Fabien Potencier in bir yazısı var, şurada:
http://fabien.potencier.org/article/35/templating-engines-in-php-follow-up
Burada Twig (http://www.twig-project.org) ile bir test yapılmış ve çok iyi görünüyor.
Mart 10th, 2010 at 1:13 pm
Lütfen APC kullanın. Çok hızlı PHP ve PHPTAL yapar.