Dołącz do zespołu ekspertów! Backend lub Frontend Developer?

Sprawdź najnowsze oferty pracy naszego partnera - 8lines.io!

Analiza obciążenia i czasu generowania

Założony przez  meto.

(24.07.2009, 11:58)taxido16 napisał(a): ....

Zauważyłem też że u mnie mybb nie potrafi korzystać z Xcache...
Zdaje się że nie bez powodu w komentarzu config.php nie jest wyszczególniony ten system cache...

Z cache to i xcache (i eA oraz być może memcache) nie są w stanie wygenerować unikalnego prefixu - robi md5(''), gdyż z jakiegoś powodu $mybb->settings['bburl'] jest niedostępne w tej funkcji. Szukałem, i wszystkie globals wyglądają na dobrze ustawione, ale $mybb->settings po prostu jest pustą tablicą...

Apropos tej tablicy to testowałem dalej, trochę po bandzie ale cóż: wyczyściłem ją. Efekt - prawda zużycie pamięci spadło do ok 9MB, ale czas generowania strony był ciągle ponad 0,25-0,3. W innych skryptach taki czas jest przy całkowicie wyłączonym cache lub gdy cały cache musi być odtworzony.

Dodatkowo MyBB cache'uje TYLKO tablice wynikowe z zapytań SQL, co z doświadczenia wiem że często trwa dłużej niż korzystanie z cache MySQL. Dodatkowo nie ma składowania żadnych już przetworzonych danych, co tak na prawdę nie skraca NIC, poza ew. I/O, a patrząc na ogólną wydajność, to nie ono pierwsze będzie problemem.
<?php
/**
 * MyBB 1.4
 * Copyright © 2008 MyBB Group, All Rights Reserved
 *
 * Website: http://www.mybboard.net
 * License: http://www.mybboard.net/about/license
 *
 * $Id: xcache.php 4304 2009-01-02 01:11:56Z chris $
 */

/**
 * Xcache Cache Handler
 */
class xcacheCacheHandler
{
    
/**
     * Unique identifier representing this copy of MyBB
     */
    
var $unique_id;
    
    function 
xcacheCacheHandler($silent=false)
    {
        if(!
function_exists("xcache_get"))
        {
            
// Check if our DB engine is loaded
            
if(!extension_loaded("XCache"))
            {
                
// Try and manually load it - DIRECTORY_SEPARATOR checks if running windows
                
if(DIRECTORY_SEPARATOR == '\\')
                {
                    @
dl('php_xcache.dll');
                } 
                else 
                {
                    @
dl('xcache.so');
                }
                
                
// Check again to see if we've been able to load it
                
if(!extension_loaded("XCache") && !$silent)
                {
                    
// Throw our super awesome cache loading error
                    
die("Xcache needs to be configured with PHP to use the Xcache cache support");
                    
$mybb->trigger_generic_error("sql_load_error");
                }
            }
        }
    }

    
/**
     * Connect and initialize this handler.
     *
     * @return boolean True if successful, false on failure
     */
    
function connect()
    {
        global 
$mybb;

        
// Set a unique identifier for all queries in case other forums on this server also use this cache handler
        
$this->unique_id md5("hajlo.com");

        return 
true;
    }
    
    
/**
     * Retrieve an item from the cache.
     *
     * @param string The name of the cache
     * @param boolean True if we should do a hard refresh
     * @return mixed Cache data if successful, false if failure
     */
    
    
function fetch($name$hard_refresh=false)
    {
        if(!
xcache_isset($this->unique_id."_".$name))
        {
            return 
false;
        }
        return 
xcache_get($this->unique_id."_".$name);
    }
    
    
/**
     * Write an item to the cache.
     *
     * @param string The name of the cache
     * @param mixed The data to write to the cache item
     * @return boolean True on success, false on failure
     */
    
function put($name$contents)
    {
        return 
xcache_set($this->unique_id."_".$name$contents);
    }
    
    
/**
     * Delete a cache
     *
     * @param string The name of the cache
     * @return boolean True on success, false on failure
     */
    
function delete($name)
    {
        return 
xcache_unset($this->unique_id."_".$name);
    }
    
    
/**
     * Disconnect from the cache
     */
    
function disconnect()
    {
        return 
true;
    }
    
    function 
size_of($name)
    {
        global 
$lang;
        
        return 
$lang->na;
    }
}
?>

