PHP facteur 30 différence de performances de Linux à Windows

Notre équipe de travail est le développement de plugins WordPress et fournit des cas hébergé sur un couple de serveurs indépendants. Notre installation de WordPress est géré par Git, tous les serveurs ont la même source & programme d'installation de WordPress déployé, seuls les domaines & les données dans la base de données varie. Pour chaque installation, MySql est en cours d'exécution sur le même hôte. WordPress est exécuté exclusivement sur chaque serveur.

Cependant, après avoir déployé cette installation sur un Windows Server 2008 RC2, nous avons remarqué une chute drastique de différence de performance par rapport à nos autres serveurs: génération de la page le temps passe de avg. 400ms à 4000-5000 ms pour les pages générées avec PHP. Pour les ressources statiques livré par Apache seulement, la vitesse est environ le même que sur linux.

Nous avons donc pris des mesures pour réduire le problème:

  1. Assurez-vous il n'y a pas de antivir logiciel en cours d'exécution ou autre domaine windows trucs interférer
  2. Collecter les données de profilage pour identifier les timekillers au cours de l'exécution du script
  3. De tester les différents serveur & les configurations des matériels
  4. Double-vérifier à la fois d'Apache et de PHP de configuration pour d'évidentes erreurs de configuration

Après un certain profilage nous avons rapidement remarqué que l'évaluation des expressions régulières est horriblement lent sur nos machines windows. L'évaluation de 10.000 expressions Régulières (preg_match) prend environ 90ms sur Linux et 3000ms sur Windows.

De profilage, des tests de système et la configuration des détails sont fournis ci-dessous. Nous ne voulons pas d'optimiser ce script (dont nous ne savons comment le faire). Nous voulons obtenir le script à exécuter environ la même vitesse sur windows que sur Linux (étant donné que la même configuration concernant opcache/...). Pas besoin d'optimiser l'empreinte mémoire du script de trop.

Mise à jour: Après un certain temps, les systèmes de semble manquer de mémoire, le déclenchement de la mémoire des exceptions et aléatoire des allocations. Voir ci dessous pour plus de détails. Le redémarrage d'Apache/PHP résolu le problème pour l'instant.

Trace de _get_browser est:

File (called from)
require wp-blog-header.php (index.php:17)
wp (wp-blog-header.php:14)
WP->main (functions.php:808)
php::do_action_ref_array (class-wp.php:616)
php::call_user_func_array (wp-includes/plugin:507)
wp_slimstat::slimtrack  (php::internal (507))
wp_slimstat::_get_browser (wp-slimstat.php:385)

Mise à jour 2: Certains une raison que je ne me souviens pas, nous sommes retournés à l'activation de PHP en tant que Module Apache sur nos serveurs (le même qui livrent mauvaise performance). Mais aujourd'hui, ils courent très rapide (~1s/demande). L'ajout de Opcache apporte cela à l' ~400ms/req. Apache/PHP/Windows est resté le même.

1) Le Profilage Des Résultats

De profilage a été fait avec XDebug sur toutes les machines. Habituellement, nous ne sont collectées que quelques pistes à ceux qui ont suffit à révéler l'endroit où la plupart du temps (50%+) a été consacré à la méthode [get_browser][1] du plugin WordPress wp-slimstats:

protected static function _get_browser(){
    //Load cache
    @include_once(plugin_dir_path( __FILE__ ).'databases/browscap.php');
    //browscap.php contains $slimstat_patterns and $slimstat_browsers

    $browser = array('browser' => 'Default Browser', 'version' => '1', 'platform' => 'unknown', 'css_version' => 1, 'type' => 1);
    if (empty($slimstat_patterns) || !is_array($slimstat_patterns)) return $browser;

    $user_agent = isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:'';
    $search = array();
    foreach ($slimstat_patterns as $key => $pattern){
        if (preg_match($pattern . 'i', $user_agent)){
            $search = $value = $search + $slimstat_browsers[$key];
            while (array_key_exists(3, $value) && $value[3]) {
                $value = $slimstat_browsers[$value[3]];
                $search += $value;
            }
            break;
        }
    }

    //Lots of other lines to relevant to the profiling results
  }

