реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Вопрос по LwIP, Скорость отправки
Petr_
сообщение Mar 15 2016, 18:12
Сообщение #1





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Передаю большой файл.
Использую цепочку колбеков, как и задумано в lwIP.
Но заполняю буфер передачи не полностью(узнаю из tcp_sndbuf(pcb); ).
Далее вызываю tcp_write(pcb, Data_Bf, wMaxPut, 0); и завершаю функцию.
Скорость никакущая.
Смотрю что идет по сетке - FTP клиент не посылает ACK добрых 0,3 сек.
Крепко думаю - доходит, что размер окна равен 2, а пакет уходит 1.
Рою сеть.
Нахожу вариант:
Код:
Код
    pcb->flags |= TF_NODELAY;                                   //отключаем  Nagle
    tcp_write(pcb, Data_Bf, wMaxPut >> 2, 1);                   //первый пакет
    tcp_output(pcb);                                            //передать что влезло
    //второй пакет
    tcp_write(pcb, &Data_Bf[wMaxPut >> 2], wMaxPut-(wMaxPut >> 2), 1);
    tcp_output(pcb);                                            //передать что влезло (опционально)

ACK сразу вываливаются на каждую пару пакетов и скорость вырастает в сотни раз. Здорово...
Только решение кривое.
Можно конечно набивать буфер под завязку
(как криво и не полностью сделано в WEB сервере ST).
Но это крайне неудобно.
Бить данные всегда на 2 куска - тоже левизна.

Кто то знает нормальное решение?
Go to the top of the page
 
+Quote Post
romas2010
сообщение Mar 15 2016, 19:50
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515



Цитата(Petr_ @ Mar 15 2016, 21:12) *
Передаю большой файл.
Использую цепочку колбеков, как и задумано в lwIP.
Но заполняю буфер передачи не полностью(узнаю из tcp_sndbuf(pcb); ).
Далее вызываю tcp_write(pcb, Data_Bf, wMaxPut, 0); и завершаю функцию.
Скорость никакущая.
.....
Кто то знает нормальное решение?


Ну насколько я понял из написанного,то вы сами и предложили нормальное решение,отключив алгоритм Нейгла(был такой перец,который предложил специально задерживать данные для увеличения пропускной способности сети.При этом подразумевается,что данные небольшого размера не передаются сразу в сеть,а накапливаются в буфере,и передаются только тогда,когда буфер полон)
Go to the top of the page
 
+Quote Post
Petr_
сообщение Mar 15 2016, 20:11
Сообщение #3





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Цитата(romas2010 @ Mar 15 2016, 19:50) *
Ну насколько я понял из написанного,то вы сами и предложили нормальное решение,отключив алгоритм Нейгла(был такой перец,который предложил специально задерживать данные для увеличения пропускной способности сети.При этом подразумевается,что данные небольшого размера не передаются сразу в сеть,а накапливаются в буфере,и передаются только тогда,когда буфер полон)


Не совсем так. Нейгл конечно умный перец, но...
Дело не в скорости работы самого стека или прохождении пакетов по сети.

Установили соединение - вызвался SENT, готовим данные.
Если забить буфер полностью (в настройках стека это (1500-40)*2 байт)
то LwIP пошлет 2 пакета в окне равном 2 пакета.
И любая реализация TCP (пробовал в форточках и Android)
сгенерирует ACK в конце ОКНА (т.е. после второго пакета сразу)
Он будет обработан LwIP и вызовется моя SENT для подготовки новых данных.
Но если забить буфер скажем на 2000 байт или на 500 байт,
то уйдет ОДИН пакет(а окно по прежнему - 2 пакета). И на приемной стороне ACK
будет сформирован только по истечении таймаута 0.2-0.3сек.
Скажем я делаю modbus - у меня паузы будут после каждого пакета.
И забивать буфер полностью мне просто нечем.
Тупо потому, что lwIP не умеет настраивать размер окна(есть в доке).
А если применить финт с биением данных на 2 пакета принудительно (для первого отключаем ожидание ACK, второй нормальный)
то получаем ACK немедленно и скорость обмена доходит до
10-25 тыс. туда/обратно в секунду.

