我看到了不同的 PHP 二进制文件,比如非线程还是线程安全的?
这是什么意思?
这些包有什么区别?
原文由 O.. 发布,翻译遵循 CC BY-SA 4.0 许可协议
我看到了不同的 PHP 二进制文件,比如非线程还是线程安全的?
这是什么意思?
这些包有什么区别?
原文由 O.. 发布,翻译遵循 CC BY-SA 4.0 许可协议
1 回答4.2k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
2 回答2.3k 阅读✓ 已解决
2 回答853 阅读✓ 已解决
1 回答1.4k 阅读✓ 已解决
2 回答2.3k 阅读
1 回答717 阅读✓ 已解决
其他答案涉及 SAPI 实现,虽然这是相关的,但问题询问线程安全与非线程安全分布之间的区别。
首先,PHP 被编译为可嵌入库,例如 *NIX 上的 libphp.so 和 Windows 上的 php.dll。这个库可以嵌入到任何 C/CPP 应用程序中,但显然它主要用于 Web 服务器。 PHP 的核心在两个主要阶段启动,模块初始化阶段和请求初始化阶段。模块 init 初始化 PHP 核心和所有扩展,其中 request init 初始化 PHP 用户空间 - 本地用户空间功能以及 PHP 代码本身。
PHP 库设置为只需要调用一次模块阶段,但必须为每个 HTTP 请求重新初始化请求阶段。请注意,CLI 链接到与 mod_php 等相同的库,并且仍然必须在内部经历这些阶段,即使它可能不会在处理 HTTP 请求的上下文中使用。此外,需要注意的是,PHP 并不是为处理 HTTP 请求而设计的——最准确地说,它是为处理 CGI 事件而设计的。同样,这不仅仅是 php-cgi,而是所有 SAPI/应用程序,包括 php-fpm、mod_php、CLI,甚至是极其罕见的 PHP 桌面应用程序。
链接到 libphp 的 Web 服务器(或更典型的 SAPI)倾向于遵循以下四种模式之一:
请注意,在示例 2 和 3 中,子进程通常在每次请求后终止。在示例 2 中,子进程必须在每个请求结束时终止。
第四个示例与线程实现有关
在线程的情况下,请求处理线程倾向于使用线程池,每个线程在循环中运行,在开始时初始化请求阶段,而不是在结束时销毁请求阶段,这比每个请求产生一个新线程更优化
不管线程实现如何利用 libphp,如果模块阶段在一个线程中初始化并且请求阶段在不同的线程中调用(这是 PHP 设计的情况),它需要大量的同步,而不仅仅是在 PHP核心,但也在所有原生 PHP 扩展中。请注意,此时这不仅仅是“请求”的问题,而是根据 PHP OPCODE 调用它的同步问题,这依赖于存在于不同线程中的 PHP 核心(或任何 PHP 扩展)中的任何形式的资源作为 PHP 用户空间。
这对线程安全的 PHP 发行版中的同步提出了巨大的要求,这就是为什么 PHP 倾向于遵循“不共享”规则以帮助最小化影响,但是在这种模式中没有真正的“不共享”这样的东西,除非每个线程都包含一个完全独立的 PHP 上下文,其中模块阶段和请求阶段都在每个请求的同一线程中完成,这是不建议或不支持的。如果在模块初始化阶段构建的上下文与请求初始化阶段一样位于单独的线程中,那么线程之间肯定会共享。所以最好的尝试是在模块初始化阶段最小化必须在线程之间共享的上下文,但这并不容易,在某些情况下是不可能的。
在更复杂的扩展中尤其如此,这些扩展对必须如何在线程之间共享自己的上下文有自己的要求,openssl 是这个示例的主要罪魁祸首,它有效地向外扩展到使用它的任何扩展,无论是内部的,例如PHP 流处理程序或外部的,如套接字、curl、数据库扩展等。
如果在这一点上不明显,线程安全与非线程安全不仅仅是 PHP 如何在 SAPI 实现中作为“请求处理程序”在内部工作的问题,而是 PHP 如何在内部作为嵌入式虚拟机工作的问题一种编程语言。
这一切都是由 TSRM 或线程安全资源管理器实现的,它制作精良,可以处理大量同步而几乎没有感知到的开销,但开销肯定存在,并且不仅会根据每个请求的数量而增长其次,服务器必须处理(决定 SAPI 需要多少线程的决定因素),还有每个请求(或每次执行)使用多少 PHP 代码。换句话说,大型臃肿的框架可以在 TSRM 开销方面产生真正的影响。这并不是说线程安全 PHP 中的整体 PHP 性能和资源要求,而只是说线程安全 PHP 中 TSRM 本身的额外开销。
因此,预编译的 PHP 以两种形式分发,一种是在 TSRM 在 libphp 中处于活动状态(线程安全)中构建的,另一种是 libphp 不使用任何 TSRM 功能(非线程安全),因此没有 TSRM 的开销.
另请注意,用于使用 TSRM 编译 PHP 的标志(在以后的 PHP 版本中为 –enable-maintainer-zts 或 –with-zts)导致 phpize 将其向外扩展到扩展的编译以及它们如何初始化自己的库(libssl 、libzip、libcurl 等),它们通常有自己的编译线程安全和非线程安全实现的方式,即它们自己的同步机制在 TSRM 和 PHP 之外作为一个整体。虽然这并不完全与 PHP 相关,但最终仍会对 TSRM 之外的 PHP 性能产生影响(意思是 _在 TSRM 之上_)。因此,PHP 扩展(及其依赖项,以及外部库 PHP 或扩展链接到或以其他方式依赖)在广告安全的 PHP 发行版中通常具有不同的属性。