Is there any compatible memory cache for PHP 7? Is there any compatible memory cache for PHP 7? php php

Is there any compatible memory cache for PHP 7?


I'd suggest using Memcached, especially if you're concerned about performance.

Whilst you are correct that APC(u) is a lot faster than Memcache, you're not taking into the account that by the time you're worrying about these metrics, you will be running across multiple servers and APC(u) cannot be shared across nodes.

You can use a single Memcache instance or cluster to serve as many application servers as you want. Scalability is a greater concern in modern application development than "how much performance can I squeeze out of one server?"

Having said that, your alternative is APCu, which has all of the functionality that you're used to from APC. It is marked as stable with PHP7 but I wouldn't recommend this because of its single-node nature & inability to work correctly with fastcgi.


APCU is literally APC without the code caching (they took the APC code, removed the byte-code cache and released it as APCU). It's a drop-in replacement. Exactly as APC's user-cache, it keeps the data in the same process as the PHP runtime, and so using the value is like much like retrieving an ordinary variable, hence the speed.


Another approach (which I haven't tried, but sounds very interesting) is to take advantage of the opcache as a key value cache. This graphiq post contains more details but no real code unfortunately (and note the comments from Kerry Schwab).

The gist of it is to ensure that the opcache is enabled and has enough memory allocated for the data that you need to cache and then something along the lines of the following (lifted from the article, check it out in full). Cache expiration (aside from manual deletion) would need to be handled too, but wouldn't be hard to add (e.g. wrap your data in a containing object with an expiry time and check it in your cache_get, deleting and ignoring the record if it's expired).

function cache_set($key, $val) {   $val = var_export($val, true);   // HHVM fails at __set_state, so just use object cast for now   $val = str_replace('stdClass::__set_state', '(object)', $val);   // Write to temp file first to ensure atomicity   $tmp = "/tmp/$key." . uniqid('', true) . '.tmp';   file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX);   rename($tmp, "/tmp/$key");}function cache_get($key) {    @include "/tmp/$key";    return isset($val) ? $val : false;}

Because of the opcache this functions as an in memory cache, but it avoids the overhead of serialization and deserialization. I guess that the cache_set should also call opcache_invalidate when writing (and in the cache_delete function which doesn't exist in their examples) but otherwise it seems sound for a cache which doesn't need to be shared between servers.

Edit: An example implementation with cache expiry (only accurate to a second, could use microtime(true) if more accuracy is required) below. Minimal testing actually done, and I dropped the HHVM specific replacement, so YMMV. Suggestions for improvements welcome.

class Cache {                                                                       private $root;                                                                  private $compile;                                                               private $ttl;                                                                   public function __construct($options = []) {                                        $this->options = array_merge(                                                       array(                                                                              'root' => sys_get_temp_dir(),                                                   'ttl'  => false,                                                            ),                                                                              $options                                                                    );                                                                              $this->root = $this->options['root'];                                           $this->ttl = $this->options['ttl'];                                         }                                                                               public function set($key, $val, $ttl = null) {                                      $ttl = $ttl === null ? $this->ttl : $ttl;                                       $file = md5($key);                                                              $val = var_export(array(                                                            'expiry' => $ttl ? time() + $ttl : false,                                       'data' => $val,                                                             ), true);                                                                       // Write to temp file first to ensure atomicity                                 $tmp = $this->root . '/' . $file . '.' . uniqid('', true) . '.tmp';             file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX);                 $dest = $this->root . '/' . $file;                                              rename($tmp, $dest);                                                            opcache_invalidate($dest);                                                  }                                                                               public function get($key) {                                                         @include $this->root . '/' . md5($key);                                         // Not found                                                                    if (!isset($val)) return null;                                                  // Found and not expired                                                        if (!$val['expiry'] || $val['expiry'] > time()) return $val['data'];            // Expired, clean up                                                            $this->remove($key);                                                        }                                                                               public function remove($key) {                                                      $dest = $this->root . '/' . md5($key);                                          if (@unlink($dest)) {                                                               // Invalidate cache if successfully written                                     opcache_invalidate($dest);                                                  }                                                                           }                                                                           }