Просто решение корявое, хотя и рабочее. Потому спрашиваю.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 15 2016, 20:32
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Petr_ @ Mar 15 2016, 23:11) *
для первого отключаем ожидание ACK, второй нормальный

В вашем примере Nagle отключается не только для первого пакета, а вообще для данного соединения.
Go to the top of the page
 
+Quote Post
Petr_
сообщение Mar 15 2016, 20:54
Сообщение #5





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Цитата(aaarrr @ Mar 15 2016, 20:32) *
В вашем примере Nagle отключается не только для первого пакета, а вообще для данного соединения.


Это не так в реале!
ACK ожидается для 2-го пакета. Это вариант из Сети.
Я посмотрел исходники. Это имнно так - флаг убирается для новых пакетов (согласно дефолтным установкам)
Есть еще вариант - допилить lwIP на предмет работы с окнами.
Но тогда станет невозможным легкий апгрейд, если он когда то выйдет...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 15 2016, 21:09
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Petr_ @ Mar 15 2016, 23:54) *
Я посмотрел исходники. Это имнно так - флаг убирается для новых пакетов (согласно дефолтным установкам)

Где именно он убирается?
Go to the top of the page
 
+Quote Post
Petr_
сообщение Mar 16 2016, 07:57
Сообщение #7





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Цитата(aaarrr @ Mar 15 2016, 21:09) *
Где именно он убирается?


Возможно Вы и правы. Я не нашел снова этого места.
Но наблюдения за сетью не оставляют вариантов!
Стек действительно ждет ACK после второго пакета в моем примере и
только после этого вызывает снова sent.

Если написать так:
Код
tcp_write(pcb, DirLLine, WrPntr, 0); //"нормальный" вариант

Скорость на малых пакетах около 300 Б/сек и ожидание ACK
на каждом пакете от Форточек по 0.3 сек.

Если написать так:
Код
pcb->flags |= TF_NODELAY;
tcp_write(pcb, DirLLine, WrPntr, 0);

Скорость на малых пакетах около 600 Б/сек и ожидание ACK
на каждом втором пакете от Форточек по 0.3 сек.

Если же написать так:
Код
pcb->flags |= TF_NODELAY;
tcp_write(pcb, DirLLine1, WrPntr1, 0);
tcp_output(pcb);
tcp_write(pcb, DirLLine2, WrPntr2, 0);
То имеем ACK на каждую пару пакетов мгновенно и вызывается
sent строго после получения ACK на вручную сформированное "окно".
Скорость 500-700 кБ/сек (в тысячу раз выше!)
на тех же самых малых пакетах.

Так что проблема видна четко и явно.
Решение как то мне не нравится. Хотя видимо хорошо, что есть и такое.
Обновление стека не было с 12-го года...

Сообщение отредактировал Petr_ - Mar 16 2016, 07:59
Go to the top of the page
 
+Quote Post
alag57
сообщение Mar 16 2016, 14:14
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 130
Регистрация: 26-06-06
Из: Березовский
Пользователь №: 18 355



Цитата(Petr_ @ Mar 16 2016, 12:57) *
Обновление стека не было с 12-го года...

git clone git://git.savannah.nongnu.org/lwip.git

Из changelog:
Цитата
HISTORY
(git master)
* [Enter new changes just after this line - do not remove this line]
++ New features:
2016-02-22: Ivan Delamer:
* Initial 6LoWPAN support
2015-12-26: Martin Hentschel and Dirk Ziegelmeier
* Rewrite SNMP agent
2015-11-12: Dirk Ziegelmeier
* Decouple SNMP stack from lwIP core and move stack to apps/ directory.
Breaking change: Users have to call snmp_init() now!

ну и т.д.
Go to the top of the page
 
+Quote Post
AleksBak
сообщение Mar 16 2016, 18:01
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364



Цитата(Petr_ @ Mar 16 2016, 11:57) *
...
Так что проблема видна четко и явно.
Решение как то мне не нравится. Хотя видимо хорошо, что есть и такое.
Обновление стека не было с 12-го года...

А здесь есть как отключать этот алгоритм Нейгла - вызовом функций:
Код
tcp_nagle_enable ( struct tcp_pcb * aPcb ); // enable the nagle algorithm

