Я хочу отправлять однонаправленные потоковые данные по каналу данных WebRTC и ищу лучшие параметры конфигурации (высокая полоса пропускания, низкая задержка/джиттер) и опыт других с ожидаемыми битрейтами в приложениях такого типа.
Моя тестовая программа отправляет фрагменты по 2 КБ с обратным вызовом события bufferedAmountLowThreshold, равным 2 КБ, и вызывает повторную отправку до тех пор, пока bufferedAmount не превысит 16 КБ. Используя это в Chrome, я получаю ~ 135 Мбит / с в локальной сети и ~ 20 Мбит / с из / в удаленное соединение, которое имеет соединение WAN со скоростью 100 Мбит / с на обоих концах.
Что является здесь ограничивающим фактором?
Как я могу увидеть, действительно ли данные передаются напрямую между одноранговыми узлами или используется сервер TURN?
Мое конечное приложение будет использовать библиотеку google-webrtc на Android — я использую JS только для прототипирования. Могу ли я установить параметры для ускорения битрейта в библиотеке, которые я не могу сделать в официальных JS API?
Есть много переменных, влияющих на пропускную способность, и она также сильно зависит от того, как вы ее измерили. Но я перечислю пару вещей, которые я настроил для увеличения пропускной способности каналов данных WebRTC.
Отказ от ответственности: я сделал эти настройки не для libwebrtc, а для моей собственной библиотеки каналов данных WebRTC под названием RAWRTC, которая, кстати, также компилируется для Android. Тем не менее, оба используют одну и ту же библиотеку SCTP внизу, оба используют некоторую библиотеку OpenSSL и сокеты UDP, поэтому все это должно быть применимо к libwebrtc.
Обратите внимание, что реализации канала данных WebRTC с использованием usrsctp обычно привязаны к ЦП при выполнении на одном компьютере, поэтому имейте это в виду при тестировании. С настройками RAWRTC по умолчанию я могу достичь ~ 520 Мбит / с на моем i7 5820k. По моим собственным тестам, и Chrom(e|ium), и Firefox смогли достичь ~350 Мбит/с с настройками по умолчанию.
Итак, приступим к настройкам...
Буфер отправки/получения UDP-сокетов по умолчанию в Linux по умолчанию довольно мал. Если вы можете, вы можете настроить его.
Большинство устройств Android имеют процессоры ARM без аппаратной поддержки AES. ChaCha20 обычно работает лучше в программном обеспечении, поэтому вы можете предпочесть его.
(Это то, что RAWRTC согласовывает по умолчанию, поэтому я не включил это в конечные результаты.)
Размер окна отправки/получения по умолчанию для usrsctp, стека SCTP, используемого libwebrtc, составляет 256 КиБ, который слишком мал для достижения высокой пропускной способности с умеренной задержкой. Теоретическая максимальная пропускная способность ограничена mbits = (window / (rtt_ms / 1000)) / 131072
. Таким образом, с окном по умолчанию window=262144
и довольно умеренным RTT rtt_ms=20
вы получите теоретический максимум 100 Мбит/с.
Практический максимум ниже этого... на самом деле намного ниже теоретического максимума (см. мои результаты теста). Это может быть ошибка в стеке usrsctp (см. sctplab/usrsctp#245).
Размер буфера был увеличен в Firefox (см. ошибка 1051685), но не в libwebrtc, используемом Chrom(e|ium).
Уровень оптимизации 3 имеет значение (да!).
Вероятно, вы хотите отправлять сообщения размером 256 КиБ.
Если вам не нужно поддерживать Chrome < ??? (извините, в настоящее время я не знаю, куда оно попало...), то максимальный размер сообщения составляет 64 КиБ (см. выпуск 7774).
Если вам также не требуется поддержка Firefox < 56, в этом случае максимальный размер сообщения составляет 16 КиБ (см. ошибка 979417).
Это также зависит от того, сколько вы отправляете до того, как приостановите отправку (т. е. высокая отметка уровня воды буфера), и когда вы продолжите отправку после опустошения буфера (т. е. отметка низкого уровня воды буфера). Мои тесты показали, что установка высокая отметка уровня воды на 1 МБ и установка отметка низкого уровня воды на 256 КиБ дают адекватную пропускную способность.
Это уменьшает количество вызовов API, а могу увеличивает пропускную способность.
Использование уровня оптимизации 3 с настройками по умолчанию на RAWRTC увеличило скорость до ~600 Мбит/с.
Исходя из этого, увеличение размеров буфера SCTP и UDP до 4 МБ увеличило скорость до ~ 700 Мбит/с при загрузке одного ядра ЦП на 100%.
Тем не менее, я считаю, что еще есть возможности для улучшений, но вряд ли они будут незначительными.
How can I see if the data is truly going peer to peer directly, or whether a TURN server is used?
Откройте about:webrtc
в Firefox или chrome://webrtc-internals
в Chrom(e|ium) и найдите выбранную пару кандидатов ICE. Или используйте Wireshark.
ORTC — это просто другой API более низкого уровня, и если вам не нужна поддержка WebRTC, я бы вместо этого использовал ORTC. Однако API канала данных абсолютно идентичен. Для процесса подключения взгляните на один из примеров инструментов в кодовой базе RAWRTC. По сути, вы обмениваетесь параметрами и вызываете Начало для каждого транспорта.
Технически, если одноранговый узел открывает несколько каналов данных для разных одноранговых узлов, не сможет ли он достичь более высокой пропускной способности? (при условии, что usrsctp
ограничение пропускной способности применимо к каналу данных за, а не ко всей системе).
Привет, Леннарт, спасибо за подробный ответ. Использование RAWRTC кажется нам еще лучшим выбором. Совместимость с браузерами для нас не обязательна - какие варианты для нас лучше. API и параметры канала? Я знаком только с WebRTC API, а ORTC, похоже, разделен на несколько инструментов. Что такое полный процесс подключения с использованием ORTC?