Форум: "Сети";
Текущий архив: 2009.04.05;
Скачать: [xml.tar.bz2];
ВнизПрием большого потока данных по UDP Найти похожие ветки
← →
MBo © (2008-01-31 07:26) [0]Задача следующая - некий спецдевайс передает по сети по протоколу UDP данные (видеопоток), порядка 11 мегабайт в секунду, пакет 770 байт - строка. Прием занимает очень значительную часть процессорного времени (применяется WSA-функции + RecvFrom, также пробовал использовать Indy и ICS), причем, если программа занимается еще чем-то, то пакеты, приходящие в этот момент, теряются. Например, если после приема кадра отрисовывать его, то несколько первых строк следующего кадра не принимаются.
Можно ли предпринять какие-то меры к улучшению ситуации?
C сетями ранее не работал, так что могут помочь любые идеи.
← →
ketmar © (2008-01-31 08:53) [1]собирать на отдельном сервере.
поднять приоритеты получалке.
настучать в тыкву авторам передавалки.
%-)
← →
Сергей М. © (2008-01-31 08:55) [2]
> если программа занимается еще чем-то
Сделай так чтобы она занималась только этим и ничем более
← →
MBo © (2008-01-31 09:11) [3]т.е., такое потребление ресурсов и потери пакетов - это нормальная ситуация?
← →
Anatoly Podgoretsky © (2008-01-31 09:13) [4]> MBo (31.01.2008 07:26:00) [0]
Для такого потока нужен уже 1 гигабит, 11 мегабайт в секунду можно передать только в тепличных условиях.
← →
ketmar © (2008-01-31 09:26) [5]>[3] MBo ©(31.01.08 09:11)
для UDP — да. оно ж лежит в буфере только пока новое не притащат. да и не факт, что старое дойдёт. потеряется по дороге — и всё.
← →
MBo © (2008-01-31 09:43) [6]>11 мегабайт в секунду можно передать только в тепличных условиях
судя по снифферу, в стомегабитной локалке до машины пакеты доходят все, да и если программа не занимается обсчетом/отрисовкой, то она их все принимает.
>оно ж лежит в буфере
насчет размера буфера я пока не разобрался. В ICS и в Indy можно выставить размер буфера, который, как я понимаю, отвечает за максимальный размер пакета. А есть ли еще какие-то возможности указать сетевой подсистеме винды, чтобы побольше непрочитанных еще пакетов накапливалось?
← →
ketmar © (2008-01-31 09:48) [7]>[6] MBo ©(31.01.08 09:43)
а максимальный размер пакета, афаир, всё равно 64к. и очереди в UDP нет. не успал поймать — кранты тому, что лежало.
← →
Сергей М. © (2008-01-31 09:51) [8]
> MBo © (31.01.08 09:43) [6]
см. SetSockOpt(..SO_RCVBUF..)
Но это не спасет, если выборка из буфера стабильно медленней, чем запись в буфер.
← →
Anatoly Podgoretsky © (2008-01-31 09:52) [9]> MBo (31.01.2008 09:43:06) [6]
судя по снифферу, в стомегабитной локалке до машины пакеты доходят все, да и если программа не занимается обсчетом/отрисовкой, то она их все принимает.
Этого не должно быть, что то неправильно, в программе конечно.
Но я бы все таки задумался 11 мегабайт это на пределе возможностей 100 мб сети. Не каждая машина и сетевая карта в состоянии обеспечить.
А для процессора это ничто, доли процента.
Но сам протокол UDP не обеспечивает гарантированой доставки. Размер пакета надо снижать до минимума и делать буферизации, часть буферизации делает система.
← →
Сергей М. © (2008-01-31 09:53) [10]
> MBo ©
Выноси транспортную логику в отдельный поток, повысь ему приоритет до разумных пределов.
← →
ketmar © (2008-01-31 09:58) [11]>[10] Сергей М. ©(31.01.08 09:53)
так нечестно, я это уже посоветовал! %-)
← →
MBo © (2008-01-31 10:11) [12]да, прием ведется в отдельном потоке, повышение приоритета частично помогает, но полностью проблему не снимает.
← →
ketmar © (2008-01-31 10:19) [13]>[12] MBo ©(31.01.08 10:11)
ну, ты учти, что поток не может быть особо приоритетней приложения. подними ещё приоритет самому приложению. другим потокам приоритет поспускай.
а лучше таки накапливай где-то на отдельном сервере и с него уже забирай. и на гигабитке, желательно.
← →
MBo © (2008-01-31 10:37) [14]> лучше таки накапливай где-то на отдельном сервере и с него уже забирай. и на гигабитке, желательно
Увы, не получится - в реальности будут полевые условия, железка - кабель - ноутбук.
← →
Сергей М. © (2008-01-31 10:54) [15]
> MBo © (31.01.08 10:37) [14]
Ты бы код своего транспортного алгоритма показал ..
← →
ketmar © (2008-01-31 11:23) [16]>[15] Сергей М. ©(31.01.08 10:54)
я подозреваю, что ничего там такого нет. тупо сетка успевает впритык.
однако ж глянуть не помешает в любом случае, да.
← →
MBo © (2008-01-31 13:52) [17]
инициализация в конструкторе потока
if WSAStartup($0202, WSAD) <> 0 then
Exception.Create("WSAStartup Error");
Ud := Socket(AF_INET, Sock_Dgram, 0);
if INVALID_SOCKET = Ud then
Exception.Create("Socket Create Error");
Addr.sin_family := PF_Inet;
Addr.sin_addr.S_addr := Inet_Addr("0.0.0.0");
Addr.sin_port := HtoNS(FPort);
FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
if Bind(UD, Addr, SizeOf(Addr)) = Socket_Error then
Exception.Create("Socket Bind Error");
поточная функция
Len := 770;
while not Terminated do begin
FromLen := SizeOf(TSockAddr);
WSResult := RecvFrom(UD, LineBuf, Len, 0, Addr, FromLen);
Wrd := Swap(PWord(@LineBuf[0])^);
LineNum := Wrd and $3FF;
CadrNum := (Wrd shr 12) and 1;
if LineNum = 0 then begin
Inc(FrameCount);
PostMessage(Form3.Handle, WM_USER, FrameCount and $F, CadrNum xor 1);
end;
Move(LineBuf[2], Buf[CadrNum, LineNum, 0], Wdt);
end;
Buf - 2 массива, один заполняется, предыдущий отрисовывается
в обработчике WM_USER отрисовка
SetDiBitsToDevice(Canvas.Handle, 0, 0, Wdt, Hgt, 0, 0, 0, Hgt,
@Buf[M.LParam], PBitmapInfo(@Info)^, DIB_RGB_COLORS);
← →
ketmar © (2008-01-31 14:11) [18]у-у-у. PostMessage… да ещё и SetDiBits… есть (ничем не обоснованое, правда) мнение, что:
эту фигню надо тихонько совать в буфер моска сразу по получении. раз.
наладить frame skiping, если не успевает отрисоваться, а в буферг гадит.
рисовать директиксом на оверлеях (тут, возможно, вылезут тормоза с преобразованием цветовых пространств, искать карты, оверлеи на которых потянут rgb).
да, это: присылает, как я понял, не твоя программа, так что вправить моск именно ей никак?
← →
MBo © (2008-01-31 14:32) [19]>PostMessage… да ещё и SetDiBits
Отрисовку, временно забыв об опасностях обращения к основному окну из доп. потока, можно вести и прямо из потока, ничего принципиально это не меняет.
SetDiBitsToDevice - оказался в данном случае наименее затратный способ из испытанных (альтернатива, например - формирование битмапа, происходит дольше)
насчет DirectX - еще не прорабатывал, побоялся затрат времени на преобразование цветов.
← →
Сергей М. © (2008-01-31 15:16) [20]
> один заполняется, предыдущий отрисовывается
А если отрисовка медленней заполнения ?
Подумай ...
← →
Anatoly Podgoretsky © (2008-01-31 15:41) [21]> MBo (31.01.2008 14:32:19) [19]
Для испытания временно отключи отрисовку.
← →
MBo © (2008-01-31 15:47) [22]>А если отрисовка медленней заполнения ?
тогда бы я ставил в очередь и отрисовывал бы только часть кадров.
В данном случае хватает двух буферов.
14400 пакетов в секунду, 0.07 мс один пакет
Отрисовка сначала у меня происходила более сложно, и занимала 3-4 мс, это по времени порядка 60 пакетов, около 40 КБ данных.
Визуально - если критерий отрисовки - приход нулевой строки, то в районе 20-50 строк было много выпавших.
Сейчас отрисовка быстрее, и артефактов на моей машине (Athlon 3500) практически нет, но на машинах вдвое медленнее - все-таки появляются.
Собственно, интересно - так и должна машина нагружаться при приеме из сети потока такой интенсивности, или руки нужно выпрямлять?
(С цифрового видеограббера без проблем принимаю, достаточно сложным образом обрабатываю и отрисовываю втрое-вчетверо больший поток)
← →
Anatoly Podgoretsky © (2008-01-31 16:28) [23]> MBo (31.01.2008 15:47:22) [22]
100 мегабит это ничто для процессора, проблема не в количестве, а в другом месте.
← →
MBo © (2008-01-31 18:31) [24]>а в другом месте.
Вот и хочется понять, что это за место ;)
← →
Anatoly Podgoretsky © (2008-01-31 20:05) [25]> MBo (31.01.2008 18:31:24) [24]
Э, ну ты даешь, программа то у тебя, задача сложная, явно не для форума, да и сеть у тебя работает за пределами возможностей. 11 мб не любая сеть обеспечит, а еще твоя обработка.
Так что придется тебе самому грызть.
← →
DVM © (2008-01-31 23:58) [26]
> MBo ©
А что за девайс такой? IP камера? Просто знакомая мне тематика.
← →
DVM © (2008-02-01 00:01) [27]
> Собственно, интересно - так и должна машина нагружаться
> при приеме из сети потока такой интенсивности, или руки
> нужно выпрямлять?
Нет, не должна. Вся нагрузка возникает, если в принимаемом потоке надо. что то искать, выцеплять, декодировать. Отрисовка это тоже мелочи.
← →
Slym © (2008-02-01 04:51) [28]
procedure x;
type
TLineRec=packed record
Info:word;
Data:array[0..192*4-1] of char;
end;
var
Bitmap:TBitmap;
Line:TLineRec;
FromLen,LineNum,CadrNum,Wrd:integer;
WSResult:integer;
UD:TSocket;
Addr:TSockAddr;
begin
Bitmap:=TBitmap.Create;
try
Bitmap.PixelFormat:=pf32bit;
Bitmap.Width:=192;
Bitmap.Height:=192;
while not Terminated do begin
FromLen := SizeOf(TSockAddr);
WSResult := RecvFrom(UD, Line, SizeOf(Line), 0, Addr, FromLen);
if WSResult<>SizeOf(Line) then continue;
Wrd := Swap(Line.Info);
LineNum:= Wrd and $3FF;
if (LineNum>-1) and (LineNum<Bitmap.Height) then
Move(Line.Data,Bitmap.ScanLine[LineNum]^,SizeOf(Line.Data));
if LineNum = Bitmap.Height-1 then
begin
Inc(FrameCount);
FCanvas.Lock;
try
FCanvas.Draw(0,0,Bitmap);
finally
FCanvas.Unlock;
end;
end;
end;
finally
Bitmap.Free;
end;
end;
← →
ага (2008-02-03 11:46) [29]2 MBo ©
WSARecv c кучей буферов сразу под весь кадр не пробовал? Те буфер один, но разбит на несколько, по числу строк.
Синхронизацию сообщениями я бы выкинул. Как и многопоточность, скоре всего, использовал бы асинхронный режим. В любом случае, синхронизация здесь - лишние потери, имхо. Два буфера, один рисуется, второй принимается. Буферы переключает "приемник", а по WM_PAINT выводится "рисуемый", независимо от того, было ли обновление.
Как гипотеза - может вывод через DirectX побыстрее будет. Не знаю, не спец.
← →
Slym © (2008-02-04 05:13) [30]если картинка боле менее статичная, то потеря небольшого колва, каждый раз разных, строк не должна вызывать видимых артефактов...
если конечно старый кадр не затирать "чернухой", а оставлять отображая новый "поверх" старого
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2009.04.05;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.007 c