Il a toujours été connu que les opérations sur disque sont lentes et nous connaissons les raisons pour lesquelles elles sont lentes. La question ici est donc de savoir pourquoi devons-nous attendre les E/S ou pourquoi existe-t-il une chose telle que IOWait, etc.?
Je veux dire que j'ai remarqué que lorsque vous effectuez des tâches d'E/S en arrière-plan, votre ordinateur devient beaucoup plus lent, j'ai particulièrement remarqué que lorsque vous utilisez Linux, si vous effectuez des tâches d'E/S plus longues , le système d'exploitation devient presque inutilisable jusqu'à ce qu'il soit terminé.
En effet, j'ai également trouvé ce sujet dans un article, il y a un extrait:
L'attente des E/S est de 12,1%. Ce serveur possède 8 cœurs (via cat/proc/cpuinfo). Ceci est très proche de (1/8 cœurs = 0,125)
Donc, fondamentalement, cela signifie qu'il ralentit beaucoup l'ordinateur, pourquoi? Je veux dire OK, maintenant l'ordinateur normal est au moins 2 cœurs, parfois 4 ou parfois ils en ont plus à cause de l'hyperthreading ou quelque chose comme ça. Mais maintenant, la question est de savoir pourquoi le CPU doit rester sur place, ne faisant pratiquement rien d'autre que d'attendre les E/S? Je veux dire l'idée de base ou l'architecture de la gestion des processus, maintenant je ne sais pas si c'est le système d'exploitation qui est responsable de cela, ou cela se résume-t-il à la partie matérielle, mais cela devrait être possible pour le processeur d'attendre ou de vérifiez régulièrement, tout en effectuant de nombreuses autres tâches et en revenant au processus IO quand il est prêt. En effet, si c'est une tâche si difficile et que le processeur devrait attendre, pourquoi n'est-ce pas? Comme cela, par exemple, il pourrait y avoir une sorte de mini processeur qui l'attendrait et fournirait la petite partie des données au processeur réel dès qu'il reviendrait au processus et donc au processus serait répété et nous n'aurions pas à consacrer pratiquement tout un cœur de processeur au processus de copie des données ... Ou serais-je celui qui devrait inventer ce genre de choses et obtenir un prix Nobel pour cela?: S
Maintenant d'accord, je le mets vraiment du point de vue des observateurs et je ne suis pas vraiment allé aussi loin dans le sujet, mais je ne comprends vraiment pas pourquoi le processeur doit fonctionner avec la vitesse du disque dur, alors qu'il pourrait simplement faites autre chose et revenez au disque dur une fois qu'il est prêt. L'idée n'est pas d'accélérer l'application qui a besoin de cette opération IO ou du processus de copie ou autre), mais l'idée est d'affecter de manière minimale la consommation du processeur tout en effectuant cette opération, de sorte que le système d'exploitation pourrait l'utiliser pour d'autres processus et l'utilisateur n'aurait pas à ressentir un décalage général de l'ordinateur lors de certaines opérations de copie ...
Les schémas d'E/S que vous décrivez sont couramment utilisés dans les ordinateurs.
pourquoi le CPU doit en fait rester là, ne faisant pratiquement rien d'autre que d'attendre les E/S?
Il s'agit de la méthode d'E/S la plus simple possible: E/S programmées . De nombreux systèmes embarqués et microprocesseurs bas de gamme n'ont qu'une seule instruction d'entrée et une seule instruction de sortie. Le processeur doit exécuter une séquence explicite d'instructions pour chaque caractère lu ou écrit.
mais il doit être possible pour le processeur d'attendre ou de vérifier régulièrement, tout en effectuant de nombreuses autres tâches et en ne retournant au processus IO que lorsqu'il est prêt
De nombreux ordinateurs personnels ont d'autres schémas d'E/S. Au lieu d'attendre dans une boucle étroite que le périphérique soit prêt ( attente occupée ), la CPU démarre le périphérique d'E/S lui demandant de générer une interruption quand c'est fait ( E/S pilotées par interruption ).
Bien que les E/S déclenchées par interruption soient un pas en avant (par rapport aux E/S programmées), elles nécessitent une interruption pour chaque caractère transmis et c'est cher ...
Par exemple, il pourrait y avoir une sorte de mini processeur qui l'attendrait et fournirait la petite partie des données au processeur réel dès qu'il reviendrait au processus et donc le processus serait répété et nous n'aurions pas pour consacrer pratiquement tout un cœur de processeur au processus de copie de données ...
La solution à de nombreux problèmes consiste à demander à quelqu'un d'autre de faire le travail! :-)
Le contrôleur/la puce DMA (accès direct à la mémoire) permet des E/S programmées, mais c'est à quelqu'un d'autre de le faire!
Avec DMA le CPU n'a qu'à initialiser quelques registres et il est libre de faire autre chose jusqu'à la fin du transfert (et une interruption est déclenchée).
Même DMA n'est pas totalement gratuit: les périphériques haute vitesse peuvent utiliser de nombreux cycles de bus pour les références de mémoire et les références de périphériques ( vol de cycle ) et le CPU doit attendre (la puce DMA a toujours une priorité de bus plus élevée).
L'attente des E/S est de 12,1%. Ce serveur possède 8 cœurs (via cat/proc/cpuinfo). Ceci est très proche de (1/8 cœurs = 0,125)
Je pense que cela vient de: Comprendre les E/S disque - quand devriez-vous vous inquiéter?
Eh bien, ce n'est pas étrange: le système (mySQL) doit récupérer toutes les lignes avant de manipuler les données et il n'y a pas d'autres activités.
Ici, il n'y a pas de problème d'architecture informatique/OS. C'est juste la façon dont l'exemple est défini.
Il peut tout au plus s'agir d'un problème de réglage du SGBDR ou d'un problème de requête SQL (index manquant, mauvais plan de requête, mauvaise requête ...)
Il est possible d'écrire asynchrone IO où vous dites au système d'exploitation d'envoyer un disque en lecture/écriture, puis allez faire autre chose et vérifiez ensuite si c'est fait. C'est loin d'être nouveau. Une méthode plus ancienne est en utilisant un autre thread pour l'IO.
Cependant, cela nécessite que vous ayez quelque chose à faire pendant que cette lecture est en cours d'exécution et vous ne serez pas autorisé à toucher le tampon que vous avez transmis pour le résultat.
Il est également beaucoup plus facile de programmer lorsque vous supposez que tout bloque les E/S.
Lorsque vous appelez une fonction de lecture bloquante, vous savez qu'elle ne reviendra que quelque chose a été lu et immédiatement après que vous pouvez commencer à le traiter.
La boucle de lecture typique est un bon exemple
//variables that the loop uses
char[1024] buffer;
while((read = fread(buffer, 1024, 1, file))>0){
//use buffer
}
Sinon, vous devez enregistrer l'état actuel de la fonction (généralement sous la forme d'un rappel + pointeur userData) et le transmettre + l'identifiant de l'opération de lecture à une boucle de type select()
. Là, si une opération est terminée, elle mappera l'identifiant de l'opération de lecture au rappel + pointeur de données et invoquera le rappel avec les informations de l'opération terminée.
void callback(void* buffer, int result, int fd, void* userData){
if(result<=0){
//done, free buffer and continue to normal processing
}
//use buffer
int readID = async_read(fd, buffer, userData->buff_size);
registerCallback(readId, callback, userData);
}
Cela signifie également que chaque fonction qui pourrait finir par utiliser cette lecture asynchrone devrait pouvoir gérer une continuation asynchrone. C'est un changement non trivial dans la plupart des programmes, vous demandez aux gens qui essaient de se lancer dans C # asynchrone à ce sujet.
Cependant synchrone IO vs asynchrone IO n'est pas la cause du ralentissement général. L'échange de pages dans est également une opération qui doit attendre sur IO. Le le planificateur passera simplement à un autre programme qui n'attend pas IO si l'un est ( IO wait est lorsque le processeur est inactif et il y a une IO opération en attente ).
Le vrai problème est que le disque dur et le CPU utilisent le même canal pour communiquer avec la RAM ; le bus mémoire. Et à moins que vous n'utilisiez RAID, il n'y a qu'un seul disque pour obtenir les données. Cela est encore pire si vous utilisez également une application graphique intensive, la communication avec le GPU interfère également.
En d'autres termes, le véritable goulot d'étranglement se situe probablement dans le matériel plutôt que dans le logiciel.
Ayez confiance que le traitement d'autres choses en attendant les E/S est assez rationalisé, presque aussi rationalisé que possible. Lorsque vous voyez que votre ordinateur n'attend les E/S que 12,1% du temps, cela signifie qu'il fait en fait beaucoup d'autres choses en parallèle. S'il devait vraiment attendre les E/S sans rien faire d'autre, il attendrait 99,9% du temps, c'est ainsi que les E/S sont lentes.
La seule façon de faire plus de choses en parallèle est de prédire ce que l'utilisateur pourrait vouloir faire ensuite, et nous ne sommes pas encore très bons dans ce genre de prédiction. Donc, si l'utilisateur effectue une opération qui nécessite la lecture d'un secteur particulier à partir du disque dur, et que ce secteur ne se trouve pas déjà dans le cache, le système d'exploitation commencera le très long processus de lecture de ce secteur, et il va essayer de voir s'il y a autre chose à faire dans l'intervalle. S'il y a un autre utilisateur qui veut un secteur différent, il mettra également cette demande en file d'attente. À un moment donné, toutes les demandes ont été mises en file d'attente et nous ne pouvons rien faire d'autre que d'attendre que la première d'entre elles soit satisfaite avant de pouvoir continuer. C'est juste une réalité de la vie.
ÉDITER:
Trouver une solution au problème de la façon de faire d'autres choses tout en faisant des E/S serait un exploit admirable, car ce serait en même temps une solution au problème de la façon de faire d'autres choses en veille. Un exploit incroyable qui serait, car cela signifierait que vous trouveriez du travail pour votre ordinateur, alors qu'il n'en a pas.
Vous voyez, c'est ce qui se passe: votre ordinateur est assis 99,99% du temps, sans rien faire. Quand vous lui donnez quelque chose à faire, il s'en va et le fait. Si ce faisant, il doit attendre les E/S, il reste là et attend. S'il a autre chose à faire lors des E/S, il le fait aussi. Mais s'il n'a rien d'autre à faire en plus des E/S, il doit rester là et attendre que les E/S soient terminées. Il n'y a aucun moyen de contourner cela, à part en vous inscrivant à SETI @ Home.
Le système d'exploitation (sauf s'il s'agit d'un système embarqué de très bas niveau ou de quelque chose d'exotique similaire) s'en occupe déjà: si votre application doit attendre les E/S, elle se bloquera généralement sur ces E/S et un autre thread ou application deviendra actif. L'ordonnanceur décide lequel.
Ce n'est que s'il n'y a aucun autre thread ou application en cours d'exécution que vous accumulez réellement du temps d'attente. Dans l'article que vous avez cité (merci à @manlio pour le lien), c'est le cas: vous avez 12,1% d'attente contre 87,4% inactif, ce qui signifie qu'un cœur attend que les E/S se terminent tandis que le reste ne fait rien du tout. Donnez à ce système quelque chose à faire, de préférence plusieurs choses, et le pourcentage d'attente devrait chuter.
L'un des principaux objectifs de la conception d'applications d'aujourd'hui est de garantir que même s'il n'y a qu'une seule application en cours d'exécution, et même si cette application attend à un moment donné des E/S, l'application peut toujours continuer sur un autre morceau de travail. Les threads sont une approche à cela, les E/S non bloquantes une autre, mais cela dépend beaucoup du type de travail que vous faites, si vous pouvez réellement faire quelque chose sans les données que vous attendez.
lorsque vous utilisez Linux, si vous effectuez des tâches d'E/S plus longues, le système d'exploitation devient presque inutilisable jusqu'à ce qu'elles soient terminées.
C'est généralement une indication d'une situation liée aux E/S. J'ose dire que le système ne ralentit pas car il ne peut pas faire assez de traitement CPU. Il est plus probable que cela soit lent car un certain nombre de choses dépendent des données du disque dur, qui est occupé à ce moment-là. Il peut s'agir d'applications que vous souhaitez exécuter mais qui doivent charger leurs fichiers exécutables, fichiers de bibliothèque, icônes, polices et autres ressources. Il peut s'agir d'applications que vous avez déjà en cours d'exécution, mais qui ont échangé une partie de leur mémoire et ont maintenant besoin de l'échanger à nouveau pour continuer. Il peut s'agir d'un démon qui, pour une raison ou une autre, pense qu'il doit non seulement écrire une ligne dans un fichier journal, mais également vider ce fichier journal avant de répondre à une demande.
Vous pouvez utiliser des outils tels que iotop
pour voir comment la capacité d'E/S est allouée aux processus et ionice
pour définir les priorités d'E/S pour les processus. Par exemple, sur une machine de bureau, vous pouvez classer tous les traitements de données en bloc dans la classe de planification idle
, de sorte que le moment où une application interactive a besoin de bande passante d'E/S, le traitement en bloc soit suspendu jusqu'à ce que l'application interactive soit terminée.
Cela dépend de votre code d'application. Je suppose que votre code fonctionne sous Linux.
Vous pouvez utiliser multi - threading (par exemple POSIX pthreads ) pour que les threads liés au calcul effectuent certains calculs tandis que d'autres threads liés aux IO font le IO (et en attente). Vous pourriez même avoir votre application en cours d'exécution plusieurs processus communiquer avec communication inter-processus (IPC), voir pipe (7) , fifo (7) , socket (7) , - nix (7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2) et lire Programmation Linux avancée etc ....
Vous pouvez utiliser IO non bloquant , par exemple passer O_NOBLOCK
à open (2) etc etc etc ...; alors vous devrez poll (2) et/ou utiliser SIGIO
signal (7) ... et gérer le EWOULDBLOCK
erreur de lire (2) etc ...
Vous pouvez utiliser les E/S asynchrones POSIX, voir aio (7)
Pour l'accès aux fichiers, vous pouvez donner des indications à cache de page , par ex. avec madvise (2) après mmap (2) et avec posix_fadvise (2) ; voir aussi le spécifique à Linux readahead (2)
Mais vous atteindriez éventuellement un goulot d'étranglement matériel (le bus, la RAM, etc ...). Voir aussi ionice (1)
J'ajoute un autre point de vue que d'autres, peut-être controversé:
Son problème typique des systèmes d'exploitation Linux. Décalage spécifique (recherchez "Décalage de la souris Linux"). Windows n'a pas ce problème. J'ai Windows 7 et Linux Mint à double démarrage. Même lorsque vous effectuez une opération de disque intensive dans Windows, Windows se sent bien, la souris se déplace normalement. Dans Linux opposé, il ne semble pas si lisse et parfois la souris traîne même pendant la navigation Web normale.
C'est probablement parce que la philosophie et l'histoire de ces deux systèmes sont différentes. Windows est depuis le début conçu pour les utilisateurs ordinaires, ses systèmes d'exploitation principalement graphiques. Et pour les utilisateurs de Windows, un comportement système non fluide et l'arrêt de la souris signalent que quelque chose ne va pas. Les programmeurs de Microsofts ont donc travaillé dur pour concevoir l'ensemble du système afin de minimiser les cas où les systèmes semblent lents. À l'opposé, Linux n'est pas initialement un système graphique, le bureau n'est qu'un ajout tiers ici. Et Linux est principalement conçu pour les pirates utilisant la ligne de commande. Faites avancer les choses. Linux n'est tout simplement pas conçu pour un comportement fluide, les sentiments n'ont pas d'importance ici.
Remarque: je ne dis pas que Windows est meilleur que Linux, je dis simplement qu'ils ont une philosophie globale différente, ce qui dans un environnement complexe peut conduire à un comportement/sentiment de haut niveau différent de ces systèmes.