Cette fonction similaire à PHP get_browser détecte les capacités du navigateur et de l'OS. La plupart de l'exécution du script de temps est passé dans cette foreach boucle, l'évaluation de tous ceux preg_match (~environ 8000 - 10000 per demande de page). Cela prend environ 90ms sur Linux et 3000ms sur Windows. Les résultats étaient les mêmes sur toutes les configurations testées (tableau montre les données de deux exécutions):

PHP facteur 30 différence de performances de Linux à Windows

Sûr, le chargement de deux tableaux de grande prend un certain temps. L'évaluation des expressions régulières aussi. Mais nous nous attendons à ce que la prendre à peu près en même temps sur Linux et Windows. C'est le profilage de résultat sur une machine virtuelle linux (une demande de page uniquement). La différence est assez évident:

PHP facteur 30 différence de performances de Linux à Windows

Un autre tueur de temps a fait l'Objet de la mémoire Cache de WordPress utilise:

function get( $key, $group = 'default', $force = false, &$found = null ) {
    if ( empty( $group ) )
        $group = 'default';

    if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
        $key = $this->blog_prefix . $key;

    if ( $this->_exists( $key, $group ) ) {
        $found = true;
        $this->cache_hits += 1;
        if ( is_object($this->cache[$group][$key]) )
            return clone $this->cache[$group][$key];
        else
            return $this->cache[$group][$key];
    }

    $found = false;
    $this->cache_misses += 1;
    return false;
}

De temps est passé dans cette fonction elle-même (3 exécutions de scripts):

PHP facteur 30 différence de performances de Linux à Windows

Sur linux:

PHP facteur 30 différence de performances de Linux à Windows

Le dernier vrai grand tueur de temps ont été traduits. Chaque traduction, chargé de la mémoire, prend quelque chose de 0,2 ms à 4ms dans WordPress:
PHP facteur 30 différence de performances de Linux à Windows

Sur linux:

PHP facteur 30 différence de performances de Linux à Windows

2) les systèmes Testés

Afin de s'assurer de la virtualisation ou Apache influent sur cela, nous l'avons testé sur plusieurs configurations. Antivir est désactivé sur toutes les configurations:

  • Linux Debian, Apache 2 & PHP, jusqu'à ce jour les versions stables. C'est la même chose pour les développeurs d'exécution dans leurs machines virtuelles comme pour la mise en scène/serveurs en direct. Agissant comme un système de référence de la performance désirée. Soit dans nos bureaux ou à certaines d'hébergement fournit (espace partagé). Les Systèmes Windows avait entre 4 go et 8 go de RAM, à tous les temps de l'utilisation de la mémoire a été sous le seuil des 50%. Virtualizations ne jamais exécuter Windows & Apache en même temps.
  • De vie des Serveurs, la course à T-Systems (gestion de serveurs virtualisés), sur VMWare Player
    • Win 2008 R2. Apache 2.2.25 + PHP 5.4.26 NTS,VC9 comme module fastcgi
    • Win 2008 R2. Apache 2.2.25 + PHP 5.5.1 NTS,VC11 comme module fastcgi
    • Win 2008 R2. Apache 2.2.25 + PHP 5.5.1 NTS,VC11 en tant que module apache
    • Win 2008 R2, Apache 2.2.25 + PHP 5.5.11 TS,VC11 en tant que module apache (c'est le plus rapide que j'ai mentionné dans la mise à jour 2)
  • Sur une machine locale, de l'Hôte: OpenSuse, la Virtualisation: VMWare player, de même que @T-Systems. Pour éviter à leurs infrastructures, nous influence:
    • Win 2008 R2. Apache 2.2.25 + PHP 5.4.26 NTS,VC9 comme module fastcgi
    • Win 2008 R2. IIS7 + PHP 5.4.26 NTS,VC9 comme module fastcgi (avec et sans wincache)
    • Gagner 2012. IIS * + PHP 5.5.10 NTS,VC11 comme module fastcgi (avec et sans wincache)
  • Sur une machine locale sans la virtualisation
    • Win 2008 R2. Apache 2.2.25 + PHP 5.4.26 NTS,VC9 comme module fastcgi