Poprawiłem funkcje
function delete($name)
    {
        return 
xcache_unset($this->unique_id."_".$name);
    } 
(prosiłbym tu o komentarz...)

Ustawiłem na sztywno unique_id i próbowałem na sztywno wpisać TTL, ale to i tak nic nie daje w moim przypadku ;/
(24.07.2009, 14:30)taxido16 napisał(a): ...

Poprawiłem funkcje
function delete($name)
    {
        return 
xcache_unset($this->unique_id."_".$name);
    } 
(prosiłbym tu o komentarz...)

Ustawiłem na sztywno unique_id i próbowałem na sztywno wpisać TTL, ale to i tak nic nie daje w moim przypadku ;/

Tak, to tez widzialem. Nie jestem też pewien czy zasadne jest uzywanie xcache_isset a pozniej xcache_get, jako ze ta druga tez zwraca false w przypadku jak nie ma zmiennej w cache.

czyli proponowałbym zmianę na:
function fetch($name$hard_refresh=false)
    {
        return 
xcache_get($this->unique_id."_".$name);
    } 

Nie widzisz zmiany z tego powodu, o którym mówiłem wcześniej - MyBB nie oszczędza w żaden sposób liczenia dzięki cache. Jedyny zysk to mniejsza ilość zapytań SQL czy I/O.

Moim zdaniem cache'owana powinna być np cała strona główna (flush po zmianach) lub chociazby drzewo tematów przetworzone, najlepiej w postaci do "eval'owania" zapisane jako .php i wykonywane przez include. Wtedy omijasz mechanizm składowania zmiennych, bo pliki wskakują do cache opcode, co jeszcze bardziej przyspiesza działanie systemu.

MyBB tak "mieli" moim zdaniem dlatego, że operuje na bardzo dużych i wielowymiarowych tabelach, dzięki czemu to zawsze php obrywa. Rozumiem, że czasami nie da się tego ominąć, ale wypada cach'eowach w tym wypadku tabele wynikowe, choćby po ID usera jeśli jest taka potrzeba (tak się odbywa w SMF).
Funkcja xcache_get nie zwraca false, raczej NULL (choć nie jestem pewny...)


Zapomniałem... Miałem opisać jak filtrowałem te uprawnienia

