Concernant l'utilité du tracing, c'est effectivement très varié. Chaque famille de tracepoint prend son sens dans un contexte différent. C'est aux developpeurs de leur donner du sens en écrivant les outils adaptés.
Prends par exemple les tracepoints de l'ordonnaceur de tâche. On a les suivants:
- context switch (tache A dort, tâche B prend la main)
- wakeup (tache A est mise en état "runnable")
- migrate (tache A est migrée du CPU x à CPU y)
Avec ça on peut analyser énormément de choses. On a un outil dans perf events qui s'appele "perf sched". Avec ça on peut tracer la latence de l'ordonnanceur: le temps maximum/moyen pour qu'une tâche, prête à être executée, est finalement executée. On pourrait aussi analyser l'efficacité des décisions de migration. Imagine que sur le CPU 0 on ait quatre tâches qui se battent en duel, et sur le CPU 1 une seule. Si cet état dure trop longtemps, ça signifie qu'il y a un soucis. Les tracepoints permettent d'analyser ce genre de comportement.
Mais le tracing peut aussi être utilisé pour du débuggage. Imagine que tu as un bug en ouvrant un fichier et que tu as besoin de voir quel chemin a été pris par le code.
Tu peux utiliser le function graph tracer pour determiner ce qui se passe à chaque appel de open:
# cd /debug/tracing/
# echo sys_open > set_graph_function
# echo function_graph > current_tracer
# less trace
0) | sys_open() {
0) | do_sys_open() {
0) | getname() {
0) 1.028 us | kmem_cache_alloc();
0) 0.924 us | strncpy_from_user();
0) 5.309 us | }
0) | alloc_fd() {
0) 1.028 us | _raw_spin_lock();
0) 0.991 us | expand_files();
0) 0.886 us | _raw_spin_unlock();
0) 6.931 us | }
0) | do_filp_open() {
0) | get_empty_filp() {
0) 1.622 us | kmem_cache_alloc();
0) | security_file_alloc() {
0) 0.804 us | cap_file_alloc_security();
0) 2.598 us | }
0) 9.536 us | }
0) | do_path_lookup() {
0) | path_init() {
0) 0.901 us | _raw_read_lock();
0) 0.991 us | _raw_read_unlock();
0) 4.994 us | }
Et là tu vois exactement ce qui se passe.
De plus il y a point de traçage statique et dynamique, quel sont les avantages/inconvénients de chacun ?
Les tracepoints statiques sont placés sur des endroits très stratégiques, pertinents pour le sous système en question. Ils permettent de couvrir la majorité des besoins de tracing.
Si quelqu'un veut observer un point moins stratégique, aller plus en profondeur, il peut définir un tracepoint dynamique.
Les statiques sont aussi plus "puissants" dans les données qu'ils peuvent remonter. On peut leur demander de déréférencer des pointeurs, observer des données à l'intérieur d'une structure...on peut leur demander de remonter tout ce qu'on veut en fait.
Les dynamiques n'ont pas encore cette puissance. On peut leur demander d'afficher quelques variables, pourvu qu'il s'agisse de simples entiers ou adresses. Mais déréférencer des pointeurs, on y est pas encore.
Donc les statiques sont plus puissants et précis dans les données qu'ils peuvent remonter, tandis que les dynamiques sont plus puissants dans le fait qu'ils peuvent être placés un peu n'importe où.
frédéric dit qu'"avoir des points de traçage statiques un peu partout dans le noyau n'enchantait pas grand monde dans la branche principale", mais pourquoi est-ce que maintenant ça ne les dérangent plus ?
Parce qu'avant, placer un tracepoint ne faisait que placer un tracepoint :-) C'est à dire que du code noyau pouvait demander à observer ce tracepoint etc...mais il n'y avait pas encore de code qui faisait ça.
Aujourd'hui, quand tu ajoutes un tracepoint, il est directement utilisable par le biais des outils de perf events, ou par debugfs. Tu peux l'activer/désactiver en passant par un fichier. Récupérer ses données formatées en ascii ou directement en binaire. Tu peux filter en utilisant des expressions conditionelles. Générer des scripts python/perl automatiquement pour les analyser, modifier ces scripts, etc....
Donc aujourd'hui, ils sont considérés comme utiles directement.
Sinon autre chose, à propos des "régressions" : est-ce que c'est une manière élégante de dire "bugs" ?
Quand quelque chose fonctionnait, et que soudain du nouveau code casse ce qui fonctionnait, ça s'appelle une regression. C'est le type de bug le plus redouté (avec les trous de sécurité)
[^] # Re: À propos du tracing
Posté par fweisbec . En réponse à la dépêche Nouvelle version 2.6.33 du noyau Linux. Évalué à 6.
Prends par exemple les tracepoints de l'ordonnaceur de tâche. On a les suivants:
- context switch (tache A dort, tâche B prend la main)
- wakeup (tache A est mise en état "runnable")
- migrate (tache A est migrée du CPU x à CPU y)
Avec ça on peut analyser énormément de choses. On a un outil dans perf events qui s'appele "perf sched". Avec ça on peut tracer la latence de l'ordonnanceur: le temps maximum/moyen pour qu'une tâche, prête à être executée, est finalement executée. On pourrait aussi analyser l'efficacité des décisions de migration. Imagine que sur le CPU 0 on ait quatre tâches qui se battent en duel, et sur le CPU 1 une seule. Si cet état dure trop longtemps, ça signifie qu'il y a un soucis. Les tracepoints permettent d'analyser ce genre de comportement.
Mais le tracing peut aussi être utilisé pour du débuggage. Imagine que tu as un bug en ouvrant un fichier et que tu as besoin de voir quel chemin a été pris par le code.
Tu peux utiliser le function graph tracer pour determiner ce qui se passe à chaque appel de open:
# cd /debug/tracing/
# echo sys_open > set_graph_function
# echo function_graph > current_tracer
# less trace
0) | sys_open() {
0) | do_sys_open() {
0) | getname() {
0) 1.028 us | kmem_cache_alloc();
0) 0.924 us | strncpy_from_user();
0) 5.309 us | }
0) | alloc_fd() {
0) 1.028 us | _raw_spin_lock();
0) 0.991 us | expand_files();
0) 0.886 us | _raw_spin_unlock();
0) 6.931 us | }
0) | do_filp_open() {
0) | get_empty_filp() {
0) 1.622 us | kmem_cache_alloc();
0) | security_file_alloc() {
0) 0.804 us | cap_file_alloc_security();
0) 2.598 us | }
0) 9.536 us | }
0) | do_path_lookup() {
0) | path_init() {
0) 0.901 us | _raw_read_lock();
0) 0.991 us | _raw_read_unlock();
0) 4.994 us | }
Et là tu vois exactement ce qui se passe.
De plus il y a point de traçage statique et dynamique, quel sont les avantages/inconvénients de chacun ?
Les tracepoints statiques sont placés sur des endroits très stratégiques, pertinents pour le sous système en question. Ils permettent de couvrir la majorité des besoins de tracing.
Si quelqu'un veut observer un point moins stratégique, aller plus en profondeur, il peut définir un tracepoint dynamique.
Les statiques sont aussi plus "puissants" dans les données qu'ils peuvent remonter. On peut leur demander de déréférencer des pointeurs, observer des données à l'intérieur d'une structure...on peut leur demander de remonter tout ce qu'on veut en fait.
Les dynamiques n'ont pas encore cette puissance. On peut leur demander d'afficher quelques variables, pourvu qu'il s'agisse de simples entiers ou adresses. Mais déréférencer des pointeurs, on y est pas encore.
Donc les statiques sont plus puissants et précis dans les données qu'ils peuvent remonter, tandis que les dynamiques sont plus puissants dans le fait qu'ils peuvent être placés un peu n'importe où.
frédéric dit qu'"avoir des points de traçage statiques un peu partout dans le noyau n'enchantait pas grand monde dans la branche principale", mais pourquoi est-ce que maintenant ça ne les dérangent plus ?
Parce qu'avant, placer un tracepoint ne faisait que placer un tracepoint :-) C'est à dire que du code noyau pouvait demander à observer ce tracepoint etc...mais il n'y avait pas encore de code qui faisait ça.
Aujourd'hui, quand tu ajoutes un tracepoint, il est directement utilisable par le biais des outils de perf events, ou par debugfs. Tu peux l'activer/désactiver en passant par un fichier. Récupérer ses données formatées en ascii ou directement en binaire. Tu peux filter en utilisant des expressions conditionelles. Générer des scripts python/perl automatiquement pour les analyser, modifier ces scripts, etc....
Donc aujourd'hui, ils sont considérés comme utiles directement.
Sinon autre chose, à propos des "régressions" : est-ce que c'est une manière élégante de dire "bugs" ?
Quand quelque chose fonctionnait, et que soudain du nouveau code casse ce qui fonctionnait, ça s'appelle une regression. C'est le type de bug le plus redouté (avec les trous de sécurité)