tcp_nagle_disable ( struct tcp_pcb * aPcb ); // disable the nagle algorithm

tcp_nagle_disabled ( struct tcp_pcb * aPcb ); // return true if the algorithm is not enabled

посмотрите там. Вроде там тоже самое, что Вы и делали и делается. Похоже на самом деле, что-то продолжается в этом lwip исправляться и пр. Я склонировал себе и надо бы сравнить как-нибудь. Похоже, что реально бардак, иначе не скажешь, с доками и сайтами у этого lwip. Есть wiki и вроде официальная, а там последняя версия 1.3.0 (?) Ссылка на один сайт (похоже ихний шведский какой-то) вообще уже не работает. sm.gif) Бесплатный сыр он такой. Еще нашел пару ссылок про упоминание lwip + Nagle (можете тоже сами найти если нужно, но там ничего такого).
Go to the top of the page
 
+Quote Post
scifi
сообщение Mar 16 2016, 18:12
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(AleksBak @ Mar 16 2016, 21:01) *
Похоже, что реально бардак, иначе не скажешь, с доками и сайтами у этого lwip. Есть wiki и вроде официальная, а там последняя версия 1.3.0 (?) Ссылка на один сайт (похоже ихний шведский какой-то) вообще уже не работает. sm.gif) Бесплатный сыр он такой.

Там с самого начала так. Ну да, бесплатный сыр. Хороший код, но там реально нужно самому врубиться. Наскоком не получится.
Go to the top of the page
 
+Quote Post
Petr_
сообщение Mar 17 2016, 06:56
Сообщение #11





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Цитата(alag57 @ Mar 16 2016, 14:14) *
git clone git://git.savannah.nongnu.org/lwip.git


Да, спасибо за ссылку. Я это видел.
Насколько я читал - эта фишка есть и в этом моде.
У меня сейчас версия 1.3.1
Но однозначно потом попробую.
Go to the top of the page
 
+Quote Post
AleksBak
сообщение Mar 17 2016, 07:13
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364



Вот, вчера это пропустил - еще там есть по этой теме: Maximizing throughput. Для обоих видов протокола TCP и UDP приводят рекомендации.

Цитата(Petr_ @ Mar 17 2016, 10:56) *
...
У меня сейчас версия 1.3.1
...

А в этой версии есть эти функции: tcp_nagle_enable/tcp_nagle_disable ? Если взять сгенерированное от Куба, то там 1.4.1 (и функции эти есть и еще кое-какие дефайны по этой теме), но правда полученный код уже будет привязан к HAL от Куба. Хотя при желании его (этот HAL) не трудно переписать/убрать на свой.
Go to the top of the page
 
+Quote Post
Petr_
сообщение Mar 17 2016, 11:04
Сообщение #13





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Цитата(AleksBak @ Mar 17 2016, 07:13) *
Вот, вчера это пропустил - еще там есть по этой теме: Maximizing throughput. Для обоих видов протокола TCP и UDP приводят рекомендации.


А в этой версии есть эти функции: tcp_nagle_enable/tcp_nagle_disable ? Если взять сгенерированное от Куба, то там 1.4.1 (и функции эти есть и еще кое-какие дефайны по этой теме), но правда полученный код уже будет привязан к HAL от Куба. Хотя при желании его (этот HAL) не трудно переписать/убрать на свой.


Спасибо за ссылку!!!
Там оказался прямой ответ/совет:
"Try to prevent sending small chunks of data waiting for an ACK: delayed ACK on the remote host might destroy performance (often, only every 2nd packet is ACKed)"
Также совет чуть выше:
"If you write small chunks turn off the nagle algorithm (see wikipedia for more info!) to let the stack send data right away instead of waiting for more data to form bigger packets (see tcp_nagle_disable())."

Иными словами найденный мной вариант и есть лучшее решение - нейгл отключается и шлется 2 "неполных" пакета немедленно. И именно пара пакетов подтверждается ACK.

В WEB сервере от ST эта проблема замаскирована и не вылезает:D
Там если файл больше пары пакетов (т.е. целого буфера) - буфер заполняется полностью и LwIP шлет 2 пакета добровольно.
А если остаток файла маленький - он шлется и соединение тут же закрывается. Что естественным образом снимает вопрос ожидания ACK на одиночный пакет.

