117 votes

Pourquoi la création d'un nouveau processus est-elle plus coûteuse sous Windows que sous Linux ?

J'ai entendu dire que la création d'un nouveau processus sur une machine Windows est plus coûteuse que sur Linux. Est-ce vrai ? Quelqu'un peut-il expliquer les raisons techniques pour lesquelles c'est plus cher et fournir des raisons historiques pour les décisions de conception à l'origine de ces raisons ?

77voto

Johannes Passing Points 1365

Mweerden : NT a été conçu pour le multi-utilisateur dès le premier jour, ce n'est donc pas vraiment une raison. Cependant, vous avez raison de dire que la création de processus joue un rôle moins important sur NT que sur Unix car NT, contrairement à Unix, favorise le multithreading plutôt que le multiprocessing.

Rob, il est vrai que le fork est relativement bon marché lorsque COW est utilisé, mais en fait, le fork est le plus souvent suivi d'un exec. Et un exec doit également charger toutes les images. Discuter des performances de la fourchette n'est donc qu'une partie de la vérité.

Lorsque l'on parle de la vitesse de création des processus, il est probablement bon de faire la distinction entre NT et Windows/Win32. En ce qui concerne NT (c'est-à-dire le noyau lui-même), je ne pense pas que la création de processus (NtCreateProcess) et la création de threads (NtCreateThread) soient significativement plus lentes que sur un Unix moyen. Il se peut qu'il y ait un peu plus de choses, mais je ne vois pas la raison principale de la différence de performance ici.

Si vous regardez Win32, cependant, vous remarquerez qu'il ajoute un certain nombre de frais généraux à la création de processus. Tout d'abord, il faut que le CSRSS soit informé de la création d'un processus, ce qui implique le LPC. Il faut qu'au moins kernel32 soit chargé en plus, et il doit effectuer un certain nombre de tâches comptables supplémentaires avant que le processus ne soit considéré comme un processus Win32 à part entière. Et n'oublions pas tous les frais généraux supplémentaires imposés par l'analyse des manifestes, la vérification si l'image nécessite un shim de compatibilité, la vérification si les politiques de restriction logicielle s'appliquent, yada yada.

Cela dit, je vois le ralentissement général dans la somme de toutes ces petites choses qui doivent être faites en plus de la création brute d'un processus, d'un espace VA et d'un fil initial. Mais comme je l'ai dit au début, en raison de la préférence accordée au multithreading par rapport au multitâche, les seuls logiciels sérieusement affectés par cette dépense supplémentaire sont les logiciels Unix mal portés. Bien que cette situation change lorsque des logiciels comme Chrome et IE8 redécouvrent soudainement les avantages du multiprocessing et commencent à démarrer et démanteler fréquemment des processus...

11 votes

Fork n'est pas toujours suivi par exec(), et les gens s'intéressent uniquement à fork(). Apache 1.3 utilise fork() (sans exec) sous Linux et threads sous Windows, même si, dans de nombreux cas, les processus sont forkés avant d'être nécessaires et conservés dans un pool.

5 votes

Sans oublier, bien sûr, la commande 'vfork', qui est conçue pour le scénario 'just call exec' que vous décrivez.

0 votes

les seuls logiciels sérieusement affectés par ces dépenses supplémentaires sont les logiciels Unix mal portés . Python, je vous regarde

30voto

Chris Smith Points 2858

Pour compléter ce qu'a dit JP, la plupart des frais généraux sont liés au démarrage de Win32 pour le processus.

Le noyau de Windows NT prend effectivement en charge la fourche COW. SFU (l'environnement UNIX de Microsoft pour Windows) les utilise. Cependant, Win32 ne prend pas en charge les fourches. Les processus SFU ne sont pas des processus Win32. La SFU est orthogonale à Win32 : il s'agit de deux sous-systèmes d'environnement construits sur le même noyau.

En plus des appels LPC hors processus à CSRSS Dans XP et les versions ultérieures, il y a un appel hors processus au moteur de compatibilité des applications pour trouver le programme dans la base de données de compatibilité des applications. Cette étape cause suffisamment de surcharge pour que Microsoft propose une option de stratégie de groupe pour désactiver le moteur de compatibilité sur WS2003 pour des raisons de performance.

Les bibliothèques d'exécution Win32 (kernel32.dll, etc.) effectuent également de nombreuses lectures de registre et initialisations au démarrage qui ne s'appliquent pas aux processus UNIX, SFU ou natifs.

Les processus natifs (sans sous-système d'environnement) sont très rapides à créer. SFU en fait beaucoup moins que Win32 pour la création de processus, de sorte que ses processus sont également rapides à créer.

MISE À JOUR POUR 2019 : ajouter LXSS : Sous-système Windows pour Linux

Le sous-système d'environnement LXSS remplace SFU pour Windows 10. Il est 100% en mode noyau et ne nécessite aucune des IPC que Win32 continue d'avoir. L'appel système pour ces processus est dirigé directement vers lxss.sys/lxcore.sys, de sorte que le fork() ou tout autre appel de création de processus ne coûte qu'un seul appel système pour le créateur, au total. [Une zone de données appelée instance] garde la trace de tous les processus LX, des threads et de l'état d'exécution.

Les processus LXSS sont basés sur des processus natifs, et non sur des processus Win32. Tous les éléments spécifiques à Win32, comme le moteur de compatibilité, ne sont pas du tout engagés.

29voto

Rob Walker Points 25840

Unix dispose d'un appel système "fork" qui "divise" le processus en cours en deux et vous donne un second processus identique au premier (modulo le retour de l'appel fork). Étant donné que l'espace d'adressage du nouveau processus est déjà opérationnel, cela devrait être moins coûteux que d'appeler "CreateProcess" dans Windows et de lui faire charger l'image exe, les dll associées, etc.

Dans le cas de la fourche, le système d'exploitation peut utiliser la sémantique "copy-on-write" pour les pages de mémoire associées aux deux nouveaux processus afin de s'assurer que chacun obtient sa propre copie des pages qu'il modifie par la suite.

28 votes

Cet argument n'est valable que dans le cas d'une véritable bifurcation. Si vous démarrez un nouveau processus, sous Unix, vous devez toujours forker et exécuter. Windows et Unix disposent tous deux de la fonction copy on write. Windows réutilisera certainement un EXE chargé si vous exécutez une deuxième copie d'une application. Je ne pense pas que votre explication soit correcte, désolé.

1 votes

0 votes

J'ai ajouté quelques données sur les performances dans ma réponse. stackoverflow.com/a/51396188/537980 Vous pouvez constater qu'il est plus rapide.

17voto

VolkerK Points 54118

En plus de la réponse de Rob Walker : De nos jours, vous avez des choses comme la bibliothèque native POSIX Thread Library - si vous le souhaitez. Mais pendant longtemps, la seule façon de "déléguer" le travail dans le monde Unix était d'utiliser fork() (et c'est toujours préférable dans de très nombreuses circonstances). Par exemple, une sorte de serveur de socket

socket\_accept()
fork()
if (child)
    handleRequest()
else
    goOnBeingParent()
La mise en œuvre de la fourche devait donc être rapide et de nombreuses optimisations ont été mises en œuvre au fil du temps. Microsoft a approuvé CreateThread ou même fibers au lieu de créer de nouveaux processus et d'utiliser la communication interprocessus. Je pense qu'il n'est pas "juste" de comparer CreateProcess à fork puisqu'ils ne sont pas interchangeables. Il est probablement plus approprié de comparer fork/exec à CreateProcess.

2 votes

Concernant votre dernier point : fork() n'est pas interchangeable avec CreateProcess(), mais on peut aussi dire que Windows devrait implémenter fork() alors, parce que cela donne plus de flexibilité.

1 votes

Mais fork+exec sous Linux est plus rapide que CreateThread sous MS-Windows. Et Linux peut faire le fork tout seul pour être encore plus rapide. Quelle que soit la comparaison, MS est plus lent.

13voto

mweerden Points 4291

Je pense que la clé de cette question réside dans l'utilisation historique des deux systèmes. Windows (et DOS avant cela) ont été à l'origine des systèmes mono-utilisateur pour personnel des ordinateurs. En tant que tels, ces systèmes n'ont généralement pas besoin de créer un grand nombre de processus en permanence ; en termes (très) simples, un processus n'est créé que lorsque cet utilisateur solitaire le demande (et nous, les humains, ne fonctionnons pas très vite, relativement parlant).

Les systèmes basés sur Unix sont à l'origine des systèmes et des serveurs multi-utilisateurs. Pour ces derniers en particulier, il n'est pas rare d'avoir des processus (par exemple des démons de messagerie ou http) qui divisent les processus pour gérer des tâches spécifiques (par exemple, s'occuper d'une connexion entrante). Un facteur important à cet égard est l'utilisation d'un système d'exploitation bon marché. fork (qui, comme le mentionne Rob Walker ( 47865 ), utilise initialement la même mémoire pour le processus nouvellement créé), ce qui est très utile car le nouveau processus dispose immédiatement de toutes les informations dont il a besoin.

Il est clair qu'au moins historiquement, la nécessité pour les systèmes Unix d'avoir une création rapide de processus est bien plus grande que pour les systèmes Windows. Je pense que c'est toujours le cas parce que les systèmes Unix sont encore très orientés processus, alors que Windows, en raison de son histoire, a probablement été plus orienté threads (les threads étant utiles pour créer des applications réactives).

Avertissement : je ne suis en aucun cas un expert en la matière, alors pardonnez-moi si je me suis trompé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X