News:

Bored?  Looking to kill some time?  Want to chat with other SMF users?  Join us in IRC chat or Discord

Main Menu

SMF 2.0 - Visitor Cache v1.0

Started by Türkçe Forum, May 11, 2011, 12:20:25 PM

Previous topic - Next topic

Türkçe Forum

Kendim (mecburen) bir cache sistemi yazmak istiyorum. Fakat bunu yaparken SMF ile ilgili bazı bilgilere ihtiyacım var. Önce kendi çabamla yaptığım şeyi anlatayım. Bir index yaptım ve onu cache sistemli hale getirdim. (http://index.vatan.tc) Muhteşem bir hızla çalışıyor ve db sorgulama sayısı çok azaldığı için, sayfalar hızlı açılıyor.

Basit bir cache tekniği uyguladım, fakat sonuç mükemmel. Kodları kendim yazdığım için cache sistemini uygulamak kolay oldu. Fakat aynı şeyi FORUM kısmı için de yapmak istiyorum.

Kullandığım teknik:

Quote
<?php
	
$cFile 'onbellekalinacaksayfa.html';
        
        
//    Daha önce önbellekte dosya varsa...
	
if ( (
file_exists($cFile)) && ((filemtime($cFile) + 600) > time()) ) { $content file_get_contents($cFile); echo $content; }
 
        
//    Daha önce önbellekte dosya yoksa, önbellek dosyasını oluştur....
                 
else
	
{
	
	
ob_start();                                              // Kayıt başlıyor...
	
	
echo 
'<html>TÜM İÇERİK</html>';          // Echo yapılan bütün içerik...
	
	
$content ob_get_contents();              // $contents kayda alınanlar...
	
	
ob_end_clean();                                     // Kaydı temizliyor...
	
	
file_put_contents($cFile,$content);        // Kaydedilen içeriği önbellek alınacak sayfa olarak kaydet.
	
	
echo 
$content;
	
}
?>


Bu sistemi SMF foruma nasıl entegre edebiliriz?
Teknik bilgisi olan arkadaşlar, fikir önerilerinde bulunurlarsa, güzel bir cache modu meydana getirebiliriz.


E d i t :

Problemi çözdüm ve Cache sisteminin ismini Visitor Cache yaptım. Faydalanmak isteyenler şu linkten kodlara bakabilirler:
* http://www.simplemachines.org/community/index.php?topic=433706.msg3042197#msg3042197

Visitor Cache v1.1 için şu adresi inceleyebilirsiniz, daha hızlı ve sağlıklı bir hale getirildi:
* http://forum.vatan.tc/smf-2x-visitor-cache-sistemi-v11-t58661.0.html

Yağız...

SMF 2.0 sürümünün kendi önbellek sistemi var: Yönetim > Sunucu Ayarları > Önbellek Ayarları

Alpay

Evet 3 seviye hemde, ancak bunların her seviyesine almak bile bir o kadar bilgi gerektiriyor :)

Türkçe Forum

Arkadaşlar o dediğinizi biliyorum.
Fakat onu uygulamak için bazı eklentilerin kurulması lazım. Seviye 1 için eklentiye gerek yok bende çalışıyor, Şuan seviye 1 için kullanıyorum ama pek etkili olmuyor. Yukarıda anlattığım cache sistemi çok etkili ve hızlı çalışıyor. Onu SMF mod şekline dönüştürebilirsek, muhteşem olur.

Gerekli olan bilgi, SMF bir konuyu gösterdiği zaman hangi dosyalar kullanılıyor onları bilmek.

Mesela /index.php?topic=7.0 dediğimizde hangi dosyalar çalışıyor ve tüm çıktıyı kaydedebilir miyiz? Eğer tüm çıktıyı tek bir seferde kaydedebilirsek, onu .html olarak kaydedip, bir dahaki çağrılışında database işlemleri ve diğer php işlemlerini yaptırmadan, direkt o dosyaya yönlenmesini sağlayabiliriz. SMF'e biraz daha hakim olsam yapardım eksik kısımları dolduran olursa, çok güzel bir mod yapılabilir.