Кстати у меня исходники не от Куба!
Оригинальный пример от ST и заменен HAL путем замены 2-х файлов.
Переделку делал один мой приятель из Штатов.

Версии LwIP пока пробовать не буду, пока не допилю проект.
И опыта поднаберусь и железо получше выучу.
Go to the top of the page
 
+Quote Post
AleksBak
сообщение Mar 17 2016, 11:33
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364



Цитата(Petr_ @ Mar 17 2016, 15:04) *
Спасибо за ссылку!!!
...

Очень рад этому. Реально. beer.gif Но еще вопрос у меня если можно - см. ниже. (Вообще взаимное обсуждение на форуме завсегда полезно я как твердо понял всем - столько мелких моментов всплывает.).
Цитата(Petr_ @ Mar 17 2016, 15:04) *
...
В WEB сервере от ST эта проблема замаскирована и не вылезает:D
Там если файл больше пары пакетов (т.е. целого буфера) - буфер заполняется полностью и LwIP шлет 2 пакета добровольно.
А если остаток файла маленький - он шлется и соединение тут же закрывается. Что естественным образом снимает вопрос ожидания ACK на одиночный пакет.
...

Вы какие исходники WEB сервера от ST смотрели? Даже скажем так - я как понял у ST лучше смотреть там где самое "современное" и иными словами там где самая последняя на данный момент линейка процессоров - M7. Т.е. например от платы DISCOVERY-746 (или EVAL-756). Между прочим там используется ОС т.е. судя по-всему Вы их не смотрели. А вообще Вы хотя и начали со "сложного" пути - без Куба (на самом деле это как обычно и по "старинке"), но все-таки более правильный путь это иногда т.к. вот сейчас например я думаю как бы избавиться полностью от этой cmsis_os.h например (это обертки над "чистыми" функциями FreeRTOS и хоть есть в них некоторые полезности, но лишние они) и еще некоторые вещи. А все потому что стал кушать огромный бесплатный сыр от Куба, объелся/подавился им и самое плохое, что приобрел "наркозависимость" от него (не избавиться от него вот так вот просто). sm.gif
Go to the top of the page
 
+Quote Post
Petr_
сообщение Mar 17 2016, 11:55
Сообщение #15





Группа: Участник
Сообщений: 14
Регистрация: 15-03-16
Пользователь №: 90 876



Цитата(AleksBak @ Mar 17 2016, 11:33) *
Вы какие исходники WEB сервера от ST смотрели? Даже скажем так - я как понял у ST лучше смотреть там где самое "современное" и иными словами там где самая последняя на данный момент линейка процессоров - M7. Т.е. например от платы DISCOVERY-746 (или EVAL-756). Между прочим там используется ОС т.е. судя по-всему Вы их не смотрели. А вообще Вы хотя и начали со "сложного" пути - без Куба (на самом деле это как обычно и по "старинке"), но все-таки более правильный путь это иногда т.к. вот сейчас например я думаю как бы избавиться полностью от этой cmsis_os.h например (это обертки над "чистыми" функциями FreeRTOS и хоть есть в них некоторые полезности, но лишние они) и еще некоторые вещи. А все потому что стал кушать огромный бесплатный сыр от Куба, объелся/подавился им и самое плохое, что приобрел "наркозависимость" от него (не избавиться от него вот так вот просто). sm.gif


Я взял исходники от их отладочной платы STM3210C-EVAL
Вот отсюда:
http://www2.st.com/content/st_com/en/produ...3210c-eval.html
Далее заменил 2 файла (HAL для Ethernet микросхемы)
поскольку плата у меня Olimex!!
Там все по другому подключено и нет такого красивого ЖКИ :D
WEB сервер и стек сразу заработали.
Никакой "оси" там нет, чему я очень рад. Поскольку не считаю полезным.
Софт от 2009 года и LwIP там 1.3.1


Далее я выпилил поддержку ЖКИ и привел в порядок использование ног.
Ну и теперь пилю сетевую часть проекта.

Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 4th July 2025 - 16:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.01512 секунд с 7
ELECTRONIX ©2004-2016