Vcoderz Community

Vcoderz Community (http://forum.vcoderz.com/index.php)
-   Computers & Information Technologies (http://forum.vcoderz.com/forumdisplay.php?f=6)
-   -   PHP caching system - optimization idea (http://forum.vcoderz.com/showthread.php?t=16977)

xcoder 10-28-2009 07:16 PM

PHP caching system - optimization idea
 
I was thinking about an effective caching system to reduce server load and DB connections and eventually makes the server traffic bandwidth bigger + faster response. I will be using an easy way to explain my idea.

Such system can be applied only on heavy traffic websites that have hundreds and thousands of page views every minute and same output to all clients not personalized or dynamic.
Blogs and news websites are the most to benefit from such system.

We will make easy calculations to compare before & after and how much this could reduce the load on the server and increase its traffic bandwidth and eventually servers that could cost thousands of dollars.

We will be using PHP script + MySQL + Apache

-------------------------

Before:

Pageviews: 100/minute
Average DB queries / page: 5

--------------------------------
DB queries on 100 visit: 5 x 100 = 500


How does the system work:

The system functionality is very simple, its main functionality is to create static pages (html) that were already compiled and don't require any PHP rendering nor SQL connections anymore, now every time a client request a page the HTML page will load.

Okay that's great but what if i needed to edit or delete a page... and applying this system on all my website plug ins could take ages to finish.

I already thought about this and the system is global, in a meaning it will cache the whole page (from top to bottom) and not part of it so you don't have to make it internal but global and add it to your page headers.
Editing the pages is very easy also you will understand it below:

Steps:
  1. Client-1 request a page
  2. System creates static copy of that page store it then load it to the client.
  3. Client-2 request a page
  4. The system checks the life_date of the static page, if it's < than 1 minute load it else go to step 2
So if any changes are made, it doesn't take longer than a minute to display. Of course you are free to set the time you wish and customize the system according to your needs in a way it caches parts of the website and not everything (hint: URL based)

After:
Pageviews: 100/minute
Average DB queries / page: 5
--------------------------------
So all SQL queries in 1 minute are simply 5

SQL connections reduced by 100 times, PHP rendering by almost 50% (since we are still loading the caching system on each request) and the response time has greatly increased especially on peak times.
The response time has greatly increased since the system has nothing to compile anymore.

This can seriously speed up your website like hell + reduce expenses + increase traffic bandwidth.

Of course it's not as simple as that and lot of things should be taken into consideration but this is the base idea of the system.
This is one of the things I'd like to develop.

=)

Google 10-28-2009 11:39 PM

[mouse]
Interesting idea. Already proposed many times, but not ideal.
I will post a detailed analysis as soon as I get a keyboard.

[/mouse]

hegma 10-29-2009 10:26 AM

this photo explian the caching with php
http://img691.imageshack.us/img691/2108/withcache.png

As you can see, the MySQL database and Templates aren't touched, the web server just sends back the contents of a plain .html file to the browser. The request is completed in a fraction of the time, the user gets their page faster, and your server has less load on it...
Everyone's Happy.

xcoder 01-26-2010 07:05 AM

I created the caching system last night and currently in use online and its' working very smoothly.

Find the codes below:

http://www.copypastecode.com/20949/
Code:

class cache{
   
    // Attributes
    private $cache_dir;                                    // Cache directory (Default: document_root + cache/)
    private $expiry = 60;                                // Cache file life time in seconds
    private $min_file_size = 1024;            // Min file size in cache in bytes
    private $file_path;                                    // Page path / URL (Default: curent path)
   
    // Getters and setters
    public function setCacheDir($value)            {    $this->cache_dir = $value;            }
    public function setExpiry($value)                {    $this->expiry = $value;                    }
    public function setMinFileSize($value)    {    $this->min_file_size = $value;    }
    public function setFilePath($value)            {    $this->file_path = $value;            }
   
    public function getCacheDir()                        {    return $this->cache_dir;                }
    public function getExpiry()                            {    return $this->expiry;                        }
    public function getMinFileSize()                {    return $this->min_file_size;        }
    public function getFilePath()                        {    return $this->file_path;                }
   
    // To be executed on object creation
    public function __construct(){
        // Set default cache_dir path and File path
        $this->setCacheDir($_SERVER['DOCUMENT_ROOT'] . "/cache/");
        $this->setFilePath(self::currentPath());
    }
   
    // Load file / Page into string
    static function loadFileContent($file_path){
        $file_content = file_get_contents($file_path);
        return $file_content;
    }
   
    // Encryption used to decode pathes before storing them
    private static function encrypt($str){
        return md5($str);
    }
   
    // Method to create cache file and store it
    public function createCacheFile(){
       
        // Make sure the required attributes are defined
        if($this->getCacheDir() and $this->getFilePath()){
       
            // Gets current page output
            $file_content = ob_get_contents();
           
            // Adds when the file was cached to the page bottom
            $file_content .= "";
           
            // Encrypt file path
            $file_path = $this->getCacheDir() . self::encrypt($this->getFilePath());
           
            // Create caching file
            $file_handle = fopen($file_path, 'w') or die("can't open file");
            fwrite($file_handle,$file_content);
            fclose($file_handle);
       
        // Throw an exception if the required parameters aren't defined
        }else{
           
            throw new Exception(__CLASS__ . ": Please define cache_dir and file_path to continue");
           
        }
       
    }
   
    // Method to load cached files
    public function loadFromCache(){
       
        // Make sure all required attributes are defined
        if($this->getCacheDir() and $this->getExpiry() and $this->getMinFileSize() and $this->getFilePath()){
           
            $file_path = $this->getCacheDir() . self::encrypt($this->getFilePath());
           
            // If file exists gather its information (done alone to reduce memory and CPU load on file info gathering)
            if(file_exists($file_path)){
           
                // Gather file information
                $file_age = time() - filemtime($file_path);
                $file_size = filesize($file_path);
               
                // If file exists and life expiry has not been reached yet and minimum file is above the minimum then include the file
                if($file_age < $this->getExpiry() and  $file_size > $this->getMinFileSize()){
                    include($file_path);
                    exit;
                }
               
            }
       
        // Throw an error if the required attributes weren't defined
        }else{
       
            throw new Exception(__CLASS__ . ": Please define cache_dir, expiry, file_path and min_file_size to continue");
       
        }
    }
       
    // Returns full current page path
    static function currentPath() {
        $pageURL = 'http';
        if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
        $pageURL .= "://";
        if ($_SERVER["SERVER_PORT"] != "80") {
            $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
        } else {
            $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
        }
        return $pageURL;
    }
   
    // Easy-to-implement load from cache
    public static function load($expiry = null, $min_file_size = null, $file_path = null, $cache_dir = null){
       
        // Try catch errors returned from object
        try{
       
            // Create object
            $obj = __CLASS__;
            $load_cache = new $obj;
           
            // Set attributes
            if($expiry !== null)                        $load_cache->setExpiry($expiry);
            if($min_file_size !== null)        $load_cache->setMinFileSize($min_file_size);
            if($file_path !== null)                    $load_cache->setFilePath($file_path);
            if($cache_dir !== null)                    $load_cache->setCacheDir($cache_dir);
           
            // Load from cache
            $load_cache->loadFromCache();
           
            // Destroy instance
            unset($load_cache);
       
        }catch(Exception $cache_errors){
           
            echo $cache_errors->getMessage();
           
        }
       
    }
   
    // Easy-to-implement write / create to cache
    public static function create($file_path = null, $cache_dir = null){

        // Try catch errors returned from object
        try{
       
            // Create object
            $obj = __CLASS__;
            $create_cache = new $obj;
           
            // Set attributes
            if($file_path !== null)        $create_cache->setFilePath($file_path);
            if($cache_dir !== null)        $create_cache->setCacheDir($cache_dir);
           
            // Create cache file
            $create_cache->createCacheFile();
           
            // Destroy instance
            unset($create_cache);
           
        }catch(Exception $cache_errors){
           
            echo $cache_errors->getMessage();
           
        }
       
    }

}
?>

It's very easy to implement:

Quote:

include('cache.class.php');
cache::create(); // Page top
cache::load(); // page bottom
Took me couple of hours to develop it and will consider extending it later or create a PHP based proxy server =)

Google 02-15-2010 05:12 PM

Cool script.
Other than that, use something lighter and faster than MD5.
MD5 will obviously slow down your script.

---

How about a PHP optimization competition?
I can prepare one if there will be enough participants.
The competition will involve a PHP script written in a bad way that must be optimized in order for it to run faster. So basically, we measure the time taken by each script to run and the person with the fastest script will be the winner.

Sheriff Ice 09-19-2010 12:58 AM

Great class im using it, its impressively amazing, reduced the load time dramatically

xcoder 09-19-2010 09:35 AM

Quote:

Originally Posted by Google (Post 209489)
Cool script.
Other than that, use something lighter and faster than MD5.
MD5 will obviously slow down your script.

---

How about a PHP optimization competition?
I can prepare one if there will be enough participants.
The competition will involve a PHP script written in a bad way that must be optimized in order for it to run faster. So basically, we measure the time taken by each script to run and the person with the fastest script will be the winner.

Just saw your post, i am in as long it doesn't require much time from my side.
However, optimizing an application doesn't stop on the development level.
Apache could be tweaked to easily double and triple performance.

- Enable "Worker" mode instead of "Prefork" on apache.

- Enable Gzip or mod_deflate to compress output content even though this will increase CPU load but will reduce your page size dramatically and eventually make the page load way faster since it's compressed on the server side > sent to client > uncompressed by the client browser and displayed.

- Add PHP accelerator like APC along side with the PHP based caching system.

- Disable many options from PHP like "magic_quotes" for example.

- Use a PHP caching system and make sure it's the very first thing to load on the page, this will reduce PHP rendering to very low levels and totally stop any SQL connections. Refer to the first post in this thread.

Or simply go with advanced caching systems such as Memcached (More complicated than regular classes but does wonders, many popular websites such as twitter use it).

Tweaking your server and optimizing your application could make your machine handle times more traffic and serve your client at higher speed.

xcoder 09-19-2010 09:50 AM

Quote:

Originally Posted by Sheriff Ice (Post 222553)
Great class im using it, its impressively amazing, reduced the load time dramatically

Indeed, i'm using it on multiple websites and has been doing great so far.
However, this class is made for mass page caching and works great for news and blog websites, but it breaks when you have client interaction where results are supposed to be different for each client and an SQL caching system is required.

Therefore i thought about developing a more advanced class where it caches SQL results and pops them up if query encryption matches instead of placing an SQL request each time.

for example:

// Simple SQL query
Code:

select * from users where id = 32
// What the system actually does before running the query:
- Encrypt it, add client session or id to it "32541_00000ad589174863012860b04aae75cd" let's say and check if it exists in the cache. If it does just load it, if it doesn't:

Proceed with the SQL query, get the result > serialize it > cache it.

The difference in such caching system and the above is that leaving room for dynamic queries every minute have way more effect than the above system for a simple reason: Each client results of custom queries unlike a news website where a news-load query almost never changes.

Therefore the cache should be cleared upon modification (update,delete) only.

When the record is updated you simple clear the cache of 32541_*

Will post the class when developed.


All times are GMT +1. The time now is 01:19 PM.

Powered by vBulletin® Version 3.8.3
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Ad Management plugin by RedTyger