Yağız...

../Sources/Load.php'de cache_put_data ve cache_get_data fonksiyonlara göz atabilirsiniz.

grafitus

Quote from: Yağız... on May 11, 2011, 01:30:48 PM
../Sources/Load.php'de cache_put_data ve cache_get_data fonksiyonlara göz atabilirsiniz.
O yine sayfada belirli bölümleri "cache"ler.

"Cache" konusunda pek bilgili değilim. Sizin yönteminiz mi daha iyi olur, yoksa SMF'nin varsayılan olanı mı, bilemiyorum. Ama eğer sayfanın tamamını "cache"lemek istiyorsanız, sanırım ./index.php'de şuradan sonra yazmalısınız kodlarınızı:
// What function shall we execute? (done like this for memory's sake.)
call_user_func(smf_main());

// Call obExit specially; we're coming from the main area ;).
obExit(null, null, true);


Ve şahsen file_put_contents() yerine, fopen() + fwrite() + fclose() kullanmanızı tavsiye ederim. Bende birkaç sefer sağlıklı çalışmamıştı. Birde aralarında yapılan bir test var şurada:
http://balancedbraces.com/2008/06/12/fopen-fwrite-fclose-vs-file_put_contents/

Türkçe Forum

Quote from: Yağız... on May 11, 2011, 01:30:48 PM
../Sources/Load.php'de cache_put_data ve cache_get_data fonksiyonlara göz atabilirsiniz.

Hocam söylediğin yere baktım, SMF'in 1. seviyedeki cache mantığını anlamış oldum. Meğer hiç bir işe yaramıyormuş.
Ben de, cache olduğu halde neden hala yavaş çalışıyor diyordum. Çok az şeyi kaydediyor. Birçok sorgu, yine database üzerinden, anlık gerçekleşiyor.

Şimdi lazım olan tek şey, tüm çıktıyı kaydedebilmek, index.php'yi inceledim, ilk satırlarda

// This makes it so headers can be sent!
ob_start();

şeklinde bir yer var. Yani kayıt başlatılıyor. Bir yerlerde de sonlandırılması lazım. Sonlandırmadan önce tüm veriyi yukarıda verdiğim koddaki gibi .html olarak kaydedersek, sayfa bir dahaki çağrılışında index.php'de en tepeye yazacağımız kontrol kodu ile kontrol edilir, önbellekte varsa çağılır, yoksa aynen diğer işlemler yapılır.

önemli olan nerede contents'in kaydedileceği...

Türkçe Forum

#7
Quote from: grafitus on May 11, 2011, 02:16:51 PM
Quote from: Yağız... on May 11, 2011, 01:30:48 PM
../Sources/Load.php'de cache_put_data ve cache_get_data fonksiyonlara göz atabilirsiniz.
O yine sayfada belirli bölümleri "cache"ler.

"Cache" konusunda pek bilgili değilim. Sizin yönteminiz mi daha iyi olur, yoksa SMF'nin varsayılan olanı mı, bilemiyorum. Ama eğer sayfanın tamamını "cache"lemek istiyorsanız, sanırım ./index.php'de şuradan sonra yazmalısınız kodlarınızı:
// What function shall we execute? (done like this for memory's sake.)
call_user_func(smf_main());

// Call obExit specially; we're coming from the main area ;).
obExit(null, null, true);


Ve şahsen file_put_contents() yerine, fopen() + fwrite() + fclose() kullanmanızı tavsiye ederim. Bende birkaç sefer sağlıklı çalışmamıştı. Birde aralarında yapılan bir test var şurada:
http://balancedbraces.com/2008/06/12/fopen-fwrite-fclose-vs-file_put_contents/

