<  Retour au portail Polytechnique Montréal

Analyse de performance de systèmes distribués et hétérogènes à l'aide de traçage noyau

Francis Giraldeau

Thèse de doctorat (2015)

[img]
Affichage préliminaire
Télécharger (1MB)
Citer ce document: Giraldeau, F. (2015). Analyse de performance de systèmes distribués et hétérogènes à l'aide de traçage noyau (Thèse de doctorat, École Polytechnique de Montréal). Tiré de https://publications.polymtl.ca/1940/
Afficher le résumé Cacher le résumé

Résumé

RÉSUMÉ Les systèmes infonuagiques sont en utilisation croissante. La complexité de ces systèmes provient du fait qu'ils s'exécutent de manière distribuée sur des architectures multicoeurs. Cette composition de services est souvent hétérogène, c.-à-d. qui implique différentes technologies, librairies et environnements de programmation. L'interopérabilité est assurée plutôt par l'utilisation de protocoles ouverts. L'espace de configuration résultant croît de manière exponentielle avec le nombre de paramètres, et change continuellement en fonction des nouveaux besoins et de l'adaptation de la capacité. Lorsqu'un problème de performance survient, il doit être possible d'identifier rapidement la cause pour y remédier. Or, ce problème peut être intermittent et difficile à reproduire, et dont la cause peut être une interaction transitoire entre des tâches ou des ressources. Les outils utilisés actuellement pour le diagnostic des problèmes de performance comprennent les métriques d'utilisation des ressources, les outils de profilage, la surveillance du réseau, des outils de traçage, des débogueurs interactifs et les journaux systèmes. Or, chaque composant doit être analysé séparément, ou l'utilisateur doit corréler manuellement cette information pour tenter de déduire la cause du problème. L'observation globale de l'exécution de systèmes distribués est un enjeu majeur pour en maitriser la complexité et régler les problèmes efficacement. L'objectif principal de cette recherche est d'obtenir un outil d'analyse permettant de comprendre la performance d'ensemble d'une application distribuée. Ce type d'analyse existe au niveau applicatif, mais elles sont spécifiques à un environnement d'exécution ou un domaine particulier. Nos travaux se distinguent par l'utilisation d'une trace noyau, qui procure un niveau plus abstrait de l'exécution d'un programme, et qui est indépendant du langage ou des librairies utilisées. La présente recherche vise à déterminer si la sémantique des évènements du système d'exploitation peut servir à une analyse satisfaisante. Le surcout du traçage est un enjeu important, car il doit demeurer faible pour ne pas perturber le système et être utile en pratique. Nous proposons un nouvel algorithme permettant de retrouver les relations d'attente entre les tâches et les périphériques d'un ordinateur local. Nous avons établi que le chemin critique exact d'une application nécessite des évènements qui ne sont pas visibles depuis le système d'exploitation. Nous proposons donc une approximation du chemin critique, dénomée chemin actif d'exécution, où chaque attente est remplacée par sa cause racine. Les approches antérieures reposent sur l'analyse des appels système. L'analyse doit tenir en compte la sémantique de centaines d'appels système, ce qui n'est pas possible dans le cas général, car le fonctionnement d'un appel système dépend de l'état du système au moment de son exécution. Par exemple, le comportement de l'appel système read() est complètement différent si le fichier réside sur un disque local ou sur un serveur de fichier distant. L'appel système ioctl() est particulièrement problématique, car son comportement est défini par le programmeur. Le traçage des appels système contribue aussi à augmenter le surcout, alors qu'une faible proportion d'entre eux modifie le flot de l'exécution. Les tâches d'arrière-plan du noyau n'effectuent pas d'appels système et ne peuvent pas être prises en compte par cette méthode. À cause de ces propriétés, l'analyse basée sur des appels système est fortement limitée. Notre approche remplace les appels système par des évènements de l'ordonnanceur et des interruptions. Ces évènements de plus bas niveau sont indépendants de la sémantique des appels système et prennent en compte les tâches noyau. Le traçage des appels système est donc optionnel, ce qui contribue à réduire le surcout et simplifie drastiquement l'analyse. Les bancs d'essais réalisés avec des logiciels commerciaux populaires indiquent qu'environ 90% du surcout est lié aux évènements d'ordonnancement. En produisant des cycles d'ordonnancement à la fréquence maximale du système, il a été établi que le surcout moyen au pire cas est de seulement 11%. Nous avons aussi réalisé une interface graphique interactive montrant les résultats de l'analyse. Grâce à cet outil, il a été possible d'identifier avec succès plusieurs problèmes de performance et de synchronisation. Le fonctionnement interne et l'architecture du programme sont exposés par l'outil de visualisation, qui se révèle utile pour effectuer la rétro-ingénierie d'un système complexe. Dans un second temps, la dimension distribuée du problème a été ajoutée. L'algorithme de base a été étendu pour supporter l'attente indirecte pour un évènement distant, tout en préservant ses propriétés antérieures. Le même algorithme peut donc servir pour des processus locaux ou distants. Nous avons instrumenté le noyau de manière à pouvoir faire correspondre les paquets TCP/IP émis et reçus entre les machines impliqués dans le traitement à observer. L'algorithme tient en compte que la réception ou l'émission de paquets peut se produire de manière asynchrone. Les traces obtenues sur plusieurs systèmes n'ont pas une base de temps commune, car chacun possède sa propre horloge. Aux fins de l'analyse, toutes les traces doivent être synchronisées, et les échanges apparaitre dans l'ordre de causalité. Pour cette raison, les traces doivent être préalablement synchronisées. L'algorithme a été utilisé pour explorer le comportement de différentes architectures logicielles. Différentes conditions d'opérations ont été simulées (délais réseau, durée de traitement, retransmission, etc.) afin de valider le comportement et la robustesse de la technique. Il a été vérifié que le résultat obtenu sur une grappe d'ordinateurs est le même que celui obtenu lorsque les services s'exécutent dans des machines virtuelles. Le surcout moyen nécessaire pour tracer une requête Web s'établit à 5%. La borne supérieure du surcout pour des requêtes distantes est d'environ 18%. Pour compléter l'analyse, nous avons réalisé des cas d'utilisation impliquant six environnements logiciel et domaines différents, dont une application Web Django, un serveur de calcul Java-RMI, un système de fichier distribué CIFS, un service Erlang et un calcul parallèle MPI. Comme contribution secondaire, nous avons proposé deux améliorations à l'algorithme de synchronisation. La première consiste en une étape de présynchronisation qui réduit considérablement la consommation maximale de mémoire. La deuxième amélioration concerne la performance de la fonction de transformation du temps. Le temps est représenté en nanosecondes et le taux de variation à appliquer doit être très précis. L'utilisation de l'arithmétique à point flottant de précision double n'est pas assez précis et produit des inversions d'évènements. Un couteux calcul à haute précision est requis. Grâce à une simple factorisation de l'équation linéaire, la plupart des calculs à haute précision ont été remplacés par une arithmétique entière 64-bit. Les bancs d'essai ont mesuré que cette optimisation procure une accélération de 65 fois en moyenne et que la précision du résultat n'est pas affectée. Le troisième thème de la recherche porte sur le profilage des segments du chemin d'exécution. L'échantillonnage des compteurs de performance matériel permet le profilage du code natif avec un faible surcout. Une limitation concerne le code interprété qui peut se retrouver dans une application hétérogène. Dans ce cas, le code profilé est celui de l'interpréteur, et le lien avec les sources du programme est perdu. Nous avons conçu une technique permettant de transférer à un interpréteur l'évènement de débordement du compteur de performance, provenant d'une interruption non masquable du processeur. L'analyse de l'état de l'interpréteur peut être effectuée en espace utilisateur. Un module d'analyse pour Python a été développé. Nous avons comparé le cout des méthodes pour obtenir la pile d'appel de l'interpréteur Python et celle du code interprété. Ces données sont sauvegardées par l'entremise de LTTng-UST, dont la source de temps est cohérente avec les traces produites en mode noyau, ce qui permet d'associer les échantillons produits avec le chemin d'exécution. Nous avons validé le profil à l'aide d'une application d'étalonnage. Nous avons mesuré une erreur inférieure à 1%, et ce résultat est équivalent à celui produit par un profileur déterministe. La période d'échantillonnage est établie selon un compromis entre le surcout et la résolution de l'échantillonnage. Nos tests indiquent que, pour un chemin d'exécution de 50ms, une plage de taux d'échantillonnage existe et satisfait à la fois une marge d'erreur inférieure à 5% et un surcout de moins de 10%.----------ABSTRACT Cloud systems are increasingly used. These systems have a complex behavior, because they run on a cluster of multi-core computers. This composition of services is often heterogeneous, involving different technologies, libraries and programming environments. Interoperability is ensured using open protocols rather than standardizing runtime environments. The resulting configuration space grows exponentially with the number of parameters, and constantly changes in response to new needs and capacity adaptation. When a performance problem arises, it should be possible to quickly identify the cause in order to address it. However, performance problems can be intermittent and difficult to reproduce, and their cause can be a transient interaction between tasks or resources. The tools currently used to diagnose performance problems include resource utilization metrics, profiling tools, network monitoring, layout tools, interactive debuggers and system logs. However, each component must be analyzed separately, or the user must manually correlate that information to try deducing the root cause. Observing the performance of globally distributed systems is a major challenge, to master their complexity and solve problems effectively. The main objective of this research is to obtain an analysis tool for understanding the overall performance of a distributed application. This type of analysis exists at the application level, but they are specific to a runtime environment or a particular application domain. To address this issue, we propose to use kernel tracing, which provides a more abstract information about the execution of a program and is independent of the language or the libraries used. This research aims to determine whether the semantics of the operating system events are effective for performance analysis of such systems. The additional cost of tracing is an important issue because it must remain low, to avoid disturbing the system and be useful in practice. We propose a new algorithm to find the waiting relationships between tasks and devices on a local computer. We established that the exact critical path of an application requires events which are not visible from the operating system. We therefore propose an approximation of the critical path, that we named execution path. Previous approaches rely on system call analysis. However, the analysis must take into account the semantics of hundreds of system calls. Tracing all system calls increases the overhead, while most system calls do not change the flow of execution. Furthermore, the background kernel threads do not perform system calls and are not taken into account. Our approach relies instead on lower-level events, namely from the scheduler and the interruptions. These events are independent of the semantics of system calls and take into account the kernel threads. Tracing system calls is optional, which helps reduce the overhead and simplifies the analysis. The benchmarks made with popular commercial software indicate that about 90% of the overhead is related to scheduling events. By producing scheduling cycles at the maximum frequency, we established that the average worst case overhead is only 11%. Finally, we implemented an interactive graphical view showing the results of the analysis. With this tool, it was possible to identify quickly several performance and synchronization problems in actual applications. The tool also exposes the internal functioning and architecture of the program, which is useful for performing reverse engineering of a complex system. Secondly, we addressed the distributed dimension of the problem. The basic algorithm has been extended to support indirect network wait, while preserving its previous properties. The same algorithm can therefore be used for local or remote processes. We instrumented the kernel for matching the TCP/IP packets sent and received between machines involved in the processing. The algorithm takes into account the fact that reception and transmission of packets can occur asynchronously. The traces obtained on several systems do not have a common time base, as each has its own clock. The analysis requires that all traces have the same time reference and exchanges must appear in the causal order. For this reason, the traces must first be synchronized. The algorithm was used to explore the behavior of different software architectures. We simulated various operating conditions (network delays, processing delays, retransmission, etc.) to validate the behavior and robustness of the technique. We verified that the result on a cluster of physical computers is the same as the one obtained when the services are running inside virtual machines. The average overhead to trace Web requests is about 5%. The worst case overhead measured with the higest frequency remote procedure call (empty remote call) is approximately 18\%. To complete the analysis, we implemented use cases and software environments involving six different application domains, including a Django Web application, a Java-RMI server, a CIFS distributed file system, an Erlang service and a MPI parallel computation. As a secondary contribution, we proposed two improvements to the synchronization algorithm. The first is a pre-synchronization step that dramatically reduces the maximum memory consumption. The second improvement concerns the performance of the time transformation function. The time is represented in nanoseconds and the rate of change to apply must be very precise. The use of double precision floating point arithmetic is not accurate enough and produces event inversions. Expensive high-precision calculation is required. We replaced most of high-precision calculations by integer arithmetic of native register size, providing an average acceleration of approximately 65 times for the synchronization. The third area of research focuses on profiling the execution path segments. Sampling hardware performance counters allows efficient profiling of native code. One limitation concerns the interpreted code that may be found in an heterogeneous application. In this case, the native code running is the interpreter itself, and the link with the actual sources of the interpreted program is lost. We developed a technique to transfer to an interpreter the performance counter overflow event from the non-maskable interrupt of the processor. The analysis of the interpreter state can then be performed in user-space. To demonstrate the feasability of the approach, we implemented the analysis module for Python. We compared the cost of methods to get the call stack of the Python interpreter and the interpreted code. This data is saved through LTTng-UST, which has a time source consistent with the kernel mode trace and allows the association of the samples produced with the execution path. We validated the profile using a calibrated program. We measured less than 1% profile error, and this result is equivalent to the error rate of a deterministic profiler. The sampling period is a compromise between the overhead and the profile resolution. Our tests indicate that, for an execution path of 50ms, a range of sampling exists that satisfies both a margin of error lower than 5% and an overhead of less than 10%.

Document en libre accès dans PolyPublie
Département: Département de génie informatique et génie logiciel
Directeur de mémoire/thèse: Michel Dagenais
Date du dépôt: 01 avr. 2016 10:34
Dernière modification: 01 sept. 2017 17:32
Adresse URL de PolyPublie: https://publications.polymtl.ca/1940/

Statistiques

Total des téléchargements à partir de PolyPublie

Téléchargements par année

Provenance des téléchargements

Actions réservées au personnel