-
41. Data: 2022-10-09 10:19:19
Temat: Re: lwIP - odbieranie danych przez TCP
Od: Atlantis <m...@w...pl>
On 9.10.2022 08:25, Marek wrote:
> A czy problemy z odtwarzaniem przez sieć nie wynikają ze słabej
> wydajności stosu tcpip iwip/mla przy "odległych" podłączeniach? Np. MLA
> szybko działa w lokalnej sieci (kilkaset kB/s) ale przez internet jest
> już znacznie wolniejszy (kilka kB/s) niż oczekiwany wpływ szybkości
> łącza.
Wszystkie wersje tego urządzenia na PIC32 i MLA zawsze wyciągały
wystarczającą szybkość, żeby być w stanie płynnie odtwarzać streamy z
odległych serwerów. Przez odległe mam na myśli nawet studenckie
rozgłośnie zza oceanu. ;)
Wczoraj udało mi się znaleźć źródło problemu. Okazało się ono być
banalne, ale leżało w trochę nieoczekiwanym miejscu. Mianowicie prędkość
SPI dedykowanego VS1003 była za mała. Nie wpadłem na to od razu, bo
prędkość była w pełni wystarczająca aby odtwarzać nawet MP3 o większych
bitrate'ach z lokalnych nośników.
Problemem było to, w jaki sposób stos lwIP na RAW API dostarcza dane. W
MLA można pobierać sobie dowolną ilość danych z bufora. W przypadku lwIP
taka operacja jest możliwa jedynie przy użyciu socket API, które wymaga
RTOS-a. Tutaj natomiast muszę albo:
- Przyjąć całą paczkę danych w callbacku odbiorczym, zwolnić pamięć i
zgłosić gotowość przyjęcia kolejnej porcji.
- Opóźnić tę operację i wykonać ją trochę później w pętli głównej.
Nie po prostu zapisać w buforze tyle danych, ile aktualnie mam wolnego
miejsca.
I tutaj problemem było tempo w jakim VS1003 by w stanie przyjmować dane.
Zbyt często po prostu dochodziło do sytuacji, kiedy po przyjściu nowej
paczki danych w buforze wciąż nie było dostatecznej ilości miejsca na
jej przyjęcie i trzeba było czekać aż VS przeniesie je do swojego
wewnętrznego bufora.
Po przyspieszeniu SPI wszystko zaczęło się odbywać dużo sprawniej.
Okazało się jednak, że przy buforze cyklicznym umieszczonym w pamięci
RAM (a więc ograniczonym do kilku kB) co jakiś czas zdarza się minimalne
przycięcie. Po przywróceniu 128kB bufora w pamięci SPI RAM wszystko
zaczęło działać zupełnie płynnie, chociaż na dobrą sprawę pewnie mógłbym
jeszcze dość znacznie zmniejszyć rozmiar tego bufora.
Obecnie będę musiał jeszcze trochę zoptymalizować program, zwłaszcza pod
kątem użycia pamięci. Może uda mi się jej trochę odzyskać po
przywróceniu bardziej oszczędnych ustawień lwIP.
Poza tym pingi nie wyglądają idealnie. Większość ma typową dla Ethernetu
wartość 0.1-0.5 ms, jednak podczas odtwarzania streamu mniej więcej co
piąty przychodzi z opóźnieniem od kilkudziesięciu do nawet ponad 100 ms.
W przypadku wersji na PIC32 też były opóźnienia, ale nie aż tak duże.
-
42. Data: 2022-10-09 14:45:18
Temat: Re: lwIP - odbieranie danych przez TCP
Od: Marek <f...@f...com>
On Sun, 9 Oct 2022 10:19:19 +0200, Atlantis <m...@w...pl>
wrote:
> Wszystkie wersje tego urządzenia na PIC32 i MLA zawsze wyciągały
> wystarczającą szybkość, żeby być w stanie płynnie odtwarzać streamy
> z
> odległych serwerów. Przez odległe mam na myśli nawet studenckie
> rozgłośnie zza oceanu. ;)
Ale na moment zostawmy strumieniowanie. Czy robiłeś testy porównawcze
transferu połączenia z internetu do "serwera" opartego na MLA w
porównaniu do połączenia z tym samym (i do tej samej usługi) w
lokalnym segmencie sieci? Interesuje mnie, czy to zjawisko jest tylko
u mnie czy powszechne w takich małych stosach tcpip.
--
Marek
-
43. Data: 2022-10-10 10:36:22
Temat: Re: lwIP - odbieranie danych przez TCP
Od: "J.F" <j...@p...onet.pl>
On Fri, 7 Oct 2022 20:40:36 +0200, Atlantis wrote:
> On 6.10.2022 17:18, J.F wrote:
>> Ciekawe co na to serwer - nie moze ci wyslac danych odpowiednio
>> szybko, buforowac tez nie moze w nieskonczonosc - powinien gdzies u
>> siebie przeskakiwac na aktualne dane.
>
> I wszystko wskazuje na to, że tak to właśnie działa. Przynajmniej
> odnoszę wrażenie, że dźwięki które słyszę z przerwami nie są kolejnymi
> fragmentami tego samego strumienia audio, ale raczej "okienkami" które
> aktualnie udaje się odebrać.
>
>> W przypadku radia moze byc inaczej, jesli nie ma u siebie bufora
>> danych. No ale nawet wtedy te ~20kB/s szybko uzbiera, a Ty nie
>> nadążasz odebrac.
>
> Tak. Pytanie tylko dlaczego nie nadążam tego odebrać. Można było
> teoretyzować o niskiej przepustowości pamięci SPI RAM (co i tak było
> wątpliwe, bo 18 MHz to naprawdę szybka transmisja) ale ta teoria padła w
> momencie, gdy identyczny problem udało się stwierdzić także w przypadku
> zastosowania bufora cyklicznego w RAM-ie.
>
>> Z grubsza mozliwe, ale patrz nizej.
>> A moze przerwania sa blokowane ?
>
> Jakie przerwania? W moim kodzie w ogóle nie używam przerwań związanych z
> Ethernetem. Używam gotowych sterowników dostarczanych przez producenta
> mikrokontrolera oraz gotowego stosu (lwIP). W rozsądnym projekcie
> użytkownik nie powinien w ogóle przejmować się przerwaniami - powinny
> one w tle ładować dane do jakiegoś FIFO. Zresztą nigdzie w dokumentacji
> nie znalazłem ani jednej wzmianki o przerwaniach.
> O ile informacje na jakie udało mi się trafić w Internecie są poprawne,
> to procedura odbioru jest następująca:
> - Stos wywołuje zarejestrowana wcześniej funkcję obsługi callbacku
> odbiorczego.
> - Do tej funkcji przekazywany jest wskaźnik na struct pbuf. Struktura
> zawiera dynamicznie alokowany bufor na payload. Może też zawierać
> wskaźniki do kolejnych struktur tego samego typu.
Zeby wywolac funkcje i przekazac bufor, to musi wiedziec, ze jakies
dane przyszly. Czyli przerwanie.
A jak funkcja dlugo obsluguje ... moze przerwania sa wyłączone, dopóki
nie skonczy.
> - Z jednej lub kilku struktur trzeba pobrać dane i gdzieś je zapisać.
> - Jeśli już skończyliśmy tę operację, wywołujemy pbuf_free() aby zwolnić
> pamięć oraz tcp_recved() aby zwiększyć rozmiar okna (poinformować
> serwer, że może przesłać więcej).
>
> U mnie może się zdarzyć sytuacja, że otrzymanych danych będzie więcej
> niż miejsca w buforze. Wtedy nie mogę ich odebrać od razu - muszę się z
> tym wstrzymać do czasu, aż dekoder MP3 wyjmie z bufora odpowiednią ilość
> danych. Wtedy odbiór tej konkretnej paczki jest opóźniony i odbywa się w
> pętli głównej.
I tu masz pare ryzyk:
a) przy niewielkim buforze opoznienie w wyslaniu potwierdzenia moze
skutkowac za duzym spowolnieniem transmisji,
b) bufory ci sie przepelniają, bo parametr TCP_window jest za duzy,
i serwer na poczatku przysyla ci za duzo danych,
> W żadnym miejscu nie mam do czynienia z przerwaniami.
Dekoder karmiony w petli glownej?
A moze tam sie zdarzaja duze opoznienia na inne akcje ?
>> Troche wątpie. Przy zgubieniu pakietu timeout sie wlacza, i to mogą
>> byc grube sekundy. Chyba bys nie uzyskal 5-11 kB/s.
>
> Kiedy transmisja zaczyna mulić to nie jest 5-11 kB/s, a 0-2kB/s.
A to juz moze byc, szczegolnie jesli widzisz, ze dociera kilka
pakietow, a potem dluga przerwa ..
>> Raczej bym sie spodziewal problemu w jakims opoznieniu w wyslaniu
>> potwierdzenia. Ale zeby az tak to SPI zwalniało? 18MHz wydaje sie
>> sporo ... a ogladales oscyloskopem? Albo czy mierzyles
>> przepustowosc/czas zapisu pakietu?
>
> Nie, bo wydawało mi się to nie mieć sensu. Udało mi się ustalić, że wina
> nie leży po stronie pamięci SPI. Przemawiają za tym dwa argumenty:
> - Pamięć SPI doskonale sprawdza się przy buforowaniu streama z karty SD.
> - Ten sam problem występuje, jeśli dane przychodzące przez TCP próbuję
> zapisywać do bufora cyklicznego ulokowanego w zwykłym RAM-ie.
To drugie w zasadzie wyjasnia, ale oscyloskop i tak moze pomoc.
Tu nawet nie oscyloskop, ale analizator logiczny za kilkadziesiąt zl.
>> A w ogole ... masz tam jakies zabezpieczenie kolejnosci w tej
>> bibliotece? Bo powiedzmy przychodzą pakiety nr 1, 2, 3, a nr 4 nie
>> przychodzi. Ale przychodzi nr 5, 6, 7 ... i co wtedy - nie dostaniesz
>> callbacka z nr 5, a bufory 5, 6, 7 zostaną skasowane ?
>
> Wydaje mi się, że przecież chyba TCP ogarnia kwestię pakietów
> przychodzących w złej kolejności i użytkownik nie musi się przejmować tą
> kwestią podczas pisania aplikacji.
TCP tak, pytanie, czy masz pelne TCP ..
> Ten problem pojawia się dopiero w
> przypadku zastosowania UDP.
> Tak czy inaczej lwIP ma opcję związana właśnie z tą kwestią. Jeśli
> dobrze rozumiem to można wybrać jak ma się zachować stos. W przypadku
> zgubienia któregoś z pakietów w sekwencji można albo trzymać nadmiarowe
> do momentu otrzymania brakującego, albo poprosić jeszcze raz o wysłanie
> całej sekwencji licząc, że tym razem przyjdą wszystkie i po kolei.
> Próbowałem obydwu ustawień.
Tak ogolnie TCP dziala tak, ze jak znikl jeden pakiet, to trzeba go
retransmitowac. A po nim wysylane sa ponownie wszystkie nastepne.
Po otrzymaniu pakietu "niekolejnego", stos odbiorczy byc moze moze
chwile poczekac - moze akurat "kolejny" przyjdzie, a nastepny juz
czeka w buforze.
Przy czym raczej nie podejrzewam, zeby niekolejne byly twoim
problemem.
> Swoją drogą, czy ktoś może mi wyjaśnić w jaki sposób skonfigurować lwIP,
> żeby mieć dostatecznie duży bufor odbiorczy? W stosie od Microchipa po
> prostu ustawiało się wielkość bufora nadawczego i odbiorczego dla
> konkretnego gniazda. Tutaj cała masa opcji, które nic mi wprost nie mówią...
>
> https://github.com/marekw1986/InternetRadioSTM32/blo
b/main/code/LWIP/Target/lwipopts.h
Nie znam, nie poradze.
J.