Краткий ответ: для точной задержки в ядре следует использовать perf probe и perf script.
Подробнее. Давайте посмотрим на следующий пример. Сначала мы хотим посмотреть, какие функции используются для теста TCP ping-pong (я использую netperf).
В потоке приема:
В потоке передачи:
Итак, давайте проследим некоторые функции потока передачи (он длинный, поэтому я покажу основные функции в потоке TCP). Мы можем использовать зонд perf для выборки точки входа и выхода для каждой функции:
perf probe --add sock_sendmsg='sock_sendmsg'
perf probe --add sock_sendmsg_exit='sock_sendmsg%return'
perf probe --add inet_sendmsg='inet_sendmsg'
perf probe --add inet_sendmsg_exit='inet_sendmsg%return'
perf probe --add tcp_sendmsg_exit='tcp_sendmsg%return'
perf probe --add tcp_sendmsg='tcp_sendmsg'
perf probe --add tcp_sendmsg_locked='tcp_sendmsg_locked'
perf probe --add tcp_sendmsg_locked_exit='tcp_sendmsg_locked%return'
perf probe --add sk_stream_alloc_skb='sk_stream_alloc_skb'
perf probe --add sk_stream_alloc_skb_exit='sk_stream_alloc_skb%return'
perf probe --add tcp_push_exit='tcp_push%return'
perf probe --add tcp_push='tcp_push'
perf probe --add tcp_send_mss='tcp_send_mss'
perf probe --add tcp_send_mss_exit='tcp_send_mss%return'
perf probe --add __tcp_push_pending_frames='__tcp_push_pending_frames'
perf probe --add __tcp_push_pending_frames_exit='__tcp_push_pending_frames%return'
perf probe --add tcp_write_xmit_exit='tcp_write_xmit%return'
perf probe --add tcp_transmit_skb_exit='tcp_transmit_skb%return'
perf probe --add tcp_transmit_skb='tcp_transmit_skb'
Нет, мы можем записать это:
perf record -e probe:* -aR taskset -c 7 netperf -t TCP_RR -l 5 -T 7,7
И запустите сценарий perf для отчета о задержке:
perf script -F time,event --ns
Выход (1 итерация):
525987.403094082: probe:sock_sendmsg:
525987.403095586: probe:inet_sendmsg:
525987.403096192: probe:tcp_sendmsg:
525987.403098203: probe:tcp_sendmsg_locked:
525987.403099296: probe:tcp_send_mss:
525987.403100002: probe:tcp_send_mss_exit:
525987.403100740: probe:sk_stream_alloc_skb:
525987.403101697: probe:sk_stream_alloc_skb_exit:
525987.403103079: probe:tcp_push:
525987.403104284: probe:__tcp_push_pending_frames:
525987.403105575: probe:tcp_transmit_skb:
525987.403110178: probe:tcp_transmit_skb:
525987.403111640: probe:tcp_transmit_skb_exit:
525987.403112876: probe:tcp_transmit_skb_exit:
525987.403114351: probe:tcp_write_xmit_exit:
525987.403114768: probe:__tcp_push_pending_frames_exit:
525987.403115191: probe:tcp_push_exit:
525987.403115718: probe:tcp_sendmsg_locked_exit:
525987.403117576: probe:tcp_sendmsg_exit:
525987.403118082: probe:inet_sendmsg_exit:
525987.403118568: probe:sock_sendmsg_exit:
Теперь довольно легко увидеть, на что тратится задержка. Например, мы можем заметить, что между вызовами sock_sendmsg () и inet_sendmsg () существует задержка в 1504 наносекунды (нс) или 1,504 микросекунды (нас). Также мы видим, что sk_stream_alloc_skb занимает 957 нс. В целом весь процесс (от входа sock_sendmsg до выхода) занимает ~ 24,5 мкс. Имейте в виду, что это не то, что вы увидите в netperf, поскольку пакет физически передается где-то в середине потока.
Вы можете использовать тот же метод для отслеживания любого фрагмента кода в ядре.
Надеюсь это поможет.
P.S. Это было сделано на ядре 4.14, а не 2.6. Не знаю, насколько тогда была развита производительность, так что это могло не сработать.
person
Tgilgul
schedule
25.11.2017