De profilage des résultats comme mentionné ci-dessus étaient les mêmes sur les différents systèmes (~10% de la dérivation). Windows a toujours été un facteur important plus lent que Linux.

À l'aide d'une nouvelle installation de WordPress & Slimstats entraîné env. les mêmes résultats. Réécrire le code n'est pas une option ici.

Mise à jour: en Attendant, nous avons trouvé deux autres Systèmes Windows (Windows 2008 R2, VM & Phys) où cette pile fonctionne très rapide. Même configuration que.

Mise à jour 2: l'Exécution de PHP en tant que module apache sur la durée de Vie des Serveurs a été légèrement plus rapide que la fastcgi méthode: jusqu'à ~2sec, 50% de moins.

À cours de Mémoire

Après un certain temps, notre Vivre-Server cesse de travailler à tous, le déclenchement de ces de mémoire exceptions:

PHP Fatal error:  Out of memory (allocated 4456448) (tried to allocate 136 bytes)
PHP Fatal error:  Out of memory (allocated 8650752) (tried to allocate 45 bytes) 
PHP Fatal error:  Out of memory (allocated 6815744) (tried to allocate 24 bytes) 

Ce qui se passe au hasard emplacement des scripts. Évidemment, le Gestionnaire de Mémoire Zend n'est pas en mesure d'allouer plus de mémoire, bien que les scripts soient autorisés à le faire. À l'époque, si l'incident, le serveur a eu environ 50% de libérer de la mémoire vive (2 GO+). Si le serveur n'a pas effectivement de la mémoire vive. Le redémarrage d'Apache/PHP résolu ce problème pour l'instant.

Ne sais pas si ce problème est lié à la performance de questions ici. Pourtant, comme les deux questions semblent être liés à la mémoire, son inclus ici. En particulier, nous allons essayer de reproduire les paramètres de Windows-Tests qui ont fourni des performances décentes.

3) Apache & Configuration de PHP

... n'ont probablement pas tous les pièges les plus courants. De sortie de la mémoire Tampon est activée (par défaut), multibye priorité désactivée, ... Si tout option(s) sont d'intérêt, nous serons heureux de fournir.

Sortie de httpd.exe -V

Server version: Apache/2.4.7 (Win32)
Apache Lounge VC10 Server built:   Nov 26 2013 15:46:56
Server's Module Magic Number: 20120211:27
Server loaded:  APR 1.5.0, APR-UTIL 1.5.3
Compiled using: APR 1.5.0, APR-UTIL 1.5.3
Architecture:   32-bit
Server MPM:     WinNT
  threaded:     yes (fixed thread count)
    forked:     no
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses disabled)
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/apache"
 -D SUEXEC_BIN="/apache/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error.log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

mpm_winnt_module configuration:

<IfModule mpm_winnt_module>
    ThreadsPerChild 150
    ThreadStackSize 8388608 
    MaxConnectionsPerChild 0
</IfModule>

Extrait de php.ini:

realpath_cache_size = 12M
pcre.recursion_limit = 100000

4) Courant soupçonné raison

Hypothèse ancienne:

Tous les trois exemples s'appuient largement sur de grands tableaux et les opérations de la chaîne. Qu'un type qui semble être la commune d'usine. Comme les travaux de mise en œuvre ok new'ish sur Linux, nous soupçonnons que cela soit un problème de mémoire sur Windows. Il n'existe pas d'interaction de base de données au détour des lieux, nous ne soupçonne pas le Serveur ou base de données <-> PHP intégration pour être le problème. En quelque sorte de mémoire PHP interaction semble juste être lent. Peut-être il ya quelqu'un d'interférer avec la mémoire sous Windows, rendant l'accès considérablement plus lent?

