-
Notifications
You must be signed in to change notification settings - Fork 82
Expand file tree
/
Copy pathpreload.xml
More file actions
149 lines (133 loc) · 7.42 KB
/
preload.xml
File metadata and controls
149 lines (133 loc) · 7.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 87d6bb1bbd5f118f5b0cf0160438f06c0f91ea45 Maintainer: mumumu Status: ready -->
<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 以降では、エンジンの起動時に opcache に事前ロードするスクリプトを指定できるようになりました。
指定されたファイルに存在するあらゆる 関数、クラス、
インターフェイス や トレイト (定数は除く) は、
明示的にインクルードすることなく全てのリクエストからグローバルに利用できるようになります。
これにより(コードが常に利用できるようになるため)、メモリ使用量と、
パフォーマンスおよび便利さのトレードオフが発生します。
事前ロードされたスクリプトをクリアするには PHP プロセスの再起動が必要です。
つまり、この機能は本番環境でのみ役に立ちます。開発環境では役に立ちません。
</simpara>
<simpara>
パフォーマンスとメモリ使用量の最適なトレードオフは、アプリケーションによって異なることに注意して下さい。
"全てをあらかじめ読み込む" ことはもっとも簡単な戦略かもしれませんが、
必ずしも最適とは限りません。
さらに、コードの事前ロードは、リクエストが終了しても継続して生き残るプロセスの場合にだけ役に立ちます。
つまり、opcache が有効になった CLI スクリプトは動作はしますが、
一般的にコードの事前ロードは役に立ちません。
但し、<link linkend="ffi.examples-complete">FFI</link> 経由でコードの事前ロードを使う場合は例外です。
</simpara>
<note>
<simpara>
コードの事前ロードは、Windows ではサポートされていません。
</simpara>
</note>
<simpara>
コードの事前ロードを設定するには、2つのステップが必要です。
まず、opcache を有効にしなければなりません。
その上で、<link linkend="ini.opcache.preload">opcache.preload</link> の値を &php.ini; に設定します。
</simpara>
<informalexample>
<programlisting role="ini">
<![CDATA[
opcache.preload=preload.php
]]>
</programlisting>
</informalexample>
<simpara>
<filename>preload.php</filename> は、サーバーの起動時(PHP-FPM, mod_php, など)
に一度だけ実行され、リクエストを越えて生き残るメモリ領域に読み込まれる任意のファイルです。
特権のないシステムユーザに切り替える前に root で起動するサーバーの場合や、
PHP が root 権限で実行(推奨されません)される場合のために、
<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>
両方が動作しますが、コードをどう扱うかが異なります。
<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
-->