2

It seems randomly every 10 minutes or more the cache seems to reset. I think I am using it wrong. I am using APC to cache a 3 MegaByte HTML response. About 50 of them at any given time. As far as I understand using mmap_file_mask will use files instead of memory, so it won't hog up my memory but I still think it runs out of memory and resets itself.

It is a VPS with 1 GB of memory, normally when running free it shows between 512MB and 750 MB used (this is with my current 256 MB SHM size). Should I increase my SHM size from 256 to something higher?

Should I use APC for doing this or is it better to store the responses in files and just use that instead?

My APC INI is as follows:

extension = apc.so

apc.enabled = 1
apc.shm_segments = 1
apc.shm_size = 256
apc.optimization = 0
apc.num_files_hint = 10000
apc.ttl = 0
apc.user_ttl = 0
apc.gc_ttl = 0
apc.cache_by_default = 1
apc.filters = ""
apc.mmap_file_mask = "/tmp/apc.XXXXXX"
apc.slam_defense = 0
apc.file_update_protection = 2
apc.enable_cli = 0
apc.max_file_size = 10M
apc.stat = 1
apc.write_lock = 1
apc.report_autofilter = 0
apc.include_once_override = 0
apc.localcache = 0
apc.localcache.size = 512
apc.coredump_unmap = 0
apc.stat_ctime = 0

Edit: I updated the memory to 512 MB and it lasted for a few hours, and then I went to bed. When I woke up all the cache's were gone. Seems it could be a memory issue? I might just rely on files or MySQL, debugging APC isn't worth the milliseconds of time saved on page load.

Here is the info as asked:

[num_slots] => 8192
[ttl] => 0
[num_hits] => 490
[num_misses] => 390
[num_inserts] => 13663
[expunges] => 0
[start_time] => 1355644615
[mem_size] => 5271328
[num_entries] => 204
[file_upload_progress] => 1
[memory_type] => mmap
[locking_type] => pthread mutex
[cache_list] => Array

And then it just displays the array of the caches, nothing really useful for debugging any issues I think. Nothing stands out pre-cache clearing. Not much changes from pre and post random cache clearer. No idea of the issue, 512 MB of memory should be enough for 3 MB x 50 entries. Even then, I don't even want it to use memory. I want it to use files.

Edit 2:

As requested, here is the APC code I use:

<?php
$unique_options = "query_options_that_are_unique_to_1_of_the_50_caches";

$refresh_interval = 60*15;
$refresh_triggered = (isset($_REQUEST['refresh']));


// Try to get the APC Cache, if fails, then it was never created
if ($cache_array = apc_fetch(md5($unique_options))) {
    // I got the cache, using its creation_time, see if its refreshable
    $seconds_since_last_refresh = (time() - $cache_array['creation_time']);
    $can_refresh = ($seconds_since_last_refresh >= $refresh_interval);
} else {
    // Apparently this has never had a cache created, so create it
    apc_store(md5($unique_options), array('data'=> get_json($unique_options), 'creation_time'=>time()), 0);
    $cache_array = apc_fetch(md5($unique_options));
    $refresh_triggered = false;
}

// If the cache already existed, and the user is attempting to refresh the cache, and they are allowed to refresh it, then refresh it.
if($refresh_triggered) {
    if($can_refresh) {
        apc_store(md5($unique_options), array('data'=> get_json($unique_options), 'creation_time'=>time()), 0);
        $cache_array = apc_fetch(md5($unique_options));
    } else {
        echo "You can only refresh every 15 minutes<br><br>";
    }
}

$current_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && !in_array(strtolower($_SERVER['HTTPS']),array('off','no'))) ? 'https' : 'http' . '://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$url_parts = parse_url($current_url);
$url_without_query = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];

foreach($_GET as $key => $value) {
    if($key != "refresh")
        $query .= "$key=$value&";
}
echo "Data was last refreshed " . ($seconds_since_last_refresh) . "seconds  ago  (<a href='$url_without_query?{$query}refresh'>Refresh Now</a>)<br><br>";


$data = $cache_array['data'];

// Now process the the information that was cached
// ...
?>
ParoX
  • 5,685
  • 23
  • 81
  • 152
  • So what now. Is the cache reset randomly or not? What do the info functions say? – hakre Dec 15 '12 at 19:19
  • Added the useless info function output. – ParoX Dec 16 '12 at 08:22
  • The info shows that the cache **is not reset**. You likely have an error in your code, not in APC. Additionally you've cutted the `cache_list` in the output. You should display it, soo. Also you should show the code how you generated the info data. – hakre Dec 16 '12 at 08:25
  • I updated it with my APC code, note that this was before I knew I had access to creation_time via the info array – ParoX Dec 16 '12 at 11:49
  • 1
    Is PHP run as a module on Apache are through fastcgi? If fastcgi then are you using PHP-FPM? Certain configs with fastcgi but without php-fpm do not use a shared cache but a cache per PHP process giving unexpected results. – Eelke Dec 16 '12 at 11:54
  • PHP is ran as a module on Apache – ParoX Dec 16 '12 at 12:23

3 Answers3

1

Never use a ttl of 0. APC will flush all cache when it runs out of memory.

Use the apc.php script to see the use of the memory. You should keep 20% of free memory (after hours running).

If you don't have enough ram, just fine tune APC to cache only the most frequenlty accessed files.

Check my answer here (not the one with the 46 vote up wich is wrong) What is causing "Unable to allocate memory for pool" in PHP?

Community
  • 1
  • 1
bokan
  • 3,601
  • 2
  • 23
  • 38
  • the `sysctl -a | grep -E "shmall|shmmax"` commands gave me: `error: "Operation not permitted" reading key "net.ipv4.route.flush" kernel.shmall = 2097152 kernel.shmmax = 33554432` However, I think because I am using `mmap` it's OK? None the less Ill change the ttl and report back – ParoX Dec 17 '12 at 14:30
  • Start by using the apc.php script from the APC package, it will tell you wether your APC uses mmap or shm. – bokan Dec 17 '12 at 16:36
  • the apc.php is nice. I am using mmap. I set the ttl to be 1 day, and 6 hours later my cache I had set was gone. I don't think it was memory issues because whenever I checked APC it had 280 MB used of the 512 I gave it. I had actived the "deleted" scope in APC but it yielded nothing for me. I am still confused as to why but I am just going to store in files/mysql the old fashion way. – ParoX Dec 18 '12 at 00:35
1

I had exactly the same problem and it was driving me nuts!

The actual cause of this was the servers time being different to the scripts set time.

Check the date on the server using this command on the commandline:

date

And then check your PHP time using:

<?php echo date("Y-m-d H:i:s"); ?>

If there is a difference (which is what I had), then this is why the cache is being cleared.

Checking my apc.php file I have entries for over 40 minutes now, before they would have been cleared after 10 minutes. Woohoo!

If your date/time is different, then you can either set the servers time using the date command see here or set the PHP timezone to match the servers using:

date_default_timezone_set('UTC');

You can find a list of the supported timezones for this function here: http://www.php.net/manual/en/timezones.php

I hope this helps you, I spent ages converting my scripts to use APC, it's lightening fast and now they're being stored & saved for the length of times that I'm specifying.

Matthew Ogborne
  • 544
  • 2
  • 6
  • 20
0

I ran into the same issue today, found the solution here: http://www.itofy.com/linux/cpanel/apc-cache-reset-every-2-hours/

You need to go to AccesWHM > Apache Configuration > Piped Log Configuration and Enable Piped Apache Logs.

Raheel Hasan
  • 5,753
  • 4
  • 39
  • 70