Как стать автором
Обновить

Комментарии 9

Дополнительно можно упоминуть еще два более «древних» механизма получения меток времени, годящиеся для любого протокола:
1. Через ioctl к сокету. struct timeval tv_rcv;

int res = ioctl(s, SIOCGSTAMP, &tv_rcv);

2. Через кольцевой буфер PACKET_SOCKET.
#include

typedef struct {
struct tpacket_hdr tp_h
__attribute__((aligned(TPACKET_ALIGNMENT)));
struct sockaddr_ll s_ll
__attribute__((aligned(TPACKET_ALIGNMENT)));
uint8_t data[0]
__attribute__((aligned(TPACKET_ALIGNMENT)));
} frame_map_hack_t;
/*
XXX volatile attr and invalidate cache ops may be needed in
many cases to access PACKET SOCKET ring buffers, also
keep in mind cache aliasing problems in some platforms
*/
typedef struct {
struct tpacket_hdr tp_h
__attribute__((aligned(TPACKET_ALIGNMENT)));
struct sockaddr_ll s_ll
__attribute__((aligned(TPACKET_ALIGNMENT)));

uint8_t data[CAP_SNAPLEN-sizeof(frame_map_hack_t)]
__attribute__((aligned(TPACKET_ALIGNMENT)));
} rx_ring_cell_t;


volatile rx_ring_cell_t *rc_cur = ps_rbuf;

tv_last.tv_sec = rc_cur->tp_h.tp_sec;
tv_last.tv_usec = rc_cur->tp_h.tp_usec;

Да, есть и такой способ. Можно после получения (recv) пакета из сокета дернуть ioctl SIOCGSTAMP или SIOCGSTAMPNS и получить время получения ядром этого пакета. Последний ioctl возвращает struct timespec допускающую точность до наносекунд, в отличие от первого, который возвращает struct timeval с микросекундами.


Полученное таким образов время ничем не будет отличаться времени полученного через SO_TIMESTAMPING с установленным флагом SOF_TIMESTAMPING_RX_SOFTWARE.


Но есть еще один способ получить то же самое, сделав на один системный вызов меньше. Опция сокета SO_TIMESTAMP (не путать с SO_TIMESTAMPING) включает доставку временных меток в контрольном сообщении. Временные метки те же самые, что и в SIOCGSTAMP.


См. Documentation/networking/timestamping.txt

А работа через кольцевой буфер PACKET SOCKET не требует никаких системных вызовов для получения данных и меток времени (recvmmsg/sendmsg, recv/send, read/write etc). Метки времени могут быть с микросекундной и наносекундной гранулярностью.
Правильно ли я понимаю что это работает только для UDP и RAW сокетов? А есть ли что-то похожее для TCP?

Как минимум есть TCP_INFO, где есть некоторые тайминги.

Мы хотим для event loop понять когда event loop тормозит. Т.е. получить что-то типа разницы во времени между тем когда ядро получило сообщение по TCP/IP и мы его прочитали из сокета.
Это возможно?

tcpi_last_data_recv даст что-то похоже на то, что хочется, только он отдаёт не таймштамп, а миллисекунды(1e-3!) с момента получения данных и разрешение у него в jiffies.


Я не уверен, укладывается ли такая точность в определение "тормозов" для конкретного случая.


Про использование обсуждаемых в статье таймштампов применительно TCP я не в курсе, надо исходники читать :-)

Первое что приходит на ум сравнить логи tcpdump/wireshark c логами strace -tt
на типичном офисном x86-32 и x86-64 точность будет порядка 50us если нужно точнее тогда придется встраиваться в ядро и «дампить» куда-нибудь в «отмепленную» память результаты rdtsc и в user space сравнивать и не забыть привязать ваш event loop к конкретному ядру процессора. На ppc и mips аналогично а вот у arm плохо с таймерами и гранулярность порядка 100ns к сожалению обычно предел :(

Кстати не забывайте отключать алгоритм nagle, если вам важна скорость доставки сообщений через TCP (TCP_NODELAY и выключенный TCP_CORC вам в помощь)

Documentation/networking/timestamping.txt об этом говорит следующее:


1.4 Bytestream Timestamps

The SO_TIMESTAMPING interface supports timestamping of bytes in a
bytestream. Each request is interpreted as a request for when the
entire contents of the buffer has passed a timestamping point. That
is, for streams option SOF_TIMESTAMPING_TX_SOFTWARE will record
when all bytes have reached the device driver, regardless of how
many packets the data has been converted into.

Они обещают сообщить пользовательскому приложению момент, когда последний байт данных пройдет "timestamping point". Хотя они упоминают явно только отправку пакета, полагаю что это применимо и к приему.


Лучшая документация по ядру — его исходники. Если разберетесь, обязательно расскажите нам :).

Зарегистрируйтесь на Хабре, чтобы оставить комментарий