1
0
mirror of https://github.com/php/doc-zh.git synced 2026-03-24 07:02:15 +01:00
Files
archived-doc-zh/reference/opcache/preload.xml
2026-01-18 19:38:54 +00:00

116 lines
5.8 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 87d6bb1bbd5f118f5b0cf0160438f06c0f91ea45 Maintainer: jhdxr Status: ready -->
<!-- CREDITS: Luffy -->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="opcache.preloading">
<title>预加载</title>
<simpara>
从 PHP 7.4.0 起PHP 可以被配置为在引擎启动时将一些脚本预加载进 opcache 中。在那些文件中的任何函数、类、
接口或者 trait (但不包括常量)将在接下来的所有请求中变为全局可用,不再需要显示地包含它们。这牺牲了基准的
内存占用率但换来了方便和性能(因为这些代码将始终可用)。它还需要通过重启 PHP 进程来清除预加载的脚本,
这意味着这个功能仅在生产环境中有实用价值,而非开发环境。
</simpara>
<simpara>
需要注意的是,性能和内存之间的最佳平衡因应用而异。 “预加载一切” 可能是最简单的策略,但不一定是最好的策略。
此外,只有当不同的请求间有持久化的进程时,预加载才有用。这意味着,虽然在启用了 opcache 的命令行脚本中可以使用预加载,
但这通常是没有意义的。例外情况是在使用预加载时的 <link linkend="ffi.examples-complete">FFI 库</link>
</simpara>
<note>
<simpara>
Windows 上不支持预加载。
</simpara>
</note>
<simpara>
配置预加载需要两步,并且要求开启 opcache。首先&php.ini; 中设置
<link linkend="ini.opcache.preload">opcache.preload</link> 的值:
</simpara>
<informalexample>
<programlisting role="ini">
<![CDATA[
opcache.preload=preload.php
]]>
</programlisting>
</informalexample>
<simpara>
<filename>preload.php</filename> 是一个在服务器启动时会运行一次PHP-FPM、mod_php 等)的任意文件,
它的代码会加载到持久化内存中。在以 root 用户启动后切换到非特权系统用户的服务器上,又或者是以 root
用户身份运行 PHP 的情况(不建议这样做),可以通过<link linkend="ini.opcache.preload-user">opcache.preload_user</link>
来指定进行预加载的系统用户。
默认情况下,不允许以 root 用户身份进行预加载。通过设置 <literal>opcache.preload_user=root</literal> 来显示地允许它。
</simpara>
<simpara>
<filename>preload.php</filename> 脚本中, 任何被 <function>include</function>
<function>include_once</function><function>require</function><function>require_once</function>
<function>opcache_compile_file</function> 引用的文件将被解析到持久化内存中。 在下面的这个例子中,
所有在 <filename>src</filename> 目录下的 <filename class="extension">.php</filename> 文件将被预加载,除非那是一个
<literal>Test</literal> 文件。
</simpara>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$directory = new RecursiveDirectoryIterator(__DIR__ . '/src');
$fullTree = new RecursiveIteratorIterator($directory);
$phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);
foreach ($phpFiles as $key => $file) {
require_once $file[0];
}
?>
]]>
</programlisting>
</informalexample>
<para>
<function>include</function><function>opcache_compile_file</function> 都会生效,但对代码处理方式有不同的影响。
Both <function>include</function> and <function>opcache_compile_file</function> will work, but have different
implications for how code gets handled.
<itemizedlist>
<listitem><simpara><function>include</function> 将执行文件中的代码,而 <function>opcache_compile_file</function>
不会执行代码。这意味着只有前者支持条件声明(在 if 块中声明函数)。</simpara></listitem>
<listitem><simpara>由于 <function>include</function> 会执行代码,因此所有被 <function>include</function> 的文件也将被解析,
其中的定义也将被预加载。</simpara></listitem>
<listitem><simpara><function>opcache_compile_file</function> 可以按任何顺序加载文件。也就是说,如果 <filename>a.php</filename>
定义了类 <literal>A</literal>,而 <filename>b.php</filename> 定义了一个继承类 <literal>A</literal> 的类 <literal>B</literal>
<function>opcache_compile_file</function> 可以按任何顺序来加载这两个文件。然而,当使用 <function>include</function> 时,
<filename>a.php</filename> <emphasis>必须</emphasis> 先被包含。</simpara></listitem>
<listitem><simpara>不管在哪种情况下,如果一个脚本包含了一个已经被预加载的文件,那么这个已经被预加载的文件里的内容仍将被执行,
但其中定义的任何符号将不会被重新定义。使用 <function>include_once</function> 不会阻止文件被二次包含。有时候可能仍需要重新加载文件
来包含其中定义的全局常量,因为这些常量预加载并不会处理。</simpara></listitem>
</itemizedlist>
因此,哪种方式更好取决于所需的行为。对于本来会使用自动加载器的代码,<function>opcache_compile_file</function>
有更高的灵活性。而对于本来会需要手动加载的代码,<function>include</function> 会更健壮。
</para>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->