eyvallah hocam saolasın, ben kararsız kalmıştım onda hatta file_get_contents var omu daha hızlı yoksa diğerleri mi karar veremedim. kodu aldığım yerde o şekilde kullanıldığı için öyle kullanmıştım. dediğiniz gibiyse hemen değiştiririm inşaAllah.



Edit:

evet aynı yukarıda verdiğim şekilde uyguladım ve sayfaları tek tek kaydediyor. lakin hesap edilmeyen şeyler var.
mesela üyelerle ilgili, üyelere göre düzenlenen forum ayarları var. onlar gösterilirken problem olabiliyor.
ayrıca session değerleri ile ilgili sorunlar da çıkıyor.

belki sadece herkesin aynı şekilde gördüğü yerler için bir düzenleme yapılabilir. o tip yerleri her sayfa için ayarlanacak bir .html sayfaya kaydedip, o değerleri database'den çekmek yerine direkt html olarak echo'layabiliriz.

yine de forumu en çok kastıracak yerler için kısmı bir cache ayarlanması büyük ölçüde rahatlatacaktır.
çünkü sonuç olarak birden fazla mysql sorgulaması yapmak yerine sadece 1 kere o sayfa ile ilgili bilgi dosyasına fopen() ile bağlanıp $degisken şeklinde atamak hem daha hızlı, hem daha hafifletici olacaktır.

mesela related_topics modu için çok ideal.

İlgilinenen arkadaşlara teşekkürler.

grafitus

Her üye grubu ve dil için ayrı "cache" almalısınız. Şunun gibi:

global $context, $user_info;

if (!empty($context['current_action']))
$cache_file = 'action_' . $context['current_action'];
elseif (!empty($context['current_topic']))
$cache_file = 'action_topic';
elseif (!empty($context['current_board']))
$cache_file = 'action_board';
else
$cache_file = 'action_index';

$cache_file = $cache_file . '-' . implode('_', $user_info['groups']) . '-' . $user_info['language'];

Türkçe Forum

Quote from: grafitus on May 11, 2011, 05:21:09 PM
Her üye grubu ve dil için ayrı "cache" almalısınız. Şunun gibi:

global $context, $user_info;

if (!empty($context['current_action']))
$cache_file = 'action_' . $context['current_action'];
elseif (!empty($context['current_topic']))
$cache_file = 'action_topic';
elseif (!empty($context['current_board']))
$cache_file = 'action_board';
else
$cache_file = 'action_index';

$cache_file = $cache_file . '-' . implode('_', $user_info['groups']) . '-' . $user_info['language'];


Evet hocam, dinamik değerlerde, değişen şeylere göre ayrı ayrı cache almak lazım ama benim ziyaretçiler üyelerden kat kat fazla.
Sadece ziyaretçilere cache alsam yeterli olur inşaAllah.

Birçok forumun ziyaretçi sayısı, üye sayısından fazla.
SMF, tüm sayfayı kaydeden bir cache yapsaydı iyi olurdu.
İş başa düştü yine :)



Türkçe Forum

#10
Cache tamamdır inşaAllah. Ziyaretçi sayısı fazla olan forumlar için kullanışlıdır.
Sadece ziyaretçilerin görüntüledikleri sayfalara cache tutan bir moddur.

Kullanmak isteyenler aşağıdaki düzenlemeleri yapıp, kullanabilirler.
Aşağıdaki kodlarda sadece topic sayfaları için (/index.php?topic=10.0 gibi) cache yapılmakta. SMF 2.0 ana sayfa ve MessageIndex (kategori sayfaları) için zaten yeterli miktarda cache tutmakta. Geriye kalan kısımların da cache tutulmasına gerek yok zaten.
Seo4SMF kurulu olan sistemlerde de aktiftir.

Yapılacak değişiklikler:

1] Öncelikle index.php'nin olduğu dizine ismini belirleyeceğiniz boş bir klasör açın ve klasör iznini 777 olarak ayarlayın. İçine bir de boş index.html dosyası atın. Vereceğim kodlardaki klasörün ismi yedek olacak. Bu ismi değiştirebilirsiniz.




2] Index.php içerisinde şunu bulun ve silin:

// Load the user's cookie (or set as guest) and load their settings.
loadUserSettings();





3] Index.php içerisinde şu kısmı bulun:

// Start the session. (assuming it hasn't already been.)
loadSession();



Sonrasına şunu ekleyin:

// Load the user's cookie (or set as guest) and load their settings.
loadUserSettings();

//
	
C.S.J Cache v1
if ($user_info['is_guest'] && !empty($_GET['topic']) && empty($_GET['action'])) 
{
	
$c1 = (int) $_REQUEST['topic'];
	
$c2 = (int) $_REQUEST['start'];
	

	
//
	
Klasör ismini düzenleyebilirsiniz.
	
$context['yedek'] = 'yedek';
	
$context['yedek_sure'] = 600
	
$context['yedek'] = $context['yedek'].'/t-'.$c1.'.'.$c2.'.html';
	

	
if ((
file_exists($context['yedek'])) && ((filemtime($context['yedek']) + $context['yedek_sure']) > time())) 
	

	
	
$cSj file_get_contents($context['yedek']); 
	
	
echo 
$cSj
	
	
exit; 
	
}
	
else { 
$context['yedek_al'] = true; }
}





4] Index.template.php içerisinde şu kısmı bulun:

function template_html_below()
{
global $context, $settings, $options, $scripturl, $txt, $modSettings;

echo '
</body></html>';
}



Şu kodla değiştirin:


function template_html_below()
{
	
global 
$context$settings$options$scripturl$txt$modSettings;

	
echo 
'
</body></html>'
;

//
	
C.S.J Cache v1
if ($context['yedek_al'])
{
	
$cSj '<!-- C.S.J Cache: '.date('d M Y H:i:s 'time()).' --></html>';
	
$vatan str_replace('</html>'$cSjob_get_contents());
	
$tc fopen($context['yedek'], 'w');
	
fwrite($tc$vatan);
	
fclose($tc);
}

}



Yağız...

4. bölümü Sources/QueryString.php dosyasında ob_sessrewrite fonksiyonunda yaparsanız daha sağlıklı olacaktır.

Türkçe Forum

#12
Quote from: Yağız... on May 12, 2011, 07:13:32 AM
4. bölümü Sources/QueryString.php dosyasında ob_sessrewrite fonksiyonunda yaparsanız daha sağlıklı olacaktır.

hocam o fonksiyonu yaptım fakat, index.php'de else { $context['yedek_al'] = true; } şeklinde setlenen değer, QueryString.php'de döndürülmüyor. O açıdan o kısım tamamen iptal oluyor.


bu arada biriken cache dosyalarını silmek isterseniz, aşağıdaki kodları bir php dosyasına koyup, serverınızda cron job çalıştırarak veya manuel olarak kendiniz çalıştırarak cache dosyalarını silebilirsiniz.


//
	
Yedeğe alınan önbellek sayfalarını silme scripti...
	
if (
$_GET['x'] == 'sifreniz') {
	
	
$anadizin 'yedek';
	
	
if (
$kaynak opendir($anadizin)) {
	
	
	
while (
false != ($file readdir($kaynak))) {
	
	
	
	
if (
$file != "." AND $file != ".." AND $file != "index.html" AND file !=".htaccess") { unlink($anadizin."/".$file); }
	
	
	
}
	
	
}
	
	
echo 
'Yedekler silindi...';
	
}


Şifreli yapıp başkalarının durduk yere cachelerinizi silmesini önleyebilirsiniz.
Çalıştırmak için /yedeksil.php?x=sifreniz

kimyaci

Mod için teşekkürler fakat admin panelde sürekli resimde görülen hata kaydını veriyor.


Advertisement: