我很好奇,在PHP中序列化是否有大小限制。能否将包含5000个键和值的数组序列化以便存储到缓存中?
我希望能在社交网络网站上缓存用户的好友列表,缓存需要经常更新,但几乎每次加载页面时都需要读取。
在单个服务器设置中,我认为APC比memcache更适合这种情况。
我很好奇,在PHP中序列化是否有大小限制。能否将包含5000个键和值的数组序列化以便存储到缓存中?
我希望能在社交网络网站上缓存用户的好友列表,缓存需要经常更新,但几乎每次加载页面时都需要读取。
在单个服务器设置中,我认为APC比memcache更适合这种情况。
正如其他人已经回答的那样,仅仅是为了好玩,这里有一个非常快速的基准测试(我敢称之为基准测试吗?);考虑以下代码:
转换后:
正如其他人已经回答的那样,仅仅是为了好玩,这里有一个非常快速的基准测试(我敢称之为 "基准测试" 吗?);考虑以下代码:
$num = 1;
$list = array_fill(0, 5000, str_repeat('1234567890', $num));
$before = microtime(true);
for ($i=0 ; $i<10000 ; $i++) {
$str = serialize($list);
}
$after = microtime(true);
var_dump($after-$before);
var_dump(memory_get_peak_usage());
我正在PHP 5.2.6上运行(与Ubuntu jaunty捆绑在一起的那个版本)。
是的,这里只有值;没有键;而且这些值相当简单:没有对象,没有子数组,除了字符串之外什么都没有。
对于$num = 1
,你会得到:
float(11.8147978783)
int(1702688)
对于$num = 10
,你会获得:
float(13.1230671406)
int(2612104)
假设$num = 100
,那么你会得到:
float(63.2925770283)
int(11621760)
所以,似乎数组中每个元素越大,花费的时间就越长 (其实这很公平)。但是,对于比原来大100倍的元素,你不需要多花费100倍的时间...
现在,数组有50000个元素,而不是5000个,这意味着代码的这部分已经改变:
$list = array_fill(0, 50000, str_repeat('1234567890', $num));
如果 $num = 1
,你将得到:
float(158.236332178)
int(15750752)
考虑到 $num = 10 和 $num = 100 的运行时间,我不会运行此代码...
当然,在实际情况中,您不会执行10000次;因此,让我们只尝试使用for循环的10个迭代。
对于 $num = 1
:
float(0.206310987473)
int(15750752)
对于 $num = 10
:
float(0.272629022598)
int(24849832)
对于 $num = 100
:
float(0.895547151566)
int(114949792)
是的,时间差不多是1秒钟 -- 用了相当多的内存 ^^
(不,这不是生产服务器: 我在这台开发机器上设置了很高的memory_limit ^^)
所以,最终比那些数字要简短一点-- 是的,你可以让数字说任何你想要的话--我不会说有一个 在 PHP 中是“硬编码”的“限制”,但你最终会面临其中之一:
max_execution_time
(通常在Web服务器上,它从来没有超过30秒)memory_limit
(在Web服务器上,它通常不超过32MB)但是,除非您真的正在序列化大数据的长数组,否则我不确定它是否会太重要......
您必须考虑使用该缓存可能帮助您获得的时间/ CPU负载量;-)
然而,最好的方法是通过使用真实数据自己测试;-)
PHP 没有设置限制。序列化返回序列化结构的字节流表示(字符串),因此您只会得到一个大字符串。
没有限制,但请记住序列化和反序列化是有成本的。
反序列化的成本非常高。
一种更经济的缓存数据的方法是使用var_export()
,如下所示(自 PHP 5.1.0 起,它适用于对象):
$largeArray = array(1,2,3,'hello'=>'world',4);
file_put_contents('cache.php', "<?php\nreturn ".
var_export($largeArray, true).
';');
$largeArray = include('cache.php');
资源通常不可缓存。
不幸的是,如果您的数组中存在循环引用,则需要使用serialize()
函数。
$string = json_encode($your_array_here);
并对其进行解码
$array = json_decode($your_array_here, true);
这个函数返回一个数组。即使编码后的数组是多层的,它也能正常工作。
json_decode()
**函数无用,并返回错误。 - EffectiXjson_decode()
自动解码这些 UTF-8 编码的字符。只要不破坏编码字符前面的斜杠,就一切都会没问题。 - EffectiX好的...更多数字!(PHP 5.3.0 OSX,没有opcode缓存)
@Pascal的代码在我的机器上,当n=1且迭代10k次时,结果为:
float(18.884856939316)
int(1075900)
$num = 1;
$list = array_fill(0, 5000, str_repeat('1234567890', $num));
$before = microtime(true);
for ($i=0 ; $i<10000 ; $i++) {
$str = serialize($list);
$list = unserialize($str);
}
$after = microtime(true);
var_dump($after-$before);
var_dump(memory_get_peak_usage());
float(50.204112052917)
int(1606768)
$str = var_export($list, true);
感到好奇,它们替代了原本使用的 serialize()。float(57.064643859863)
int(1066440)
仅仅比这个简单的示例少了一点内存,但时间已经更长了。
在上面使用 eval(“$list =”.$str。”;”)
而不是反序列化会产生以下结果
float(126.62566018105)
int(2944144)
执行eval时,很可能存在内存泄漏的问题 :-/。
因此,这些并不是很好的基准测试(我真的应该通过将字符串放在本地变量中来隔离eval/unserialize,但我有点懒),但它们显示了相关趋势。var_export似乎比较慢。
不,没有限制,而且这个:
set_time_limit(0);
ini_set('memory_limit ', -1);
unserialize('s:2000000000:"a";');
这就是为什么你应该打开safe.mode或者安装Suhosin这样的扩展,否则它会耗尽你系统中所有的内存。
TEXT
字段将序列化对象持久化到数据库中。TEXT
字段的限制而无法对它们进行反序列化。我认为比序列化更好的是json_encode函数。它有一个缺点,就是无法区分关联数组和对象,但字符串结果更小,对人类来说更容易阅读、调试和编辑。