Сокет Python UDP, неизвестная задержка

#python #sockets #udp #real-time #delay

#python #сокеты #udp #в режиме реального времени #задержка

Вопрос:

Я отправляю 32-байтовые данные из приложения реального времени в экземпляр python с использованием сокетов UDP каждые 1 мс. Отправитель настроен на отправку UDP-пакетов с временным разрешением 1 мс. На принимающей стороне после каждых нескольких итераций у меня задержка в 15 или 16 мс. Может ли кто-нибудь, пожалуйста, помочь мне понять, почему? Использование виртуальной машины Windows. 2-ядерный процессор Intel Xeon Gold 5120, 2,20 ГГц, 6 ГБ оперативной памяти, с ОС Windows 10 Pro.

 ## Import necessary libraries

import socket
import time
"""
just get the raw values from UDP socket every 1ms
The sender sends it with that temporal resolution

"""

UDP_IP = "10.10.114.22"
UDP_PORT = 8208 #UDP phasor values 32 bytes (V,phi,P)
sock_ph = socket.socket(socket.AF_INET,  # Internet
                     socket.SOCK_DGRAM)  # UDP
sock_ph.bind((UDP_IP, UDP_PORT))
print("socket bound, waiting for data...")

while True:
    time_before_raw = time.monotonic_ns()
    raw = sock_ph.recv(32) #I am receiving 32 bytes data
    time_after_raw = time.monotonic_ns()
    print((time_after_raw-time_before_raw),raw,len(raw))
  

Печатный результат выглядит следующим образом:

Вывод, показывающий неизвестную задержку

Я попробовал с wireshark и смог увидеть, что пакеты данных поступают с интервалом в 1 мс. Таким образом, в основном сокет python, вероятно, имеет некоторую проблему с буферизацией. Снимок экрана Wireshark, показывающий временное разрешение данных в 1 мс

При дальнейшем исследовании видно, что 14-16 пакетов UDP поступают в среду python почти все одновременно (задержка 0 мс между ними), затем через 14-16 мс поступает следующая партия пакетов. Как будто есть какой-то буфер.

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

1. Учитывая, что вы показываете только 0 и 16 мс, я подозреваю, что ваши часы просто тикают с шагом 16 мс.

2. Что произойдет, если вы используете time.perf_counter_ns() ?

3. То же самое, есть реальный случай хранения 14-16 пакетов данных, а затем отправки их сразу. Это не проблема с синхронизацией, а какая-то проблема с буфером данных. По крайней мере, я так думаю. Я пробовал datetime, time.perft … но результат всегда один и тот же. 14-16 пакетов с одинаковой временной меткой и задержкой 14-16 мс, а затем следующие 14-16 пакетов.

4. Из любопытства, что произойдет, если вы используете socket.TCP_NODELAY ? Вероятно, это не имеет значения, но я понятия не имею. recvmsg_into это также то, что я бы попробовал (что позволяет избежать буфера Python). Однако я чувствую, что это связано больше с ОС, чем с Python. Пожалуйста, добавьте название ОС и версию.

5. Использование виртуальной машины Windows. 2-ядерный процессор Intel Xeon Gold 5120, 2,20 ГГц, 6 ГБ оперативной памяти, с ОС Windows 10 Pro.

Ответ №1:

Задержка связана с временным разрешением monotonic_ns() , time.perf_counter_ns() решило эту проблему.

https://www.python.org/dev/peps/pep-0564/#id23

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

1. задержки в 16 мс напоминают ограничение в 60 кадров в секунду в Windows; существует библиотека python psychopy , в которой есть таймеры и часы обратного отсчета с различным временным разрешением; ознакомьтесь с ней, чтобы узнать, как реализовать тот, который не зависит от ограничений ОС