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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"><head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<!--
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This file is generated from xml source: DO NOT EDIT
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<title>Optimisation des performances d'Apache - Serveur HTTP Apache Version 2.4</title>
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="../style/css/prettify.css" />
<script src="../style/scripts/prettify.min.js" type="text/javascript">
</script>
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
<body id="manual-page"><div id="page-header">
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossaire</a> | <a href="../sitemap.html">Plan du site</a></p>
<p class="apache">Serveur HTTP Apache Version 2.4</p>
<img alt="" src="../images/feather.png" /></div>
<div class="up"><a href="./"><img title="<-" alt="<-" src="../images/left.gif" /></a></div>
<div id="path">
<a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">Serveur HTTP</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.4</a> > <a href="./">Documentations diverses</a></div><div id="page-content"><div id="preamble"><h1>Optimisation des performances d'Apache</h1>
<div class="toplang">
<p><span>Langues Disponibles: </span><a href="../en/misc/perf-tuning.html" hreflang="en" rel="alternate" title="English"> en </a> |
<a href="../fr/misc/perf-tuning.html" title="Français"> fr </a> |
<a href="../ko/misc/perf-tuning.html" hreflang="ko" rel="alternate" title="Korean"> ko </a> |
<a href="../tr/misc/perf-tuning.html" hreflang="tr" rel="alternate" title="Türkçe"> tr </a></p>
</div>
<p>Apache 2.x est un serveur web à usage général, conçu dans un but
d'équilibre entre souplesse, portabilité et performances. Bien que non
conçu dans le seul but d'établir une référence en la matière,
Apache 2.x est capable de hautes performances dans de nombreuses situations
du monde réel.</p>
<p>Comparée à Apache 1.3, la version 2.x comporte de nombreuses
optimisations supplémentaires permettant d'améliorer le débit du serveur
et sa personnalisation. La plupart de ces améliorations sont activées par
défaut. Cependant, certains choix de configuration à la compilation et à
l'exécution peuvent affecter les performances de manière significative. Ce
document décrit les options qu'un administrateur de serveur peut configurer
pour améliorer les performances d'une installation d'Apache 2.x. Certaines
de ces options de configuration permettent au démon httpd de mieux tirer
parti des possibilités du matériel et du système d'exploitation, tandis
que d'autres permettent à l'administrateur de privilégier la vitesse
par rapport aux fonctionnalités.</p>
</div>
<div id="quickview"><a href="https://www.apache.org/foundation/contributing.html" class="badge"><img src="https://www.apache.org/images/SupportApache-small.png" alt="Support Apache!" /></a><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#hardware">Problèmes matériels et relatifs au système d'exploitation</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#runtime">Optimisation de la configuration à l'exécution</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#compiletime">Optimisation de la configuration à la compilation</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#trace">Appendice : Analyse détaillée d'une trace</a></li>
</ul><h3>Voir aussi</h3><ul class="seealso"><li><a href="#comments_section">Commentaires</a></li></ul></div>
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="hardware" id="hardware">Problèmes matériels et relatifs au système d'exploitation</a></h2>
<p>Le principal problème matériel qui affecte les performances du serveur
web est la mémoire vive (RAM). Un serveur web ne devrait jamais avoir à
utiliser le swap, car le swapping augmente le temps de réponse de chaque
requête au delà du point que les utilisateurs considèrent comme
"trop lent". Ceci incite les utilisateurs à cliquer sur "Stop", puis
"Charger à nouveau", ce qui a pour effet d'augmenter encore la charge
du serveur. Vous pouvez, et même devez définir la valeur de la directive
<code class="directive"><a href="../mod/mpm_common.html#maxrequestworkers">MaxRequestWorkers</a></code> de façon à ce que
votre serveur ne lance pas un nombre de processus enfants tel qu'il
commence à faire du swapping. La méthode pour y parvenir est
simple : déterminez la taille de votre processus Apache standard en
consultant votre liste de processus à l'aide d'un outil tel que
<code>top</code>, et divisez votre quantité totale de mémoire disponible
par cette taille, tout en gardant un espace suffisant
pour les autres processus.</p>
<p>Hormis ce réglage relatif à la mémoire, le reste est trivial : le
processeur, la carte réseau et les disques doivent être suffisamment
rapides, où "suffisamment rapide" doit être déterminé par
l'expérience.</p>
<p>Le choix du système d'exploitation dépend principalement du
contexte local. Voici cependant quelques conseils qui se sont
généralement avérés utiles :</p>
<ul>
<li>
<p>Exécutez la dernière version stable et le niveau de patches le
plus haut du système d'exploitation que vous avez choisi. De nombreux
éditeurs de systèmes d'exploitation ont amélioré de manière
significative les performances de leurs piles TCP et de leurs
bibliothèques de thread ces dernières années.</p>
</li>
<li>
<p>Si votre système d'exploitation possède un appel système
<code>sendfile(2)</code>, assurez-vous d'avoir installé la version
et/ou les patches nécessaires à son activation. (Pour Linux, par
exemple, cela se traduit par Linux 2.4 ou plus. Pour les versions
anciennes de Solaris 8, vous pouvez être amené à appliquer un patch.)
Sur les systèmes où il est disponible, <code>sendfile</code> permet
à Apache 2 de servir les contenus statiques plus rapidement, tout en
induisant une charge CPU inférieure.</p>
</li>
</ul>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="runtime" id="runtime">Optimisation de la configuration à l'exécution</a></h2>
<table class="related"><tr><th>Modules Apparentés</th><th>Directives Apparentées</th></tr><tr><td><ul><li><code class="module"><a href="../mod/mod_dir.html">mod_dir</a></code></li><li><code class="module"><a href="../mod/mpm_common.html">mpm_common</a></code></li><li><code class="module"><a href="../mod/mod_status.html">mod_status</a></code></li></ul></td><td><ul><li><code class="directive"><a href="../mod/core.html#allowoverride">AllowOverride</a></code></li><li><code class="directive"><a href="../mod/mod_dir.html#directoryindex">DirectoryIndex</a></code></li><li><code class="directive"><a href="../mod/core.html#hostnamelookups">HostnameLookups</a></code></li><li><code class="directive"><a href="../mod/core.html#enablemmap">EnableMMAP</a></code></li><li><code class="directive"><a href="../mod/core.html#enablesendfile">EnableSendfile</a></code></li><li><code class="directive"><a href="../mod/core.html#keepalivetimeout">KeepAliveTimeout</a></code></li><li><code class="directive"><a href="../mod/prefork.html#maxspareservers">MaxSpareServers</a></code></li><li><code class="directive"><a href="../mod/prefork.html#minspareservers">MinSpareServers</a></code></li><li><code class="directive"><a href="../mod/core.html#options">Options</a></code></li><li><code class="directive"><a href="../mod/mpm_common.html#startservers">StartServers</a></code></li></ul></td></tr></table>
<h3><a name="dns" id="dns">HostnameLookups et autres considérations à propos du DNS</a></h3>
<p>Avant Apache 1.3, la directive
<code class="directive"><a href="../mod/core.html#hostnamelookups">HostnameLookups</a></code> était positionnée
par défaut à <code>On</code>. Ce réglage augmente le temps de réponse de
chaque requête car il entraîne une recherche DNS et le traitement de la
requête ne pourra pas être achevé tant que cette recherche ne sera
pas terminée. Avec Apache 1.3, ce réglage est défini par défaut à
<code>Off</code>. Si vous souhaitez que les adresses dans vos fichiers
journaux soient résolues en noms d'hôtes, utilisez le programme
<code class="program"><a href="../programs/logresolve.html">logresolve</a></code> fourni avec Apache, ou un des nombreux
paquets générateurs de rapports sur les journaux disponibles.</p>
<p>Il est recommandé d'effectuer ce genre de traitement a posteriori
de vos fichiers journaux sur une autre machine que celle qui héberge le
serveur web en production, afin que cette activité n'affecte pas les
performances du serveur.</p>
<p>Si vous utilisez une directive
<code><code class="directive"><a href="../mod/mod_access_compat.html#allow">Allow</a></code>from domain</code>
ou
<code><code class="directive"><a href="../mod/mod_access_compat.html#deny">Deny</a></code> from domain</code>
(ce qui signifie que vous utilisez un nom d'hôte ou un nom de domaine à
la place d'une adresse IP), vous devrez compter avec deux recherches
DNS (une recherche inverse suivie d'une recherche directe pour
s'assurer que l'adresse IP n'a pas été usurpée). C'est pourquoi il est
préférable, pour améliorer les performances, d'utiliser des adresses IP
plutôt que des noms lorsqu'on utilise ces directives, du moins chaque
fois que c'est possible.</p>
<p>Notez qu'il est possible de modifier la portée des directives, en les
plaçant par exemple à l'intérieur d'une section
<code><Location "/server-status"></code>. Les recherches DNS ne
seront alors effectuées que pour les requêtes qui satisfont aux critères.
Voici un exemple qui désactive les recherches DNS sauf pour les fichiers
<code>.html</code> et <code>.cgi</code> :</p>
<pre class="prettyprint lang-config">HostnameLookups off
<Files ~ "\.(html|cgi)$">
HostnameLookups on
</Files></pre>
<p>Mais même dans ce cas, si vous n'avez besoin de noms DNS que dans
certains CGIs, vous pouvez effectuer l'appel à <code>gethostbyname</code>
dans les CGIs spécifiques qui en ont besoin.</p>
<h3><a name="symlinks" id="symlinks">FollowSymLinks et SymLinksIfOwnerMatch</a></h3>
<p>Chaque fois que la ligne <code>Options FollowSymLinks</code> sera
absente, ou que la ligne <code>Options SymLinksIfOwnerMatch</code> sera
présente dans votre espace d'adressage, Apache devra effectuer des
appels système supplémentaires pour vérifier la présence de liens
symboliques. Un appel supplémentaire par élément du chemin du fichier.
Par exemple, si vous avez :</p>
<pre class="prettyprint lang-config">DocumentRoot "/www/htdocs"
<Directory "/">
Options SymLinksIfOwnerMatch
</Directory></pre>
<p>et si une requête demande l'URI <code>/index.html</code>, Apache
effectuera un appel à <code>lstat(2)</code> pour
<code>/www</code>, <code>/www/htdocs</code>, et
<code>/www/htdocs/index.html</code>. Les résultats de ces appels à
<code>lstat</code> ne sont jamais mis en cache, ils devront donc être
générés à nouveau pour chaque nouvelle requête. Si vous voulez absolument
vérifier la sécurité des liens symboliques, vous pouvez utiliser une
configuration du style :</p>
<pre class="prettyprint lang-config">DocumentRoot "/www/htdocs"
<Directory "/">
Options FollowSymLinks
</Directory>
<Directory "/www/htdocs">
Options -FollowSymLinks +SymLinksIfOwnerMatch
</Directory></pre>
<p>Ceci évite au moins les vérifications supplémentaires pour le chemin
défini par <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>. Notez que
vous devrez ajouter des sections similaires si vous avez des chemins
définis par les directives
<code class="directive"><a href="../mod/mod_alias.html#alias">Alias</a></code> ou
<code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> en dehors de
la racine de vos documents. Pour améliorer les performances, et supprimer
toute protection des liens symboliques, ajoutez l'option
<code>FollowSymLinks</code> partout, et n'utilisez jamais l'option
<code>SymLinksIfOwnerMatch</code>.</p>
<h3><a name="htaccess" id="htaccess">AllowOverride</a></h3>
<p>Dans toute partie de votre espace d'adressage où vous autoriserez
la surcharge de la configuration (en général à l'aide de fichiers
<code>.htaccess</code>), Apache va tenter d'ouvrir <code>.htaccess</code>
pour chaque élément du chemin du fichier demandé. Par exemple, si vous
avez : </p>
<pre class="prettyprint lang-config">DocumentRoot "/www/htdocs"
<Directory "/">
AllowOverride all
</Directory></pre>
<p>et qu'une requête demande l'URI <code>/index.html</code>, Apache
tentera d'ouvrir <code>/.htaccess</code>, <code>/www/.htaccess</code>,
et <code>/www/htdocs/.htaccess</code>. Les solutions sont similaires à
celles évoquées précédemment pour <code>Options FollowSymLinks</code>.
Pour améliorer les performances, utilisez <code>AllowOverride None</code>
pour tous les niveaux de votre espace d'adressage.</p>
<h3><a name="negotiation" id="negotiation">Négociation</a></h3>
<p>Dans la mesure du possible, évitez toute négociation de contenu si
vous tenez au moindre gain en performances. En pratique toutefois,
les bénéfices de la négociation l'emportent souvent sur la diminution
des performances.
Il y a cependant un cas dans lequel vous pouvez accélérer le serveur.
Au lieu d'utiliser une directive générique comme :</p>
<pre class="prettyprint lang-config">DirectoryIndex index</pre>
<p>utilisez une liste explicite d'options :</p>
<pre class="prettyprint lang-config">DirectoryIndex index.cgi index.pl index.shtml index.html</pre>
<p>où vous placez le choix courant en première position.</p>
<p>Notez aussi que créer explicitement un fichier de
<code>correspondances de type</code> fournit de meilleures performances
que l'utilisation des <code>MultiViews</code>, car les informations
nécessaires peuvent être simplement obtenues en lisant ce fichier, sans
avoir à parcourir le répertoire à la recherche de types de fichiers.</p>
<p>Par conséquent, si la négociation de contenu est nécessaire pour votre
site, préférez les fichiers de <code>correspondances de type</code> aux
directives <code>Options MultiViews</code> pour mener à bien cette
négociation. Se référer au document sur la
<a href="../content-negotiation.html">Négociation de contenu</a> pour une
description complète des méthodes de négociation, et les instructions
permettant de créer des fichiers de <code>correspondances de type</code>.</p>
<h3>Transfert en mémoire</h3>
<p>Dans les situations où Apache 2.x doit consulter le contenu d'un
fichier en train d'être servi - par exemple à l'occasion du traitement
d'une inclusion côté serveur - il transfère en général le fichier en
mémoire si le système d'exploitation supporte une forme quelconque
de <code>mmap(2)</code>.</p>
<p>Sur certains systèmes, ce transfert en mémoire améliore les
performances. Dans certains cas, ce transfert peut toutefois les dégrader
et même diminuer la stabilité du démon httpd :</p>
<ul>
<li>
<p>Dans certains systèmes d'exploitation, <code>mmap</code> devient
moins efficace que <code>read(2)</code> quand le nombre de
processeurs augmente. Sur les serveurs multiprocesseurs sous Solaris,
par exemple, Apache 2.x sert parfois les fichiers consultés par le
serveur plus rapidement quand <code>mmap</code> est désactivé.</p>
</li>
<li>
<p>Si vous transférez en mémoire un fichier localisé dans un système
de fichiers monté par NFS, et si un processus sur
une autre machine cliente NFS supprime ou tronque le fichier, votre
processus peut rencontrer une erreur de bus la prochaine fois qu'il
essaiera d'accéder au contenu du fichier en mémoire.</p>
</li>
</ul>
<p>Pour les installations où une de ces situations peut se produire,
vous devez utiliser <code>EnableMMAP off</code> afin de désactiver le
transfert en mémoire des fichiers servis. (Note : il est possible de
passer outre cette directive au niveau de chaque répertoire.)</p>
<h3>Sendfile</h3>
<p>Dans les cas où Apache peut se permettre d'ignorer le contenu du
fichier à servir - par exemple, lorsqu'il sert un contenu de fichier
statique - il utilise en général le support sendfile du noyau si le
système d'exploitation supporte l'opération <code>sendfile(2)</code>.</p>
<p>Sur la plupart des plateformes, l'utilisation de sendfile améliore
les performances en éliminant les mécanismes de lecture et envoi séparés.
Dans certains cas cependant, l'utilisation de sendfile peut nuire à la
stabilité du démon httpd :</p>
<ul>
<li>
<p>Certaines plateformes peuvent présenter un support de sendfile
défaillant que la construction du système n'a pas détecté, en
particulier si les binaires ont été construits sur une autre machine
et transférés sur la machine où le support de sendfile est
défaillant.</p>
</li>
<li>
<p>Dans le cas d'un système de fichiers monté
sous NFS, le noyau peut s'avérer incapable de servir
les fichiers réseau de manière fiable depuis
son propre cache.</p>
</li>
</ul>
<p>Pour les installations où une de ces situations peut se produire,
vous devez utiliser <code>EnableSendfile off</code> afin de désactiver
la mise à disposition de contenus de fichiers par sendfile. (Note : il
est possible de passer outre cette directive au niveau de chaque
répertoire.)</p>
<h3><a name="process" id="process">Process Creation</a></h3>
<p>Avant Apache 1.3, les directives
<code class="directive"><a href="../mod/prefork.html#minspareservers">MinSpareServers</a></code>,
<code class="directive"><a href="../mod/prefork.html#maxspareservers">MaxSpareServers</a></code>, et
<code class="directive"><a href="../mod/mpm_common.html#startservers">StartServers</a></code> avaient des
effets drastiques sur les performances de référence. En particulier,
Apache avait besoin d'un délai de "montée en puissance" afin d'atteindre
un nombre de processus enfants suffisant pour supporter la charge qui lui
était appliquée. Après le lancement initial des processus enfants par
<code class="directive"><a href="../mod/mpm_common.html#startservers">StartServers</a></code>, seulement un
processus enfant par seconde était créé afin d'atteindre la valeur de la
directive <code class="directive"><a href="../mod/prefork.html#minspareservers">MinSpareServers</a></code>. Ainsi,
un serveur accédé par 100 clients simultanés et utilisant la valeur par
défaut de <code>5</code> pour la directive
<code class="directive"><a href="../mod/mpm_common.html#startservers">StartServers</a></code>, nécessitait
environ 95 secondes pour lancer suffisamment de processus enfants
permettant de faire face à la charge. Ceci fonctionne en pratique pour
les serveurs en production, car ils sont rarement redémarrés. Ce n'est
cependant pas le cas pour les tests de référence (benchmarks) où le
serveur ne fonctionne que 10 minutes.</p>
<p>La règle "un processus par seconde" avait été implémentée afin
d'éviter l'enlisement de la machine dans le démarrage de nouveaux
processus enfants. Pendant que la machine est occupée à lancer des
processus enfants, elle ne peut pas traiter les requêtes. Mais cette
règle impactait tellement la perception des performances d'Apache qu'elle
a dû être remplacée. A partir d'Apache 1.3, le code a assoupli la règle
"un processus par seconde". Il va en lancer un, attendre une seconde,
puis en lancer deux, attendre une seconde, puis en lancer quatre et
ainsi de suite jusqu'à lancer 32 processus. Il s'arrêtera lorsque le
nombre de processus aura atteint la valeur définie par la directive
<code class="directive"><a href="../mod/prefork.html#minspareservers">MinSpareServers</a></code>.</p>
<p>Ceci s'avère suffisamment réactif pour pouvoir en général se passer
de manipuler les valeurs des directives
<code class="directive"><a href="../mod/prefork.html#minspareservers">MinSpareServers</a></code>,
<code class="directive"><a href="../mod/prefork.html#maxspareservers">MaxSpareServers</a></code> et
<code class="directive"><a href="../mod/mpm_common.html#startservers">StartServers</a></code>. Lorsque plus de
4 processus enfants sont lancés par seconde, un message est émis vers
le journal des erreurs. Si vous voyez apparaître souvent ce genre de
message, vous devez vous pencher sur ces réglages. Pour vous guider,
utilisez les informations délivrées par le module
<code class="module"><a href="../mod/mod_status.html">mod_status</a></code>.</p>
<p>À mettre en relation avec la création de processus, leur destruction
est définie par la valeur de la directive
<code class="directive"><a href="../mod/mpm_common.html#maxconnectionsperchild">MaxConnectionsPerChild</a></code>. Sa valeur
par défaut est <code>0</code>, ce qui signifie qu'il n'y a pas de limite
au nombre de connexions qu'un processus enfant peut traiter. Si votre
configuration actuelle a cette directive réglée à une valeur très basse,
de l'ordre de <code>30</code>, il est conseillé de l'augmenter de manière
significative. Si vous utilisez SunOs ou une ancienne version de Solaris,
utilisez une valeur de l'ordre de <code>10000</code> à cause des fuites
de mémoire.</p>
<p>Lorsqu'ils sont en mode "keep-alive", les processus enfants sont
maintenus et ne font rien sinon attendre la prochaine requête sur la
connexion déjà ouverte. La valeur par défaut de <code>5</code> de la
directive <code class="directive"><a href="../mod/core.html#keepalivetimeout">KeepAliveTimeout</a></code> tend à
minimiser cet effet. Il faut trouver le bon compromis entre la bande
passante réseau et les ressources du serveur. En aucun cas vous ne devez
choisir une valeur supérieure à <code>60</code> seconds, car
<a href="http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-4.html">
la plupart des bénéfices sont alors perdus</a>.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="compiletime" id="compiletime">Optimisation de la configuration à la compilation</a></h2>
<h3>Choisir un Module Multi-Processus (MPM)</h3>
<p>Apache 2.x supporte les modèles simultanés enfichables, appelés
<a href="../mpm.html">Modules Multi-Processus</a> (MPMs). Vous devez
choisir un MPM au moment de la construction d'Apache. Certaines
plateformes ont des modules MPM spécifiques :
<code class="module"><a href="../mod/mpm_netware.html">mpm_netware</a></code>, <code class="module"><a href="../mod/mpmt_os2.html">mpmt_os2</a></code> et
<code class="module"><a href="../mod/mpm_winnt.html">mpm_winnt</a></code>. Sur les systèmes de type Unix, vous avez le
choix entre un grand nombre de modules MPM. Le choix du MPM peut affecter
la vitesse et l'évolutivité du démon httpd :</p>
<ul>
<li>Le MPM <code class="module"><a href="../mod/worker.html">worker</a></code> utilise plusieurs processus
enfants possédant chacun de nombreux threads. Chaque thread gère une
seule connexion à la fois. Worker est en général un bon choix pour les
serveurs présentant un traffic important car il possède une empreinte
mémoire plus petite que le MPM prefork.</li>
<li>Comme le MPM Worker, le MPM <code class="module"><a href="../mod/event.html">event</a></code> utilise
les threads, mais il a été conçu pour traiter davantage de
requêtes simultanément en confiant une partie du travail à des
threads de support, ce qui permet aux threads principaux de
traiter de nouvelles requêtes.</li>
<li>Le MPM <code class="module"><a href="../mod/prefork.html">prefork</a></code> utilise plusieurs processus enfants
possédant chacun un seul thread. Chaque processus gère une seule
connexion à la fois. Sur de nombreux systèmes, prefork est comparable
en matière de vitesse à worker, mais il utilise plus de mémoire. De par
sa conception sans thread, prefork présente des avantages par rapport à
worker dans certaines situations : il peut être utilisé avec les
modules tiers qui ne supportent pas le threading, et son débogage est plus
aisé sur les platesformes présentant un support du débogage des threads
rudimentaire.</li>
</ul>
<p>Pour plus d'informations sur ces deux MPMs et les autres, veuillez
vous référer à la <a href="../mpm.html">documentation sur les
MPM</a>.</p>
<h3><a name="modules" id="modules">Modules</a></h3>
<p>Comme le contrôle de l'utilisation de la mémoire est très important
en matière de performance, il est conseillé d'éliminer les modules que
vous n'utilisez pas vraiment. Si vous avez construit ces modules en
tant que <a href="../dso.html">DSOs</a>, leur élimination consiste
simplement à commenter la directive
<code class="directive"><a href="../mod/mod_so.html#loadmodule">LoadModule</a></code> associée à ce
module. Ceci vous permet de vérifier si votre site fonctionne toujours
après la suppression de tel ou tel module.</p>
<p>Par contre, si les modules que vous voulez supprimer sont liés
statiquement à votre binaire Apache, vous devrez recompiler ce dernier
afin de pouvoir les éliminer.</p>
<p>La question qui découle de ce qui précède est évidemment de
savoir de quels modules vous avez besoin et desquels vous pouvez vous
passer. La réponse sera bien entendu différente d'un site web à
l'autre. Cependant, la liste <em>minimale</em> de modules nécessaire à
la survie de votre site contiendra certainement
<code class="module"><a href="../mod/mod_mime.html">mod_mime</a></code>, <code class="module"><a href="../mod/mod_dir.html">mod_dir</a></code> et
<code class="module"><a href="../mod/mod_log_config.html">mod_log_config</a></code>. <code>mod_log_config</code> est bien
entendu optionnel puisque vous pouvez faire fonctionner un site web
en se passant de fichiers journaux ; ceci est cependant
déconseillé.</p>
<h3>Opérations atomiques</h3>
<p>Certains modules, à l'instar de <code class="module"><a href="../mod/mod_cache.html">mod_cache</a></code> et des
versions de développement récentes du MPM worker, utilisent l'API
atomique d'APR. Cette API propose des opérations atomiques que l'on
peut utiliser pour alléger la synchronisation des threads.</p>
<p>Par défaut, APR implémente ces opérations en utilisant les
mécanismes les plus efficaces disponibles sur chaque plateforme cible
(Système d'exploitation et processeur). De nombreux processeurs modernes,
par exemple, possèdent une instruction qui effectue une opération
atomique de type comparaison et échange ou compare-and-swap (CAS) au
niveau matériel. Sur certaines platesformes cependant, APR utilise par
défaut une implémentation de l'API atomique plus lente, basée sur les
mutex, afin d'assurer la compatibilité avec les anciens modèles de
processeurs qui ne possèdent pas ce genre d'instruction. Si vous
construisez Apache pour une de ces platesformes, et ne prévoyez de
l'exécuter que sur des processeurs récents, vous pouvez sélectionner une
implémentation atomique plus rapide à la compilation en utilisant
l'option <code>--enable-nonportable-atomics</code> du
script configure :</p>
<div class="example"><p><code>
./buildconf<br />
./configure --with-mpm=worker --enable-nonportable-atomics=yes
</code></p></div>
<p>L'option <code>--enable-nonportable-atomics</code> concerne les
platesformes suivantes :</p>
<ul>
<li>Solaris sur SPARC<br />
Sur Solaris/SPARC, APR utilise par défaut les opérations
atomiques basées sur les mutex. Cependant, si vous ajoutez l'option
<code>--enable-nonportable-atomics</code> au script configure, APR
génère un code qui utilise le code opération SPARC v8plus pour des
opérations de compare-and-swap matériel plus rapides. Si vous
utilisez cette option de configure avec Apache, les opérations
atomiques seront plus efficaces (permettant d'alléger la charge du
processeur et un plus haut niveau de simultanéité), mais
l'exécutable produit ne fonctionnera que sur les processeurs
UltraSPARC.
</li>
<li>Linux sur x86<br />
Sous Linux, APR utilise par défaut les opérations atomiques basées
sur les mutex. Cependant, si vous ajoutez l'option
<code>--enable-nonportable-atomics</code> au script configure,
APR générera un code qui utilise un code d'opération du 486
pour des opérations de compare-and-swap matériel plus rapides. Le
code résultant est plus efficace en matière d'opérations atomiques,
mais l'exécutable produit ne fonctionnera que sur des processeurs
486 et supérieurs (et non sur des 386).
</li>
</ul>
<h3>Module mod_status et ExtendedStatus On</h3>
<p>Si vous incluez le module <code class="module"><a href="../mod/mod_status.html">mod_status</a></code> à la
construction d'Apache et ajoutez <code>ExtendedStatus On</code> à sa
configuration, Apache va effectuer pour chaque requête deux appels à
<code>gettimeofday(2)</code> (ou <code>times(2)</code> selon votre
système d'exploitation), et (pour les versions antérieures à 1.3) de
nombreux appels supplémentaires à <code>time(2)</code>. Tous ces
appels sont effectués afin que le rapport de statut puisse contenir
des indications temporelles. Pour améliorer les performances, utilisez
<code>ExtendedStatus off</code> (qui est le réglage par défaut).</p>
<h3>accept Serialization - points de connexion à un programme (sockets) multiples</h3>
<div class="warning"><h3>Mise en garde :</h3>
<p>Cette section n'a pas été totalement mise à jour car elle ne tient pas
compte des changements intervenus dans la version 2.x du Serveur HTTP
Apache. Certaines informations sont encore pertinentes, il vous est
cependant conseillé de les utiliser avec prudence.</p>
</div>
<p>Ce qui suit est une brève discussion à propos de l'API des sockets
Unix. Supposons que votre serveur web utilise plusieurs directives
<code class="directive"><a href="../mod/mpm_common.html#listen">Listen</a></code> afin d'écouter
plusieurs ports ou de multiples adresses. Afin de tester chaque socket
pour voir s'il a une connexion en attente, Apache utilise
<code>select(2)</code>. <code>select(2)</code> indique si un socket a
<em>zéro</em> ou <em>au moins une</em> connexion en attente. Le modèle
d'Apache comporte plusieurs processus enfants, et tous ceux qui sont
inactifs testent la présence de nouvelles connexions au même moment.
Une implémentation rudimentaire de ceci pourrait ressembler à
l'exemple suivant
(ces exemples ne sont pas extraits du code d'Apache, ils ne sont
proposés qu'à des fins pédagogiques) :</p>
<pre class="prettyprint lang-c"> for (;;) {
for (;;) {
fd_set accept_fds;
FD_ZERO (&accept_fds);
for (i = first_socket; i <= last_socket; ++i) {
FD_SET (i, &accept_fds);
}
rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
if (rc < 1) continue;
new_connection = -1;
for (i = first_socket; i <= last_socket; ++i) {
if (FD_ISSET (i, &accept_fds)) {
new_connection = accept (i, NULL, NULL);
if (new_connection != -1) break;
}
}
if (new_connection != -1) break;
}
process_the(new_connection);
}</pre>
<p>Mais cette implémentation rudimentaire présente une sérieuse lacune.
Rappelez-vous que les processus enfants exécutent cette boucle au même
moment ; ils vont ainsi bloquer sur <code>select</code> s'ils se trouvent
entre deux requêtes. Tous ces processus bloqués vont se réactiver et
sortir de <code>select</code> quand une requête va apparaître sur un des
sockets (le nombre de processus enfants qui se réactivent varie en
fonction du système d'exploitation et des réglages de synchronisation).
Ils vont alors tous entrer dans la boucle et tenter un
<code>"accept"</code> de la connexion. Mais seulement un d'entre eux y
parviendra (en supposant qu'il ne reste q'une seule connexion en
attente), les autres vont se bloquer au niveau de <code>accept</code>.
Ceci verrouille vraiment ces processus de telle sorte qu'ils ne peuvent
plus servir de requêtes que par cet unique socket, et il en sera ainsi
jusqu'à ce que suffisamment de nouvelles requêtes apparaissent sur ce
socket pour les réactiver tous. Cette lacune a été documentée pour la
première fois dans
<a href="http://bugs.apache.org/index/full/467">PR#467</a>. Il existe
au moins deux solutions.</p>
<p>La première consiste à rendre les sockets non blocants. Dans ce cas,
<code>accept</code> ne bloquera pas les processus enfants, et ils
pourront continuer à s'exécuter immédiatement. Mais ceci consomme des
ressources processeur. Supposons que vous ayez dix processus enfants
inactifs dans <code>select</code>, et qu'une connexion arrive.
Neuf des dix processus vont se réactiver, tenter un <code>accept</code>
de la connexion, échouer, et boucler dans <code>select</code>, tout en
n'ayant finalement rien accompli. Pendant ce temps, aucun de ces processus
ne traite les requêtes qui arrivent sur d'autres sockets jusqu'à ce
qu'ils retournent dans <code>select</code>. Finalement, cette solution
ne semble pas très efficace, à moins que vous ne disposiez d'autant de
processeurs inactifs (dans un serveur multiprocesseur) que de processus
enfants inactifs, ce qui n'est pas une situation très courante.</p>
<p>Une autre solution, celle qu'utilise Apache, consiste à sérialiser les
entrées dans la boucle interne. La boucle ressemble à ceci (les
différences sont mises en surbrillance) :</p>
<pre class="prettyprint lang-c"> for (;;) {
<strong>accept_mutex_on ();</strong>
for (;;) {
fd_set accept_fds;
FD_ZERO (&accept_fds);
for (i = first_socket; i <= last_socket; ++i) {
FD_SET (i, &accept_fds);
}
rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
if (rc < 1) continue;
new_connection = -1;
for (i = first_socket; i <= last_socket; ++i) {
if (FD_ISSET (i, &accept_fds)) {
new_connection = accept (i, NULL, NULL);
if (new_connection != -1) break;
}
}
if (new_connection != -1) break;
}
<strong>accept_mutex_off ();</strong>
process the new_connection;
}</pre>
<p><a id="serialize" name="serialize">Les fonctions</a>
<code>accept_mutex_on</code> et <code>accept_mutex_off</code>
implémentent un sémaphore permettant une exclusion mutuelle. Un seul
processus enfant à la fois peut posséder le mutex. Plusieurs choix se
présentent pour implémenter ces mutex. Ce choix est défini dans
<code>src/conf.h</code> (versions antérieures à 1.3) ou
<code>src/include/ap_config.h</code> (versions 1.3 ou supérieures).
Certaines architectures ne font pas ce choix du mode de verrouillage ;
l'utilisation de directives
<code class="directive"><a href="../mod/mpm_common.html#listen">Listen</a></code> multiples sur ces
architectures est donc peu sûr.</p>
<p>La directive <code class="directive"><a href="../mod/core.html#mutex">Mutex</a></code> permet
de modifier l'implémentation du mutex <code>mpm-accept</code> à
l'exécution. Des considérations spécifiques aux différentes
implémentations de mutex sont documentées avec cette directive.</p>
<p>Une autre solution qui a été imaginée mais jamais implémentée, consiste
à sérialiser partiellement la boucle -- c'est à dire y faire entrer un
certain nombre de processus. Ceci ne présenterait un intérêt que sur les
machines multiprocesseurs où plusieurs processus enfants peuvent
s'exécuter simultanément, et encore, la sérialisation ne tire pas
vraiment parti de toute la bande passante. C'est une possibilité
d'investigation future, mais demeure de priorité basse car les serveurs
web à architecture hautement parallèle ne sont pas la norme.</p>
<p>Pour bien faire, vous devriez faire fonctionner votre serveur sans
directives <code class="directive"><a href="../mod/mpm_common.html#listen">Listen</a></code> multiples
si vous visez les performances les plus élevées.
Mais lisez ce qui suit.</p>
<h3>accept Serialization - point de connexion à un programme (sockets) unique</h3>
<p>Ce qui précède convient pour les serveurs à sockets multiples, mais
qu'en est-il des serveurs à socket unique ? En théorie, ils ne
devraient pas rencontrer les mêmes problèmes car tous les processus
enfants peuvent se bloquer dans <code>accept(2)</code> jusqu'à ce qu'une
connexion arrive, et ils ne sont pas utilisés à ne rien faire. En
pratique, ceci dissimule un même comportement de bouclage
discuté plus haut dans la solution non-blocante. De la manière dont
sont implémentées les piles TCP, le noyau réactive véritablement tous les
processus bloqués dans <code>accept</code> quand une seule connexion
arrive. Un de ces processus prend la connexion en compte et retourne
dans l'espace utilisateur, les autres bouclant dans l'espace du
noyau et se désactivant quand ils s'aperçoivent qu'il n'y a pas de
connexion pour eux. Ce bouclage est invisible depuis le code de l'espace
utilisateur, mais il est quand-même présent. Ceci peut conduire à la
même augmentation de charge à perte que la solution non blocante au cas
des sockets multiples peut induire.</p>
<p>Pour cette raison, il apparaît que de nombreuses architectures se
comportent plus "proprement" si on sérialise même dans le cas d'une socket
unique. Il s'agit en fait du comportement par défaut dans la plupart des
cas. Des expériences poussées sous Linux (noyau 2.0.30 sur un
biprocesseur Pentium pro 166 avec 128 Mo de RAM) ont montré que la
sérialisation d'une socket unique provoque une diminution inférieure à 3%
du nombre de requêtes par secondes par rapport au traitement non
sérialisé. Mais le traitement non sérialisé des sockets uniques induit
un temps de réponse supplémentaire de 100 ms pour chaque requête. Ce
temps de réponse est probablement provoqué par une limitation sur les
lignes à haute charge, et ne constitue un problème que sur les réseaux
locaux. Si vous voulez vous passer de la sérialisation des sockets
uniques, vous pouvez définir
<code>SINGLE_LISTEN_UNSERIALIZED_ACCEPT</code> et les
serveurs à socket unique ne pratiqueront plus du tout la
sérialisation.</p>
<h3>Fermeture en prenant son temps (Lingering close)</h3>
<p>Comme discuté dans <a href="http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt">
draft-ietf-http-connection-00.txt</a> section 8, pour implémenter de
manière <strong>fiable</strong> le protocole, un serveur HTTP doit fermer
les deux directions d'une communication indépendamment (rappelez-vous
qu'une connexion TCP est bidirectionnelle, chaque direction étant
indépendante de l'autre).</p>
<p>Quand cette fonctionnalité fut ajoutée à Apache, elle causa une
avalanche de problèmes sur plusieurs versions d'Unix à cause d'une
implémentation à courte vue. La spécification TCP ne précise pas que
l'état <code>FIN_WAIT_2</code> possède un temps de réponse mais elle ne
l'exclut pas. Sur les systèmes qui n'introduisent pas ce temps de
réponse, Apache 1.2 induit de nombreux blocages définitifs de socket
dans l'état <code>FIN_WAIT_2</code>. On peut eviter ceci dans de nombreux
cas tout simplement en mettant à jour TCP/IP avec le dernier patch mis à
disposition par le fournisseur. Dans les cas où le fournisseur n'a
jamais fourni de patch (par exemple, SunOS4 -- bien que les utilisateurs
possédant une license source puissent le patcher eux-mêmes), nous avons
décidé de désactiver cette fonctionnalité.</p>
<p>Il y a deux méthodes pour arriver à ce résultat. La première est
l'option de socket <code>SO_LINGER</code>. Mais le sort a voulu que cette
solution ne soit jamais implémentée correctement dans la plupart des
piles TCP/IP. Et même dans les rares cas où cette solution a été
implémentée correctement (par exemple Linux 2.0.31), elle se
montre beaucoup plus gourmande (en temps processeur) que la solution
suivante.</p>
<p>Pour la plus grande partie, Apache implémente cette solution à l'aide
d'une fonction appelée <code>lingering_close</code> (définie dans
<code>http_main.c</code>). La fonction ressemble approximativement à
ceci :</p>
<pre class="prettyprint lang-c"> void lingering_close (int s)
{
char junk_buffer[2048];
/* shutdown the sending side */
shutdown (s, 1);
signal (SIGALRM, lingering_death);
alarm (30);
for (;;) {
select (s for reading, 2 second timeout);
if (error) break;
if (s is ready for reading) {
if (read (s, junk_buffer, sizeof (junk_buffer)) <= 0) {
break;
}
/* just toss away whatever is here */
}
}
close (s);
}</pre>
<p>Ceci ajoute naturellement un peu de charge à la fin d'une connexion,
mais s'avère nécessaire pour une implémentation fiable. Comme HTTP/1.1
est de plus en plus présent et que toutes les connexions sont
persistentes, la charge sera amortie par la multiplicité des requêtes.
Si vous voulez jouer avec le feu en désactivant cette fonctionnalité,
vous pouvez définir <code>NO_LINGCLOSE</code>, mais c'est fortement
déconseillé. En particulier, comme les connexions persistantes en
pipeline de HTTP/1.1 commencent à être utilisées,
<code>lingering_close</code> devient une absolue nécessité (et les
<a href="http://www.w3.org/Protocols/HTTP/Performance/Pipeline.html">
connexions en pipeline sont plus rapides</a> ; vous avez donc tout
intérêt à les supporter).</p>
<h3>Fichier tableau de bord (Scoreboard file)</h3>
<p>Les processus parent et enfants d'Apache communiquent entre eux à
l'aide d'un objet appelé "Tableau de bord" (Scoreboard). Idéalement, cet
échange devrait s'effectuer en mémoire partagée. Pour les systèmes
d'exploitation auxquels nous avons eu accès, ou pour lesquels nous avons
obtenu des informations suffisamment détaillées pour effectuer un
portage, cet échange est en général implémenté en utilisant la mémoire
partagée. Pour les autres, on utilise par défaut un fichier d'échange sur
disque. Le fichier d'échange sur disque est non seulement lent, mais
aussi peu fiable (et propose moins de fonctionnalités). Recherchez dans
le fichier <code>src/main/conf.h</code> correspondant à votre
architecture soit <code>USE_MMAP_SCOREBOARD</code>, soit
<code>USE_SHMGET_SCOREBOARD</code>. La définition de l'un des deux
(ainsi que leurs compagnons respectifs <code>HAVE_MMAP</code> et
<code>HAVE_SHMGET</code>), active le code fourni pour la mémoire
partagée. Si votre système propose une autre solution pour la gestion de
la mémoire partagée, éditez le fichier <code>src/main/http_main.c</code>
et ajoutez la portion de code nécessaire pour pouvoir l'utiliser dans
Apache (Merci de nous envoyer aussi le patch correspondant).</p>
<div class="note">Note à caractère historique : le portage d'Apache sous Linux
n'utilisait pas la mémoire partagée avant la version 1.2. Ceci entraînait
un comportement très rudimentaire et peu fiable des versions antérieures
d'Apache sous Linux.</div>
<h3>DYNAMIC_MODULE_LIMIT</h3>
<p>Si vous n'avez pas l'intention d'utiliser les modules chargés
dynamiquement (ce qui est probablement le cas si vous êtes en train de
lire ce document afin de personnaliser votre serveur en recherchant le
moindre des gains en performances), vous pouvez ajouter la définition
<code>-DDYNAMIC_MODULE_LIMIT=0</code> à la construction de votre serveur.
Ceci aura pour effet de libérer la mémoire RAM allouée pour le
chargement dynamique des modules.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="trace" id="trace">Appendice : Analyse détaillée d'une trace</a></h2>
<p>Voici la trace d'un appel système d'Apache 2.0.38 avec le MPM worker
sous Solaris 8. Cette trace a été collectée à l'aide de la commande :</p>
<div class="example"><p><code>
truss -l -p <var>httpd_child_pid</var>.
</code></p></div>
<p>L'option <code>-l</code> demande à truss de tracer l'ID du LWP
(lightweight process--la version de Solaris des threads niveau noyau) qui
invoque chaque appel système.</p>
<p>Les autres systèmes peuvent proposer des utilitaires de traçage
des appels système différents comme <code>strace</code>,
<code>ktrace</code>, ou <code>par</code>. Ils produisent cependant tous une
trace similaire.</p>
<p>Dans cette trace, un client a demandé un fichier statique de 10 ko au
démon httpd. Le traçage des requêtes pour des contenus non statiques
ou comportant une négociation de contenu a une présentation
différente (et même assez laide dans certains cas).</p>
<div class="example"><pre>/67: accept(3, 0x00200BEC, 0x00200C0C, 1) (sleeping...)
/67: accept(3, 0x00200BEC, 0x00200C0C, 1) = 9</pre></div>
<p>Dans cette trace, le thread à l'écoute s'exécute à l'intérieur de
LWP #67.</p>
<div class="note">Notez l'absence de la sérialisation d'<code>accept(2)</code>. Sur
cette plateforme spécifique, le MPM worker utilise un accept non sérialisé
par défaut sauf s'il est en écoute sur des ports multiples.</div>
<div class="example"><pre>/65: lwp_park(0x00000000, 0) = 0
/67: lwp_unpark(65, 1) = 0</pre></div>
<p>Après avoir accepté la connexion, le thread à l'écoute réactive un
thread du worker pour effectuer le traitement de la requête. Dans cette
trace, le thread du worker qui traite la requête est associé à
LWP #65.</p>
<div class="example"><pre>/65: getsockname(9, 0x00200BA4, 0x00200BC4, 1) = 0</pre></div>
<p>Afin de pouvoir implémenter les hôtes virtuels, Apache doit connaître
l'adresse du socket local utilisé pour accepter la connexion. On pourrait
supprimer cet appel dans de nombreuses situations (par exemple dans le cas
où il n'y a pas d'hôte virtuel ou dans le cas où les directives
<code class="directive"><a href="../mod/mpm_common.html#listen">Listen</a></code> contiennent des adresses
sans caractères de substitution). Mais aucun effort n'a été accompli à ce
jour pour effectuer ces optimisations.</p>
<div class="example"><pre>/65: brk(0x002170E8) = 0
/65: brk(0x002190E8) = 0</pre></div>
<p>L'appel <code>brk(2)</code> alloue de la mémoire dans le tas. Ceci est
rarement visible dans une trace d'appel système, car le démon httpd
utilise des allocateurs mémoire de son cru (<code>apr_pool</code> et
<code>apr_bucket_alloc</code>) pour la plupart des traitements de requêtes.
Dans cette trace, le démon httpd vient juste de démarrer, et il doit
appeler <code>malloc(3)</code> pour réserver les blocs de mémoire
nécessaires à la création de ses propres allocateurs de mémoire.</p>
<div class="example"><pre>/65: fcntl(9, F_GETFL, 0x00000000) = 2
/65: fstat64(9, 0xFAF7B818) = 0
/65: getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B910, 2190656) = 0
/65: fstat64(9, 0xFAF7B818) = 0
/65: getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B914, 2190656) = 0
/65: setsockopt(9, 65535, 8192, 0xFAF7B918, 4, 2190656) = 0
/65: fcntl(9, F_SETFL, 0x00000082) = 0</pre></div>
<p>Ensuite, le thread de worker passe la connexion du client (descripteur
de fichier 9) en mode non blocant. Les appels <code>setsockopt(2)</code>
et <code>getsockopt(2)</code> constituent un effet de bord de la manière
dont la libc de Solaris utilise <code>fcntl(2)</code> pour les sockets.</p>
<div class="example"><pre>/65: read(9, " G E T / 1 0 k . h t m".., 8000) = 97</pre></div>
<p>Le thread de worker lit la requête du client.</p>
<div class="example"><pre>/65: stat("/var/httpd/apache/httpd-8999/htdocs/10k.html", 0xFAF7B978) = 0
/65: open("/var/httpd/apache/httpd-8999/htdocs/10k.html", O_RDONLY) = 10</pre></div>
<p>Ce démon httpd a été configuré avec les options
<code>Options FollowSymLinks</code> et <code>AllowOverride None</code>. Il
n'a donc ni besoin d'appeler <code>lstat(2)</code> pour chaque répertoire
du chemin du fichier demandé, ni besoin de vérifier la présence de fichiers
<code>.htaccess</code>. Il appelle simplement <code>stat(2)</code> pour
vérifier d'une part que le fichier existe, et d'autre part que c'est un
fichier régulier, et non un répertoire.</p>
<div class="example"><pre>/65: sendfilev(0, 9, 0x00200F90, 2, 0xFAF7B53C) = 10269</pre></div>
<p>Dans cet exemple, le démon httpd peut envoyer l'en-tête de la réponse
HTTP et le fichier demandé à l'aide d'un seul appel système
<code>sendfilev(2)</code>. La sémantique de sendfile varie en fonction des
systèmes d'exploitation. Sur certains autres systèmes, il faut faire un
appel à <code>write(2)</code> ou <code>writev(2)</code> pour envoyer les
en-têtes avant d'appeler <code>sendfile(2)</code>.</p>
<div class="example"><pre>/65: write(4, " 1 2 7 . 0 . 0 . 1 - ".., 78) = 78</pre></div>
<p>Cet appel à <code>write(2)</code> enregistre la requête dans le journal
des accès. Notez qu'une des choses manquant à cette trace est un appel à
<code>time(2)</code>. A la différence d'Apache 1.3, Apache 2.x utilise
<code>gettimeofday(3)</code> pour consulter l'heure. Sur certains systèmes
d'exploitation, comme Linux ou Solaris, <code>gettimeofday</code> est
implémenté de manière optimisée de telle sorte qu'il consomme moins de
ressources qu'un appel système habituel.</p>
<div class="example"><pre>/65: shutdown(9, 1, 1) = 0
/65: poll(0xFAF7B980, 1, 2000) = 1
/65: read(9, 0xFAF7BC20, 512) = 0
/65: close(9) = 0</pre></div>
<p>Le thread de worker effectue une fermeture "en prenant son temps"
(lingering close) de la connexion.</p>
<div class="example"><pre>/65: close(10) = 0
/65: lwp_park(0x00000000, 0) (sleeping...)</pre></div>
<p>Enfin, le thread de worker ferme le fichier qu'il vient de délivrer et
se bloque jusqu'à ce que le thread en écoute lui assigne une autre
connexion.</p>
<div class="example"><pre>/67: accept(3, 0x001FEB74, 0x001FEB94, 1) (sleeping...)</pre></div>
<p>Pendant ce temps, le thread à l'écoute peut accepter une autre connexion
à partir du moment où il a assigné la connexion présente à un thread de
worker (selon une certaine logique de contrôle de flux dans le MPM worker
qui impose des limites au thread à l'écoute si tous les threads de worker
sont occupés). Bien que cela n'apparaisse pas dans cette trace,
l'<code>accept(2)</code> suivant peut (et le fait en général, en situation
de charge élevée) s'exécuter en parallèle avec le traitement de la
connexion qui vient d'être acceptée par le thread de worker.</p>
</div></div>
<div class="bottomlang">
<p><span>Langues Disponibles: </span><a href="../en/misc/perf-tuning.html" hreflang="en" rel="alternate" title="English"> en </a> |
<a href="../fr/misc/perf-tuning.html" title="Français"> fr </a> |
<a href="../ko/misc/perf-tuning.html" hreflang="ko" rel="alternate" title="Korean"> ko </a> |
<a href="../tr/misc/perf-tuning.html" hreflang="tr" rel="alternate" title="Türkçe"> tr </a></p>
</div><div class="top"><a href="#page-header"><img src="../images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Commentaires</a></h2><div class="warning"><strong>Notice:</strong><br />This is not a Q&A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our <a href="http://httpd.apache.org/lists.html">mailing lists</a>.</div>
<script type="text/javascript"><!--//--><![CDATA[//><!--
var comments_shortname = 'httpd';
var comments_identifier = 'http://httpd.apache.org/docs/2.4/misc/perf-tuning.html';
(function(w, d) {
if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
d.write('<div id="comments_thread"><\/div>');
var s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
(d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
}
else {
d.write('<div id="comments_thread">Comments are disabled for this page at the moment.<\/div>');
}
})(window, document);
//--><!]]></script></div><div id="footer">
<p class="apache">Copyright 2019 The Apache Software Foundation.<br />Autorisé sous <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossaire</a> | <a href="../sitemap.html">Plan du site</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
if (typeof(prettyPrint) !== 'undefined') {
prettyPrint();
}
//--><!]]></script>
</body></html>
|