Vieille hypothèse 2:

Que la même pile fonctionne très bien sur d'autres machines sous Windows, nous supposons que le problème doit être quelque part dans la configuration de Windows.

Nouvelle hypothèse 3:

En fait, je suis d'hypothèses. Pourquoi irait PHP que beaucoup plus lent que fastcgi puis en tant que module apache>

Des idées sur la façon de vérifier cela, ou trouver le vrai problème ici? Toute aide ou d'orientation pour la résolution de ce problème est très bienvenu.

  • Êtes-vous en cours d'exécution à la fois sur le même matériel?
  • apache & mysql? oui. Étant donné le contexte actuel de la mémoire / CPU de la consommation et de l'emplacement de temps passé, cela ne devrait pas poser un problème.
  • Non, je veux dire windows et linux
  • non, différentes machines. Même pour les différents Tests Windows.
  • Je veux dire: Sont-ils comparables?
  • ils ont tous le même partitionnement du disque dur (et les applications sont sur le même emplacement), la quantité de ram et environ la même Vitesse du PROCESSEUR. Des différences mineures oui, mais rien de radical. Linux, VMs sont probablement les plus limitée de ceux (encore plus performants).
  • (en disant: le windows serveurs de tests, tous étaient équipés de façon meilleurs que n'importe quel serveur linux, nous avons utilisé).
  • Qu'est-ce que le Windows Apache taille de la pile? Est-il le même?
  • Elle a été définie par défaut, il a augmenté de 8 MO. pas de changements dans la performance. À cours de pile doit au moins résultat dans les processus d'être tué. Processus de finition toujours bien. Ajout de la sortie de httpd -V et la mpm_winnt_module de configuration dans la question.
  • Sont Apache, PHP, et le fastcgi tous les modules 64 bits? (Et je suppose que vous voulez dire Windows Server 2008 R2, pas RC2?)
  • Tous les Logiciels en versions 32 bits. Et oui, bien sûr R2 🙂
  • Que pourrait être un facteur, je voudrais essayer les versions 64 bits si disponible.
  • Nous avons vécu la même que celle décrite dans ce thread: stackoverflow.com/questions/21448661/... . Il n'y avait pas de différence de performances (au moins pas assez pour résoudre ce problème ici).
  • Je ne sais pas si c'est une option pour vous, mais si vous voulez réparer rapidement, aurait PHP+IIS être vaut la peine d'essayer? Je crois que PHP les performances de l'intérieur IIS a été considérablement améliorée récemment, en raison de travaux conjoints entre Zend et Microsoft. Je n'ai aucune idée si cela peut aider dans ce cas, vous l'esprit.
  • IIS est une parfaitement bien de remplacement. Nous avons cependant eu la même mauvaise performance sur IIS (voir 2) les Systèmes Testés).
  • Avez-vous jamais résoudre ce problème ? Nous avons aussi remarqué que PHP et WordPress sont très lents sur windows.
  • malheureusement pas. nous avons déménagé à une machine physique avec un excédent de ressources et tout a fonctionné okish. Il propose toujours de manière plus mauvaise performance et de voir toutes ces ressources vont à la poubelle avec une telle mauvaise performance, assurez-vous blesse (24 cœurs, 32 go de ram), mais de génération de la page est d'environ maintenant correctement au moins. Heureusement, nous avons enfin peut passer à linux dans les prochains mois 🙂
  • Curieusement, le commentateur dans le sljit.sourceforge.net/regex_perf.html a trouvé la plupart des regex analyseurs plus rapide dans MSWindows que Linux. (alhtough ils ne triche et exécutez le MSWindows tests sur du matériel plus puissant)

InformationsquelleAutor Fge | 2014-04-03