Which php caching for XenForo ?

I currently have my vBulletin 4.2.0 forum that I am converting to the latest Xenforo, running memcache. Does Xenforo support memcache accelerator or would I be better changing to another type like Xcache or APC? I have a VPS server with 1GB of memory, CentOS 5.9 64-bit with Xen VPS running cPanel bleeding-edge, Apache 2.4.4, PHP 5.3.23, MySQL 5.5.30. Also, am I now able to upgrade to PHP 5.4 since I am dumping that lame duck that is vBulletin?

Thanks in advance.
What is your Forum size for that VPS specs?
 
What is your Forum size for that VPS specs?
Only a tiny forum really. I have a bigger one that I am sticking with vBulletin for now until 4.x is EOL (which I estimate to be much sooner than later). The one I have the Xenforo licence for is only just over 5K members, around 3K active members, 29K threads and 71K posts. Obviously these are not exact totals, but gives you an idea that it's only a small forum. I also run Magento 1.7, but not on the same server (same domain though).
 
I currently have my vBulletin 4.2.0 forum that I am converting to the latest Xenforo, running memcache. Does Xenforo support memcache accelerator or would I be better changing to another type like Xcache or APC? I have a VPS server with 1GB of memory, CentOS 5.9 64-bit with Xen VPS running cPanel bleeding-edge, Apache 2.4.4, PHP 5.3.23, MySQL 5.5.30. Also, am I now able to upgrade to PHP 5.4 since I am dumping that lame duck that is vBulletin?

Thanks in advance.
APC with xcache is powerful combo. APC is as simple as having it installed. Don't add it to config.php. xcache is what you'll want to add to config.php

Since you're using cpanel though I would again remind you that xcache that comes with cPanel has some issues and its better if you add it manually from source. I'd also suggest you up your ram by 1gb for good measure.
 
APC with xcache is powerful combo. APC is as simple as having it installed. Don't add it to config.php. xcache is what you'll want to add to config.php

Since you're using cpanel though I would again remind you that xcache that comes with cPanel has some issues and its better if you add it manually from source. I'd also suggest you up your ram by 1gb for good measure.
Does APC and Xcache need to be compiled in Apache and PHP to work? Or is it standalone like memcache and you just add the .so to php.ini?
 
Did you try to use APC + XCache ? I thought XCache was doing the same thing as APC.
APC will give your whole php setup a boost. xCache will specifically filter (cache) your back end.

Yes, I've done it before. Although its been a while. I do know that memcache & memcached will eat your resources, but most importantly is doing overall not much when using it on a single server.

Digitalpoint (if I recall correctly, could be I'm mixing people up) wrote up something about how memcache worked better on mutli-sever setups vs using it on a single LAMP install.
 

PHP:
$config['cache'] = array(
    'enabled' => true,
    'frontend' => 'Core',
    'frontendOptions' => array(
            'caching' => true,
            'automatic_serialization' => false,
            'cache_id_prefix' => 'you_prefix_',
            'lifetime' => 18000
    ),
    'backend' => 'Xcache',
    'backendOptions' => array(),
    'cacheSessions' => true
);

NOTE: If you have suPHP, you're better off with file cache and should forget xcache altogether

PHP:
$config['cache']['enabled'] = true;
$config['cache']['cacheSessions'] = true;
$config['cache']['backend'] = 'File';
$config['cache']['backendOptions'] ['cache_dir'] = '/path/to/cache';
$config['cache']['frontend'] = 'Core';
$config['cache']['frontendOptions'] ['cache_id_prefix'] = 'xf_';

I would suggest 1 configuration to that
http://xenforo.com/community/threads/xcache-config-for-dummies-like-me.29137/#post-338222
 
We offer both APC and Memcache at xF Host, majority of our clients, plus my own boards all use Memcache.
php 5.5 will come with Zend Optimizer+

I've played with it on another VPS. I think it could very well replace APC easily (it's faster and more stable)
 
Mind to share your found solution about munin, Tracy Perry ? Yes, I'm exceptionally lazy to search. :p
This is for using nginx - so here we go.

In /etc/munin/plugin-conf.d make a file called php_apc and place
Code:
[php_apc_*]
user root
env.url http://localhost/apc_info.php?auto
in it.

