Exécuter le conteneur avec -v /:/host
flag et exécutant perf report
dans le conteneur avec --symfs /host
flag le corrige :
96.59% a.out a.out [.] function
2.93% a.out [kernel.kallsyms] [k] 0xffffffff8105144a
0.13% a.out [nvidia] [k] 0x00000000002eda57
0.11% a.out libc-2.19.so [.] vfprintf
0.11% a.out libc-2.19.so [.] 0x0000000000049980
0.09% a.out a.out [.] main
0.02% a.out libc-2.19.so [.] _IO_file_write
0.02% a.out libc-2.19.so [.] write
Une partie de la raison pour laquelle cela ne fonctionne pas tel quel? La sortie de perf script
en quelque sorte jette un peu de lumière sur ceci :
...
a.out 24 3374818.880960: cycles: ffffffff81141140 __perf_event__output_id_sample ([kernel.kallsyms])
a.out 24 3374818.881012: cycles: ffffffff817319fd _raw_spin_lock_irqsave ([kernel.kallsyms])
a.out 24 3374818.882217: cycles: ffffffff8109aba3 ttwu_do_activate.constprop.75 ([kernel.kallsyms])
a.out 24 3374818.884071: cycles: 40053d [unknown] (/var/lib/docker/aufs/diff/9bd2d4389cf7ad185405245b1f5c7d24d461bd565757880bfb4f970d3f4f7915/a.out)
a.out 24 3374818.885329: cycles: 400544 [unknown] (/var/lib/docker/aufs/diff/9bd2d4389cf7ad185405245b1f5c7d24d461bd565757880bfb4f970d3f4f7915/a.out)
...
Notez le /var/lib/docker/aufs
chemin. Cela vient de l'hôte donc il n'existera pas dans le conteneur et vous devez aider perf report
pour le localiser. Cela se produit probablement parce que les événements mmap sont suivis par perf en dehors de tout groupe de contrôle et perf n'essaie pas de remapper les chemins.
Une autre option consiste à exécuter perf côté hôte, comme sudo perf record -a docker run -ti <container name>
. Mais la collection doit être à l'échelle du système ici (le -a
flag) car les conteneurs sont générés par le processus du démon docker qui ne se trouve pas dans la hiérarchie des processus de l'outil client docker que nous exécutons ici.
Une autre façon qui ne nécessite pas de changer la façon dont vous exécutez le conteneur (afin que vous puissiez profiler un processus déjà en cours d'exécution) consiste à monter la racine du conteneur sur l'hôte à l'aide de bindfs :
bindfs /proc/$(docker inspect --format {{.State.Pid}} $CONTAINER_ID)/root /foo
Exécutez ensuite le rapport de performances en tant que perf report --symfs /foo
Vous devrez exécuter perf record
à l'échelle du système, mais vous pouvez le limiter à la collecte d'événements uniquement pour le conteneur spécifique :
perf record -g -a -F 100 -e cpu-clock -G docker/$(docker inspect --format {{.Id}} $CONTAINER_ID) sleep 90