Esecuzione del contenitore con -v /:/host
flag e l'esecuzione di perf report
nel contenitore con --symfs /host
flag lo risolve:
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
Parte del motivo per cui non funziona così com'è? L'output di perf script
in qualche modo fa luce su questo:
...
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)
...
Nota il /var/lib/docker/aufs
sentiero. Viene dall'host, quindi non esisterà nel contenitore e devi aiutare perf report
per individuarlo. Ciò accade probabilmente perché gli eventi mmap vengono tracciati da perf al di fuori di qualsiasi cgroup e perf non tenta di rimappare i percorsi.
Un'altra opzione è eseguire perf lato host, come sudo perf record -a docker run -ti <container name>
. Ma qui la raccolta deve essere estesa a tutto il sistema (il file -a
flag) poiché i contenitori vengono generati dal processo daemon docker che non è nella gerarchia dei processi dello strumento client docker che eseguiamo qui.
Un altro modo che non richiede di modificare la modalità di esecuzione del contenitore (in modo da poter profilare un processo già in esecuzione) è montare la radice del contenitore sull'host utilizzando bindfs:
bindfs /proc/$(docker inspect --format {{.State.Pid}} $CONTAINER_ID)/root /foo
Quindi esegui il report perf come perf report --symfs /foo
Dovrai eseguire perf record
a livello di sistema, ma puoi limitarlo a raccogliere solo eventi per il contenitore specifico:
perf record -g -a -F 100 -e cpu-clock -G docker/$(docker inspect --format {{.Id}} $CONTAINER_ID) sleep 90