Define a localhost for nginx with
Code:
server {
    server_name localhost;
    include /etc/nginx/php.conf;
    root /usr/share/nginx/html;
    allow 127.0.0.1;
    deny all;
    location / {
    access_log off;
        }
    location /nginx_status {
    stub_status on;
    access_log off;
        }
            }

In the ROOT defined above create a file called apc_info.php that contains
Code:
<?php
/**
* TODO: File header.
* TODO: Code comments.
*/
 
if(function_exists("apc_cache_info") && function_exists("apc_sma_info")) {
 
  $time = time();
 
  $mem = apc_sma_info();
  $mem_size = $mem['num_seg']*$mem['seg_size'];
  $mem_avail= $mem['avail_mem'];
  $mem_used = $mem_size-$mem_avail;
 
  // Some code taken from the file apc.php by The PHP Group.
  $nseg = $freeseg = $fragsize = $freetotal = 0;
  for($i=0; $i<$mem['num_seg']; $i++) {
    $ptr = 0;
    foreach($mem['block_lists'][$i] as $block) {
      if ($block['offset'] != $ptr) {
        ++$nseg;
      }
      $ptr = $block['offset'] + $block['size'];
      // Only consider blocks <5M for the fragmentation %
      if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
      $freetotal+=$block['size'];
    }
    $freeseg += count($mem['block_lists'][$i]);
  }
 
  if ($freeseg < 2) {
    $fragsize = 0;
    $freeseg = 0;
  }
 
  $cache_mode = 'opmode';
  $cache=@apc_cache_info($cache_mode);
 
  // Item hits, misses and inserts
  $hits = $cache['num_hits'];
  $misses = $cache['num_misses'];
  $inserts = $cache['num_inserts'];
 
  //
  $req_rate = ($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']);
  $hit_rate = ($cache['num_hits'])/($time-$cache['start_time']); // Number of entries in cache $number_entries = $cache['num_entries'];
  $miss_rate = ($cache['num_misses'])/($time-$cache['start_time']); // Total number of cache purges $purges = $cache['expunges'];
  $insert_rate = ($cache['num_inserts'])/($time-$cache['start_time']);
 
  // Number of entries in cache
  $number_entries = $cache['num_entries'];
 
  // Total number of cache purges
  $purges = $cache['expunges'];
 
  //apc_clear_cache($cache_mode);
 
  $out = array(
    'size: ' . sprintf("%.2f", $mem_size),
    'used: ' . sprintf("%.2f", $mem_used),
    'free: ' . sprintf("%.2f", $mem_avail - $fragsize),
    'hits: ' . sprintf("%.2f", $hits * 100 / ($hits + $misses)),
    'misses: ' . sprintf("%.2f", $misses * 100 / ($hits + $misses)),
    'request_rate: ' . sprintf("%.2f", $req_rate),
    'hit_rate: ' . sprintf("%.2f", $hit_rate),
    'miss_rate: ' . sprintf("%.2f", $miss_rate),
    'insert_rate: ' . sprintf("%.2f", $insert_rate),
    'entries: ' . $number_entries,
    'inserts: ' . $inserts,
    'purges: ' . $purges,
 
  // TODO: Delete
    'purge_rate: ' . sprintf("%.2f", (100 - ($number_entries / $inserts) * 100)),
  // TODO: Delete
    'fragment_percentage: ' . sprintf("%.2f", ($fragsize/$mem_avail)*100),
    'fragmented: ' . sprintf("%.2f", $fragsize),
    'fragment_segments: ' . $freeseg,
  );
}
else {
  $out = array('APC-not-installed');
}
echo implode(' ', $out);


Create a file in your /etc/nginx directory called php.conf containing
Code:
index index.php index.html index.htm;
 
location ~ \.php$ {
  # Zero-day exploit defense.
  # http://forum.nginx.org/read.php?2,88845,page=3
  # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
  # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.
  try_files $uri =404;
 
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  include /etc/nginx/fastcgi_params;
 
  # As explained in http://kbeezie.com/view/php-self-path-nginx/ some fastcgi_param are missing from fastcgi_params.
  # Keep these parameters for compatibility with old PHP scripts using them.
  fastcgi_param PATH_INFO      $fastcgi_path_info;
  fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 
  # Some default config
  fastcgi_connect_timeout        60;
  fastcgi_send_timeout          180;
  fastcgi_read_timeout          180;
  fastcgi_busy_buffers_size    256k;
  fastcgi_temp_file_write_size 256k;
 
  fastcgi_intercept_errors    on;
  fastcgi_ignore_client_abort off;
 
  fastcgi_pass 127.0.0.1:9000;
}
 
Continued due to 10000 character limit

Create a file called php_apc_ in /usr/share/munin/plugins containing
Code:
#!/usr/bin/perl
#
# Magic markers:
#%# family=auto
#%# capabilities=autoconf
 
use strict;
use Munin::Plugin;
 
need_multigraph();
 
my $ret = undef;
 
if (! eval "require LWP::UserAgent;")
{
    $ret = "LWP::UserAgent not found";
}
 
my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://127.0.0.1:%d/apc_info.php?auto";
my @PORTS = exists $ENV{'ports'} ? split(' ', $ENV{'ports'}) : (80);
 
if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" )
{
    if ($ret)
    {
        print "no ($ret)\n";
        exit 1;
    }
 
    my $ua = LWP::UserAgent->new(timeout => 30);
 
    my @badports;
    foreach my $port (@PORTS) {
        my $url = sprintf $URL, $port;
        my $response = $ua->request(HTTP::Request->new('GET',$url));
        push @badports, $port unless $response->is_success and $response->content =~ /^size:/im;
    }
    if (@badports) {
        print "no (apc-status)\n";
        exit 1;
    } else {
        print "yes\n";
        exit 0;
    }
}
 
if ( defined $ARGV[0] and $ARGV[0] eq "config" )
{
 
$0 =~ /php_apc_(.+)*/;
my $plugin = $1;
 
## PHP APC Cache Usage
if($plugin eq 'usage') {
print('multigraph php_apc_usage
graph_title Cache Usage
graph_args --base 1024 -l 0
graph_vlabel Bytes
graph_category php-apc
graph_order used free
graph_total Total
used.label Used Memory
used.draw AREASTACK
fragmented.label Fragmented Memory
fragmented.draw AREASTACK
free.label Available Memory
free.draw AREASTACK
');
}
 
## PHP APC Hit / Miss by percentage
elsif($plugin eq 'hit_miss') {
print('multigraph php_apc_hit_miss
graph_title Cache Hits / Misses
graph_args --base 1000 --lower-limit 0 --upper-limit 100 --rigid
graph_vlabel Percent
graph_category php-apc
graph_total Total
hits.label Hits
hits.draw AREA
hits.min 0
misses.label Misses
misses.draw STACK
misses.min 0
misses.warning 50
');
}
 
## PHP APC Purge rate (# Entries / Inserts)
elsif($plugin eq 'purge') {
print('multigraph php_apc_purge
graph_title Purge rate
graph_args --base 1000 --lower-limit 0 --upper-limit 100 --rigid
graph_vlabel Percent
graph_category php-apc
purge_rate.label Purge Rate
purge_rate.draw LINE2
purge_rate.min 0
purge_rate.warning 10
');
}
 
## PHP APC Fragmentation
elsif($plugin eq 'fragmentation') {
print('multigraph php_apc_fragmentation
graph_title Fragmentation
graph_args --base 1000 --upper-limit 100
graph_vlabel Percent
graph_category php-apc
fragment_percentage.label Fragmentation Percent
fragment_percentage.draw LINE2
fragment_percentage.min 0
fragment_percentage.warning 10
');
}
 
## PHP APC Number of files in cache
elsif($plugin eq 'files') {
print('multigraph php_apc_files
graph_title Files in Cache
graph_args -l 0
graph_vlabel Number of Files
graph_category php-apc
entries.label Number of files
entries.draw LINE2
entries.min 0
');
}
 
## PHP APC Rates
elsif($plugin eq 'rates') {
print('multigraph php_apc_rates
graph_title Hit, Miss and Insert Rates
graph_args --base 1000
graph_vlabel Cache Requests / Second
graph_category php-apc
request_rate.label Request rate (Hits + Misses)
request_rate.draw LINE2
request_rate.min 0
hit_rate.label Hit rate
hit_rate.draw LINE2
hit_rate.min 0
miss_rate.label Miss rate
miss_rate.draw LINE2
miss_rate.min 0
insert_rate.label Insert rate
insert_rate.draw LINE2
insert_rate.min 0
');
}
 
exit 0;
}
 
foreach my $port (@PORTS)
{
    my $ua = LWP::UserAgent->new(timeout => 30);
    my $url = sprintf $URL, $port;
    my $response = $ua->request(HTTP::Request->new('GET',$url));
 
    if ($response->content =~ /used:\s+([0-9\.]+)/im) {
        print "used.value $1\n";
    } else {
        print "used.value U\n";
    }
    if ($response->content =~ /free:\s+([0-9\.]+)/im) {
            print "free.value $1\n";
    } else {
            print "free.value U\n";
    }
 
    if ($response->content =~ /hits:\s+([0-9\.]+)/im) {
            print "hits.value $1\n";
    } else {
            print "hits.value U\n";
    }
 
    if ($response->content =~ /misses:\s+([0-9\.]+)/im) {
            print "misses.value $1\n";
    } else {
            print "misses.value U\n";
    }
 
    if ($response->content =~ /request_rate:\s+([0-9\.]+)/im) {
            print "request_rate.value $1\n";
    } else {
            print "request_rate.value U\n";
    }
 
    if ($response->content =~ /hit_rate:\s+([0-9\.]+)/im) {
            print "hit_rate.value $1\n";
    } else {
            print "hit_rate.value U\n";
    }
 
    if ($response->content =~ /miss_rate:\s+([0-9\.]+)/im) {
            print "miss_rate.value $1\n";
    } else {
            print "miss_rate.value U\n";
    }
 
    if ($response->content =~ /insert_rate:\s+([0-9\.]+)/im) {
            print "insert_rate.value $1\n";
    } else {
            print "insert_rate.value U\n";
    }
 
    if ($response->content =~ /entries:\s+([0-9]+)/im) {
            print "entries.value $1\n";
    } else {
            print "entries.value U\n";
    }
 
    if ($response->content =~ /inserts:\s+([0-9]+)/im) {
            print "inserts.value $1\n";
    } else {
            print "inserts.value U\n";
    }
 
    if ($response->content =~ /purges:\s+([0-9]+)/im) {
            print "purges.value $1\n";
    } else {
            print "purges.value U\n";
    }
 
    if ($response->content =~ /purge_rate:\s+([0-9\.]+)/im) {
            print "purge_rate.value $1\n";
    } else {
            print "purge_rate.value U\n";
    }
 
    if ($response->content =~ /fragmented:\s+([0-9\.]+)/im) {
            print "fragmented.value $1\n";
    } else {
            print "fragmented.value U\n";
    }
 
    if ($response->content =~ /fragment_segments:\s+([0-9]+)/im) {
            print "fragment_segments.value $1\n";
    } else {
            print "fragment_segments.value U\n";
    }
 
    if ($response->content =~ /fragment_percentage:\s+([0-9\.]+)/im) {
            print "fragment_percentage.value $1\n";
    } else {
            print "fragment_percentage.value U\n";
    }
}
 
# vim:syntax=perl

at the command line issue
Code:
chmod -R 755 /usr/share/munin/plugins/php_apc_
ln -s /usr/share/munin/plugins/php_apc_ /etc/munin/plugins/php_apc_usage
ln -s /usr/share/munin/plugins/php_apc_ /etc/munin/plugins/php_apc_hit_miss
ln -s /usr/share/munin/plugins/php_apc_ /etc/munin/plugins/php_apc_purge
ln -s /usr/share/munin/plugins/php_apc_ /etc/munin/plugins/php_apc_fragmentation
ln -s /usr/share/munin/plugins/php_apc_ /etc/munin/plugins/php_apc_files
ln -s /usr/share/munin/plugins/php_apc_ /etc/munin/plugins/php_apc_rates

You must have libwww-perl installed.

I think that covered everything. ;)
Oh, forgot to mention - issue an /etc/init.d/munin-node restart. :rolleyes:
 
It will look somewhat like this - in addition to fragmentation, purge rates and files in cache.
1.webp
 
Top Bottom