【问题标题】:Make ZVAL persistent across the SAPI?让 ZVAL 在 SAPI 中持久化?
【发布时间】:2012-04-17 15:28:25
【问题描述】:

ZVAL 通常是使用 emalloc 创建的,因此它会在页面请求结束时被销毁。有没有办法获取现有的 ZVAL 并使其在 SAPI 中持续存在(相当于 pemalloc)?用 pemalloc 创建 ZVAL 怎么样?

理想情况下我想做的(在 PHP 代码中)是这样的:

class Object
{
    public $foo;
}

if(!($object = persist("object")))
{
   $object = persist("object", new Object());
}

$object->foo[] = "bar";

print count($object->foo);

count 每次请求都会返回 +1(假设每次都使用相同的 PHP“worker” - 我正在使用 PHP-FPM)。

【问题讨论】:

  • 作为一个有趣的说明:我们决定改变平台。我们现在将使用 Go。
  • 酷。你能详细说明原因吗?我在看自己去,很高兴知道其他人的动机。
  • 我们需要一个活动的应用程序实例。我们还需要并行执行。我们也评估了 Node 和 Java。 Node 是单线程的并使用异步模型。 Java 使用传统的线程模型(困难)。 Go 使并行执行变得非常容易,并且还有一些其他不错的功能。最重要的是,Go 是编译好的,但具有脚本语言的灵活性。它获得了很大的吸引力。它是新的,但我们认为它至少比 PHP 快:)。

标签: php-extension php-internals


【解决方案1】:

zend_object 不能持久,因此你不能这样做。 APC 等扩展将对象序列化到内存中。

【讨论】:

    【解决方案2】:

    你基本上是在描述http://lxr.php.net/opengrok/xref/PHP_5_3/ext/sysvshm/sysvshm.c#242

    在不复制 shm 中已有功能的情况下,您可以获得的最接近的是 https://github.com/flavius/php-persist。问题:在 prefork/多进程 SAPI(如 apache)中,来自同一客户端的不同请求可能最终在不同的进程中,因此,您将看到不同的数据(在 Linux + Firefox 上尝试每次都进行硬刷新在浏览器中)。

    注意:这是一个正在进行的工作,目前它只保留一个整数。添加一个数组应该是微不足道的。欢迎补丁。它仍然需要反序列化部分,并实际使用persist()的第一个参数。

    【讨论】:

    • 其实没关系。它不需要跨不同的进程/线程持续存在。目标是预先加载某些对象,这样就不必每次都初始化它们。
    • 如果我要保留对父 zval 的引用并将其标记为永久或在请求关闭之前复制它会怎样。那应该可以,我只是不确定如何使现有的 zval 永久化。我知道我可以使用 ALLOC_PERMANENT_ZVAL 宏创建一个新的永久 zval。
    • 什么是“父zval”?无论如何它是行不通的,因为 zval 可能同时消失了,或者更糟:它可能已经被另一个 zval 取代(所以如果你幸运的话,你可能会在 zval 中得到另一个值,如果没有,你'会得到一个段错误)。
    • 在我的例子中是“$object”。基本上我在想我可以将引用计数增加 1 并跟踪哈希表中的 zval。然后在请求关闭扩展中,通过将 zval 及其子项标记为持久性或使用 permalloc 进行深层复制来使 zval 持久化。如果有人覆盖了 $object 或者它超出了应该没问题的范围 - 增加的 refcount 应该防止它被 gc'd。它只跟踪放置在 persist() 函数中的 zval。之后变量 $object 就无关紧要了。但是应该捕获对比例子项的更改。
    • @Luke 我已经实现了你的想法,反序列化部分仍然需要完成。它仅适用于单个 zval*。如果您有兴趣,请随时发送拉取请求。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 2011-05-31
    • 2014-12-12
    相关资源
    最近更新 更多