przed funkcją
function forum_permissions($fid=0$uid=0$gid=0
w functions.php dodałem funkcje

/**
 * Group permissions to forum permissions
 *
 * @param array Group permissions
 * @return array Permissions for this forum
*/
function fetch_forum_permissions_group_permissions_filtr($filtr)
{
    
    
$forum_per_filtr = array(
        
canview => $filtr['canview'],
        
canviewthreads => $filtr['canviewthreads'],
        
candlattachments => $filtr['candlattachments'],
        
canpostthreads => $filtr['canpostthreads'],
        
canpostreplys => $filtr['canpostreplys'],
        
canpostattachments => $filtr['canpostattachments'],
        
canratethreads => $filtr['canratethreads'],
        
caneditposts => $filtr['caneditposts'],
        
candeleteposts => $filtr['candeleteposts'],
        
candeletethreads => $filtr['candeletethreads'],
        
caneditattachments => $filtr['caneditattachments'],
        
canpostpolls => $filtr['canpostpolls'],
        
canvotepolls => $filtr['canvotepolls'],
        
cansearch => $filtr['cansearch'],
    );
    
    return 
$forum_per_filtr;
    


Trochę na siłę ale działa:P
A funkcje
function forum_permissions($fid=0$uid=0$gid=0
zmodyfikowałem następująco

/**
 * Build the forum permissions for a specific forum, user or group
 *
 * @param int The forum ID to build permissions for (0 builds for all forums)
 * @param int The user to build the permissions for (0 will select the uid automatically)
 * @param int The group of the user to build permissions for (0 will fetch it)
 * @return array Forum permissions for the specific forum or forums
 */
function forum_permissions($fid=0$uid=0$gid=0)
{
    global 
$db$cache$groupscache$forum_cache$fpermcache$mybb$usercache$cached_forum_permissions_permissions$cached_forum_permissions;

    if(
$uid == 0)
    {
        
$uid $mybb->user['uid'];
    }

    if(!
$gid || $gid == 0// If no group, we need to fetch it
    
{
        if(
$uid != && $uid != $mybb->user['uid'])
        {
            if(!
$usercache[$uid])
            {
                
$query $db->simple_select("users""*""uid='$uid'");
                
$usercache[$uid] = $db->fetch_array($query);
            }

            
$gid $usercache[$uid]['usergroup'].",".$usercache[$uid]['additionalgroups'];
            
$groupperms usergroup_permissions($gid);
        }
        else
        {
            
$gid $mybb->user['usergroup'];

            if(isset(
$mybb->user['additionalgroups']))
            {
                
$gid .= ",".$mybb->user['additionalgroups'];
            }

            
$groupperms $mybb->usergroup;
        }
    }

    
$groupperms fetch_forum_permissions_group_permissions_filtr($groupperms); //fix
    
    
if(!is_array($forum_cache))
    {
        
$forum_cache cache_forums();

        if(!
$forum_cache)
        {
            return 
false;
        }
    }

    if(!
is_array($fpermcache))
    {
        
$fpermcache $cache->read("forumpermissions");
    }

    if(
$fid// Fetch the permissions for a single forum
    
{
        if(!
$cached_forum_permissions_permissions[$gid][$fid])
        {
            
$cached_forum_permissions_permissions[$gid][$fid] = fetch_forum_permissions($fid$gid$groupperms);
        }
        return 
$cached_forum_permissions_permissions[$gid][$fid];
    }
    else
    {
        if(!
$cached_forum_permissions[$gid])
        {
            foreach(
$forum_cache as $forum)
            {
                
$cached_forum_permissions[$gid][$forum['fid']] = fetch_forum_permissions($forum['fid'], $gid$groupperms);
            }
        }
        return 
$cached_forum_permissions[$gid];
    }


przy okazji zauważyłem że $cached_forum_permissions_permissions, $cached_forum_permissions; nie są wcale takie cached ;p
(24.07.2009, 17:34)taxido16 napisał(a): Funkcja xcache_get nie zwraca false, raczej NULL (choć nie jestem pewny...)
...
Ok, ok... do momentu uzycia === nie ma problemu ;), mozna też dla purystów zrobić if'a żeby zwracać false. Chodzi o to że xcache_isset niepotrzebny, szczególnie w dużej pamięci podręcznej może długo trwać.

Jaki efekt tej modyfikacji?

Update:
Ja szczerze nie zauważyłem efektów po tych zmianach :(
Czy ktoś może posiada/zna forum na MyBB powyżej 50k postów z czasem generowania głównej niższym niż 200ms (0,2s)?
W chwili obecnej czasy generowania które otrzymuje wachają się od 0.25s do nawet 2s:angry:
Z moich testów wynika że największą amplitude na indexie powoduje funkcja buildforumbits()
http://crossreference.mybboard.de/nav.ht...ex.php.htm

Nie rozumiem też czego statystyki poszczególnych działów są wyliczane co request, a także że nie są w żaden sposób cachowane. Nie wspomnę o tworzeniu tablic wielowymiarowych aby rozbijac je na inne tablice, a także niepotrzebne preg_replace'y (w moim wypadku nawet 600 na request)

W wielu miejscach i tak dane są pobierane z bazy pomimo iż są już cachowane,

Niestety skrypt nie jest przystosowany do obslugi for (niekoniecznie duzych) z sporą ilością grup użytkowników, oraz działów z wielopoziomowymi subforami .

Mybb ma dość dobry cache I/O lecz jest niemiłosierny dla pamięci i procesora. :dodgy:
Pamiętacie moje forum securcomp? Zrezygnowałem właśnie dlatego, że postawiłem na MyBB. Przy 10 osobach online forum działało więcej niż nieciekawie, zresztą moje problemy opisałem na blogu. Na moim hostingu shared nie mam limitu zapytań do bazy, więc "zwisa mi to" od pewnego czasu, jeżeli chodzi o użycie pamięci i CPU to jednak muszę wiedzieć co robię, no i tutaj MyBB całkowicie mnie zawiodło.

Ze znajomym zastanawiamy się nad otwarciem nowego serwisu, który miałby z pewnością forum, zaś przewidywany ruch byłby spory. Myślałem nad MyBB lub phpBB3, ale po ostatnich cyrkach nie mam ochoty już na początku wydawać pieniędzy na serwer typu VPS...
I chyba nadszedł czas, w którym mogę smiało stwierdzić że jednak MWW(mroczna wizja wujasa, jak nazwał to Damian) zaczyna się sprawdzać.
Moje forum nieciekawie chodziło w webh.pl, więc przeniosłem się do głowy.
I teraz uwaga. W webh już zużycie pamięci było nieciekawe, bo 6 mb na głównej. To nic, przeniosłem do głowy.
I uwaga!
Forum na głównej zużywa 9.25 MB (9699328 bytes)
I to wcale nie za sprawą wtyczek, bo po wyłączeniu google seo i innych spada może o 0.5 mb.
Wygląda to naprawdę nieciekawie. Jutro zacznę diagnozować, jeśli nic nie znajdę, czeka mnie migracja na inny skrypt. A tego bym nie chciał.
Debug w załączniku.


Załączone pliki
  MyBB Debug Information.htm (Rozmiar: 27,98 KB / Pobrań: 751)
Serwery CS REKSIO:))
(27.02.2010, 20:41)wujas napisał(a): I chyba nadszedł czas, w którym mogę smiało stwierdzić że jednak MWW(mroczna wizja wujasa, jak nazwał to Damian) zaczyna się sprawdzać.
Moje forum nieciekawie chodziło w webh.pl, więc przeniosłem się do głowy.
I teraz uwaga. W webh już zużycie pamięci było nieciekawe, bo 6 mb na głównej. To nic, przeniosłem do głowy.
I uwaga!
Forum na głównej zużywa 9.25 MB (9699328 bytes)
I to wcale nie za sprawą wtyczek, bo po wyłączeniu google seo i innych spada może o 0.5 mb.
Wygląda to naprawdę nieciekawie. Jutro zacznę diagnozować, jeśli nic nie znajdę, czeka mnie migracja na inny skrypt. A tego bym nie chciał.
Debug w załączniku.

reksio-cs.pl:
Cytat:15 użytkowników aktywnych w ciągu ostatnich 15 minut
W ciągu ostatnich 24 godzin było 49 użytkowników online
9 MB (9437184 bytes)

elfbot.pl:
Cytat:8 użytkowników aktywnych w ciągu ostatnich 15 minut
W ciągu ostatnich 24 godzin było 88 użytkowników online
6,5 MB (6815744 bytes)

Dodatkowo ja jadę na Google Seo...
Mój debug w załączniku.

Nie chciałbym nikogo broń boże obrażać, ale ja forum trzymam w czystości i takich problemów jak Wy nie mam.

#Edit:
No jeszcze warto zauważyć, że Ty na forum masz te tagi, najczęstsze zapytania i sporo działów...
Też jadę na google seo, do tego dopiero co forum przeniosłem, userzy w tej chwili są dzielenie na dwa, Ci którym odświeżyło dns i Ci którym nie zdążyło.
Być może mybb nie lubi litespeed, nie wiem...
@edit
I w ogóle dziwi mnie że w webh statystyki wyglądały inaczej.
Forum generuje się szybko, tylko ta pamięc.
A i 6 mb to dużo za dużo, podobne fora na bb3 zużywają ledwo 2 mb.
Serwery CS REKSIO:))
Mybb niczego nie lubi...
Co ma do tak dużego wzrostu pobieranej pamięci ilość działów? Przecież skoro na phpbb3 czy smf tego nie ma, to znaczy, że jednak da się.

Zresztą, na zagranicznych jak i polskich forach można już przeczytać, co dzieje się później - nawet 2 gb pamięci potrafi wciągnąć...

Nie jestem przeciwnikiem mybb, choć może to tak wyglądać. Cenię sobie funkcjonalność jak i wygodę tego skryptu, ale cena za jego użytkowanie jest zbyt wielka. Skoro forum ma się rozwijać, a póki co nie jest wielkie, to zalecam jak najszybszą konwersję do phpbb3.
Problem w tym, że jako tak ucieczki nie ma. Konwertery są na pewno do płatnych skryptów. Do phpbb3 nie widziałem konwertera...
Serwery CS REKSIO:))
(27.02.2010, 21:37)wujas napisał(a): 6 mb to dużo za dużo,

W takim razie mam pytanie co do mojego forum :P

Wg. TEGO Mam 9 mb zużycia pamięci, baza zajmuje ok. 3.14mb (wiem, malo :D ), czy mam wysoki problem z obciążeniem?
To tyle co ja przy bazie 30 mb...
Wrzuć sobie http://www.reksio-cs.pl/t-strona-z-infor...o-1522.htm i pochwal się tutaj, bo przy takim forum jak masz Ty to faktycznie coś nie tak...
Serwery CS REKSIO:))



Użytkownicy przeglądający ten wątek:

12 gości