我正在使用APC将类名映射存储到类文件路径。我在自动加载功能中构建了这样的地图:
$class_paths = apc_fetch('class_paths');
// If the class path is stored in application cache - search finished.
if (isset($class_paths[$class])) {
return require_once $class_paths[$class];
// Otherwise search in known places
} else {
// List of places to look for class
$paths = array(
'/src/',
'/modules/',
'/libs/',
);
// Search directories and store path in cache if found.
foreach ($paths as $path) {
$file = DOC_ROOT . $path . $class . '.php';
if (file_exists($file)) {
echo 'File was found in => ' . $file . '<br />';
$class_paths[$class] = $file;
apc_store('class_paths', $class_paths);
return require_once $file;
}
}
}
我可以看到,随着越来越多的类被加载,它们被添加到地图中,但在某些时候apc_fetch
在页面请求的中间返回NULL
,而不是返回地图
Getting => class_paths
Array
(
[MCS\CMS\Helper\LayoutHelper] => /Users/mbl/Documents/Projects/mcs_ibob/core/trunk/src/MCS/CMS/Helper/LayoutHelper.php
[MCS\CMS\Model\Spot] => /Users/mbl/Documents/Projects/mcs_ibob/core/trunk/src/MCS/CMS/Model/Spot.php
)
Getting => class_paths
{null}
很多时候,缓存的值也会在页面请求之间消失。
这可能是什么原因?
我正在使用APC作为运行PHP 5.3的扩展程序(PECL)。
更新 在下面的评论中,您将看到人们声称APC不是持久性的,并且它不值得信任。但在我的情况下,代码在15-50ms之间的一个页面请求中执行。我不应该长期信任 APC吗?
更新
似乎缓存包含具有相同密钥的多个条目,当它应该只包含一个时 - 在调用apc_store()
时覆盖该值。我希望这可以帮助别人理解这个问题。 (我已经禁用了强力防守并写锁定)
Array
(
[num_slots] => 4099
[ttl] => 0
[num_hits] => 0
[num_misses] => 3
[num_inserts] => 9678
[expunges] => 0
[start_time] => 1293109072
[mem_size] => 40064
[num_entries] => 8
[file_upload_progress] => 1
[memory_type] => mmap
[locking_type] => file
[cache_list] => Array
(
[0] => Array
(
[info] => fSchema::mysql::fORM::default::/Users/mbl/Documents/Projects/mcs_ibob/core/trunk/public_html/::::column_info
[ttl] => 0
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 12456
)
[1] => Array
(
[info] => mcs:odk:class_paths
[ttl] => 3600
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 648
)
[2] => Array
(
[info] => mcs:odk:class_paths
[ttl] => 3600
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 648
)
[3] => Array
(
[info] => mcs:odk:class_paths
[ttl] => 3600
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 648
)
[4] => Array
(
[info] => mcs:odk:class_paths
[ttl] => 3600
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 648
)
[5] => Array
(
[info] => mcs:odk:class_paths
[ttl] => 3600
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 648
)
[6] => Array
(
[info] => mcs:odk:class_paths
[ttl] => 3600
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 648
)
[7] => Array
(
[info] => fSchema::mysql::fORM::default::/Users/mbl/Documents/Projects/mcs_ibob/core/trunk/public_html/::::merged_column_info
[ttl] => 0
[type] => user
[num_hits] => 0
[mtime] => 1293109072
[creation_time] => 1293109072
[deletion_time] => 0
[access_time] => 1293109072
[ref_count] => 0
[mem_size] => 23720
)
)
[deleted_list] => Array
(
)
)
答案 0 :(得分:5)
这不是持久性存储。 您可以通过增加APC的内存大小来改进它,但无论如何,没有任何保证。 因此,如果您看到它们被丢弃,您应该重新启动它们。
答案 1 :(得分:4)
我将尝试从我所学到的内容中回答我自己的问题。
首先,正如许多人正确指出的那样。
APC is not persistent.
如果没有实际的解释,或者更好的指导如何使用它,我很难接受这个声明。
我发现有一些规则或相当陷阱需要注意 - 很多人仍然没有找到我。使用APC API意味着使用apc_fetch
和apc_store
这两个都可能失败,或者更正确地放置,错过。当你期望数据是神秘所在的时候,为什么你有时会收到NULL
。
以下是一些随机信息:
缓存条目的秒数 允许在插槽中闲置,以防万一 另一个需要缓存输入槽 条目。将此保留为零意味着 APC的缓存可能会填满 在较新的条目时使用过时的条目 不会被缓存。 - http://php.net/manual/en/apc.configuration.php
与apc.ttl
和apc.user_ttl
一起玩,直到找到适合自己的内容为止 - 直到您看到很多点击而不是很多条目。
apc_fetch
和apc_store
可以返回NULL
,原因有很多,有些原因如上所述,例如ttl另一个原因可能是密钥提取超时。但重点是设计 - 围绕它。期待这一点。
如果你喜欢我一直对APC的行为感到非常沮丧,请看看这篇由scoates指出的文章:http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan。它不会给你很多答案,但是有一些关于缓存设计的基本知识,或许像我一样,我并不孤单的一些事情:)
在我的问题中描述的类路径问题的情况下,我决定使用局部变量来构建缓存,然后在最后通过一次apc_store
调用将其存储在缓存中。这导致命中率上升,每个键的缓存条目下降 - 我的代码现在运行得很快。
答案 2 :(得分:-2)
APC是持久的,但每个apache进程都是独立的。
PHP为每个apache进程建立一个单独的APC CACHE存储,这是完全正常的,因为每个apache进程都有自己的内存空间。