[MANUAL] English:
[zend.git] / documentation / manual / fr / ref / performance-classloading.xml
blob0f62e279b66cb13bca9608e40e224ef27f42e928
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 20876 -->
3 <!-- Reviewed: no -->
4 <sect1 id="performance.classloading">
5     <title>Chargement des classes</title>
7     <para>
8         Tous ceux qui ont déjà réalisé le profilage d'une application Zend Framework
9         reconnaîtront immédiatement que le chargement des classes y est relativement coûteux. Entre
10         le nombre important de fichier de classe qui doivent être chargées pour un grand nombre de
11         composants et l'utilisation des plugins qui n'impliquent pas une relation 1:1 entre leur nom
12         de classe et le système de fichier, les différents appels de <code>include_once</code> et
13         <code>require_once</code> peuvent être problématique. Ce chapitre a pour but de fournir des
14         solutions concrètes pour solutionner ces problèmes.
15     </para>
17     <sect2 id="performance.classloading.includepath">
18         <title>Comment optimiser mon include_path&#160;?</title>
20         <para>
21             Une optimisation triviale pour accélérer la vitesse de chargement des classes est
22             de faire attention à votre <code>include_path</code>. En particulier, vous devriez faire
23             quatre choses&#160;: utilisez des chemins absolus (ou des chemins relatifs à des chemins
24             absolus), réduire le nombre des chemins à inclure, définir le dossier de Zend Framework
25             le plus tôt possible dans l'<code>include_path</code> et inclure le dossier courant en
26             dernier dans votre <code>include_path</code>.
27         </para>
29         <sect3 id="performance.classloading.includepath.abspath">
30             <title>Utiliser des chemins absolus</title>
32             <para>
33                 Tandis que ceci peut sembler une micro-optimisation, le fait est que si vous
34                 ne le faites pas, vous n'obtiendrez qu'un très petit avantage de la mise en cache du
35                 realpath de PHP, et en conséquence, le cache d'opcode ne fonctionnera pas tout à
36                 fait comme vous pourriez l'imaginer.
37             </para>
39             <para>
40                 Il y a deux manières simples de s'assurer de ceci. Premièrement, vous pouvez
41                 le mettre en dur dans votre <filename>php.ini</filename>,
42                 <filename>httpd.conf</filename>, ou <filename>.htaccess</filename>. Deuxièmement,
43                 vous pouvez utiliser la fonction <code>realpath()</code> de PHP au moment du
44                 paramétrage de votre <code>include_path</code>&#160;:
45             </para>
47             <programlisting language="php"><![CDATA[
48 $paths = array(
49     realpath(dirname(__FILE__) . '/../library'),
50     '.',
52 set_include_path(implode(PATH_SEPARATOR, $paths);
53 ]]></programlisting>
55             <para>
56                 Vous <emphasis>pouvez</emphasis> utiliser des chemins relatifs - du moment
57                 qu'ils sont relatifs à un chemin absolu&#160;:
58             </para>
60             <programlisting language="php"><![CDATA[
61 define('APPLICATION_PATH', realpath(dirname(__FILE__)));
62 $paths = array(
63     APPLICATION_PATH . '/../library'),
64     '.',
66 set_include_path(implode(PATH_SEPARATOR, $paths);
67 ]]></programlisting>
69             <para>
70                 Néanmoins, c'est typiquement une tâche insignifiante de fournir simplement le
71                 chemin à <code>realpath()</code>.
72             </para>
73         </sect3>
75         <sect3 id="performance.classloading.includepath.reduce">
76             <title>Réduire le nombre de dossier défini dans l'include_path</title>
78             <para>
79                 Les chemins d'inclusion sont scannés dans l'ordre dans lequel ils apparaissent
80                 dans l'<code>include_path</code>. Évidemment, ceci veut dire que vous aurez un
81                 résultat plus rapide si le fichier est trouvé dans le premier chemin scanné que si
82                 vous le trouvez dans le dernier chemin scanné. De plus, une amélioration plutôt
83                 évidente est de diminuer tout simplement le nombre de chemins dans votre
84                 <code>include_path</code> à seulement de ce que vous avez réellement besoin.
85                 Regardez chaque chemin que vous avez défini dans votre include_path pour déterminer
86                 si vous avez réellement besoin d'une fonctionnalité dans votre application&#160;; si
87                 ce n'est pas le cas, enlevez le.
88             </para>
90             <para>
91                 Une autre optimisation consiste en la combinaison de chemins. Par exemple,
92                 Zend Framework suit la convention de nommage PEAR&#160;; ainsi , si vous utilisez
93                 des librairies PEAR (ou d'autres framework ou librairies de composants qui
94                 respectent la convention de nommage PEAR), essayez de mettre toutes ces librairies
95                 dans le même chemin de l'<code>include_path</code>. Ceci peut souvent être réalisé
96                 par quelque chose d'assez simple comme de créer des liens symboliques vers une ou
97                 plusieurs bibliothèques dans un dossier commun.
98             </para>
99         </sect3>
101         <sect3 id="performance.classloading.includepath.early">
102             <title>
103                 Définir le dossier de Zend Framework le plus tôt possible dans l'include_path
104             </title>
106             <para>
107                 Pour continuer avec les suggestions précédentes, une autre optimisation
108                 évidente est de définir le dossier de Zend Framework le plus tôt possible dans votre
109                 <code>include_path</code>. Dans la plupart des cas, il devrait être le premier de la
110                 liste. Ceci permet de s'assurer les fichiers de Zend Framework à inclure le sont dès
111                 le premier scan.
112             </para>
113         </sect3>
115         <sect3 id="performance.classloading.includepath.currentdir">
116             <title>Définir le dossier courant le plus tard possible ou pas du tout</title>
118             <para>
119                 La plupart des exemples d'<code>include_path</code> montre l'utilisation du
120                 répertoire courant ("<code>.</code>"). Ceci est pratique pour s'assurer que les
121                 scripts dans le même dossier que le fichier courant peuvent aussi être chargés.
122                 Cependant ces mêmes exemples montrent souvent ce dossier comme étant le premier de
123                 la liste des include_path - ce qui veut dire l'arbre de dossiers courant est
124                 toujours scanné en premier. La plupart du temps, avec Zend Framework, ce n'est pas
125                 nécessaire, et ce dossier peut tout naturellement être mis en dernière position de
126                 la liste.
127             </para>
129             <example id="performance.classloading.includepath.example">
130                 <title>Exemple : optimisation de l'include_path</title>
132                 <para>
133                     Essayons de mettre ensemble toutes ces suggestions. Considérons que nous
134                     utilisons une ou plusieurs composants PEAR en conjonction avec Zend Framework -
135                     par exemple les composants PHPUnit et Archive_Tar - et qu'il est
136                     occasionnellement nécessaire d'inclure les fichiers relativement au fichier
137                     courant.
138                 </para>
140                 <para>
141                     Premièrement, nous allons créer un dossier pour les librairies dans notre
142                     projet. Dans ce même dossier, nous allons créer un lien symbolique vers notre
143                     dossier Zend Framework "<filename>library/Zend</filename>", ainsi que les
144                     dossiers nécessaires dans notre installation PEAR&#160;:
145                 </para>
147                 <programlisting language="php"><![CDATA[
148 library
149     Archive/
150     PEAR/
151     PHPUnit/
152     Zend/
153 ]]></programlisting>
155                 <para>
156                     Ceci nous permet d'ajouter notre propre librairie si nécessaire, tout en
157                     laissant intact les librairies partagées.
158                 </para>
160                 <para>
161                     Ensuite, nous optons pur la création de notre <code>include_path</code>
162                     par programme à l'intérieur de notre fichier
163                     <filename>public/index.php</filename>. Ceci nous permet de déplacer notre code
164                     dans le système de fichiers, sans devoir éditer l'<code>include_path</code> à
165                     chaque fois.
166                 </para>
168                 <para>
169                     Nous emprunterons des idées à chacune des suggestions ci-dessus : nous
170                     utiliserons les chemins absolus, déterminé en utilisant le
171                     <code>realpath()</code>&#160;; nous positionnerons Zend Framework au plus tôt
172                     dans l'<code>include_path</code> ; nous avons déjà vérifié les chemins
173                     d'inclusions nécessaires&#160;; et nous mettrons le dossier courant comme
174                     dernier chemin. En fait, nous faisons tout bien ici - nous allons donc terminer
175                     avec seulement deux chemins.
176                 </para>
178                 <programlisting language="php"><![CDATA[
179 $paths = array(
180     realpath(dirname(__FILE__) . '/../library'),
181     '.'
183 set_include_path(implode(PATH_SEPARATOR, $paths));
184 ]]></programlisting>
185             </example>
186         </sect3>
187     </sect2>
189     <sect2 id="performance.classloading.striprequires">
190         <title>Comment éliminer les déclarations require_once non nécessaires ?</title>
192         <para>
193             Le chargement tardif ("lazy loading") est une technique d'optimisation conçue pour
194             repousser l'opération coûteuse de chargement d'une classe jusqu'au dernier moment
195             possible - c'est-à-dire lors de l'instanciation d'un objet de cette classe, ou lors de
196             l'utilisation d'une constante de classe ou d'une propriété statique. PHP supporte tout
197             ceci via l'autoloading (ou "chargement automatique"), ce qui vous permet de définir un
198             ou plusieurs callbacks à exécuter dans le but de faire correspondre un nom de classe à
199             un fichier.
200         </para>
202         <para>
203             Cependant, la plupart des avantages que vous pourrez retirer de l'autoloading sont
204             diminués si le code de votre librairie exécute toujours des appels à
205             <code>require_once</code> - ce qui est précisément le cas de Zend Framework. La question
206             est donc : comment éliminer ces déclarations <code>require_once</code> dans le but de
207             maximiser les performances de l'autoloader.
208         </para>
210         <sect3 id="performance.classloading.striprequires.sed">
211             <title>Effacer les appels de require_once avec find et sed</title>
213             <para>
214                 Une manière simple d'effacer les appels require_once est d'utiliser les
215                 utilitaires Unix "find" en conjonction avec "sed" pour passe en commentaires tous
216                 les appels. Essayez d'exécuter les commandes suivantes (où "%" indique le prompteur
217                 shell)&#160;:
218             </para>
220             <programlisting language="shell"><![CDATA[
221 % cd chemin/vers/la/librarie/ZendFramework
222 % find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
223   -not -wholename '*/Application.php' -print0 | \
224   xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'
225 ]]></programlisting>
227             <para>
228                 Cette ligne unique (coupée en deux pour la lisibilité) itère parmi les
229                 fichiers PHP et y remplace toute les instances de <code>require_once</code> par
230                 <code>//require_once</code>, c'est-à-dire en commentant toutes ces lignes (tout
231                 en maintenant les appels à <function>require_once</function> dans
232                 <classname>Zend_Application</classname> et
233                 <classname>Zend_Loader_Autoloader</classname>, puisque ces classes tomberont en
234                 erreur sans ceux-ci).
235             </para>
237             <para>
238                 Cette commande peut être simplement ajoutée à un script de construction
239                 automatique ou à un processus de mise en production, permettent ainsi d'augmenter
240                 les performances de votre application en production. Il est à noter, cependant, que
241                 si vous utilisez cette technique, vous <emphasis>devez</emphasis> utiliser
242                 l'autoloading ; vous pouvez l'activer dans votre fichier
243                 <filename>public/index.php</filename> en ajoutant le code suivant&#160;:
244             </para>
246             <programlisting language="php"><![CDATA[
247 require_once 'Zend/Loader/Autoloader.php';
248 Zend_Loader_Autoloader::getInstance();
249 ]]></programlisting>
250         </sect3>
251     </sect2>
253     <sect2 id="performance.classloading.pluginloader">
254         <title>Comment accélérer le chargement des plugins&#160;?</title>
256         <para>
257             Certains composants utilisent les plugins, ce qui vous permet de créer vos propres
258             classes afin de les utiliser avec le composant, de même que de surcharger les plugins
259             standard existants embarqués dans Zend Framework. Ceci fournit une importante
260             flexibilité au framework, mais a un prix&#160;: le chargement des plugins est une tâche
261             assez coûteuse.
262         </para>
264         <para>
265             Le chargeur de plugins vous permet de définir des paires préfixe de classe /
266             chemin, vous autorisant ainsi à spécifier des fichiers de classe dans des chemins de
267             dossiers non standard. Chaque préfixe peut avoir de multiples chemins associés. En
268             interne, le chargeur de plugins boucle à travers chaque préfixe, et ensuite à travers
269             chaque chemin lui étant associé, en testant l'existence du fichier et s'il est
270             accessible dans ce chemin. Il le charge ensuite, et teste pour voir si la classe
271             recherchée est bien disponible. Comme vous pouvez l'imaginer, tout ceci entraîne des
272             appels aux stats du système de fichiers.
273         </para>
275         <para>
276             Multipliez ceci par le nombre de composants qui utilisent le PluginLoader, et vous
277             aurez une idée de l'importance de ce problème. Au moment de l'écriture de ce document,
278             les composants suivants utilisent le PluginLoader&#160;:
279         </para>
281         <itemizedlist>
282             <listitem>
283                 <para>
284                     <classname>Zend_Controller_Action_HelperBroker</classname>&#160;: aides
285                     d'action
286                 </para>
287             </listitem>
289             <listitem>
290                 <para>
291                     <classname>Zend_Dojo</classname>&#160;: aides de vues, éléments de formulaires
292                     et décorateurs
293                 </para>
294             </listitem>
296             <listitem>
297                 <para><classname>Zend_File_Transfer</classname>&#160;: adaptateurs</para>
298             </listitem>
300             <listitem>
301                 <para>
302                     <classname>Zend_Filter_Inflector</classname>&#160;: filtres (utilisé par l'aide
303                     d'action <code>ViewRenderer</code> et <classname>Zend_Layout</classname>)
304                 </para>
305             </listitem>
307             <listitem>
308                 <para><classname>Zend_Filter_Input</classname>&#160;: filtres et validateurs</para>
309             </listitem>
311             <listitem>
312                 <para>
313                     <classname>Zend_Form</classname>&#160;: éléments, validateurs, filtres,
314                     décorateurs, captcha et adaptateur pour les transferts de fichiers
315                 </para>
316             </listitem>
318             <listitem>
319                 <para><classname>Zend_Paginator</classname>&#160;: adaptateurs</para>
320             </listitem>
322             <listitem>
323                 <para><classname>Zend_View</classname>&#160;: aides de vues, filtres</para>
324             </listitem>
325         </itemizedlist>
327         <para>Comment réduire le nombre des appels réalisés&#160;?</para>
329         <sect3 id="performance.classloading.pluginloader.includefilecache">
330             <title>Utiliser le fichier de cache des inclusions du PluginLoader</title>
332             <para>
333                 Zend Framework 1.7.0 ajoute un fichier de cache des inclusions au
334                 PluginLoader. Cette fonctionnalité écrit dans un fichier les appels
335                 "<code>include_once</code>", que vous pouvez ensuite inclure dans votre fichier
336                 d'amorçage. Même si ceci introduit de nouveaux appels include_once dans votre code,
337                 cela permet de s'assurer que le PluginLoader les retournera au plus vite.
338             </para>
340             <para>
341                 La documentation du PluginLoader <link
342                 linkend="zend.loader.pluginloader.performance.example">inclue un exemple complet de
343                 son utilisation</link>.
344             </para>
345         </sect3>
346     </sect2>
347 </sect1>