Skúmanie enginu Mediastreamer2 VoIP. Časť 12

Materiál článku je prevzatý z môjho zenový kanál.

Skúmanie enginu Mediastreamer2 VoIP. Časť 12

V poslednom článok, Sľúbil som, že zvážim otázku odhadu zaťaženia tickera a spôsobov, ako sa vysporiadať s nadmerným výpočtovým zaťažením v streameri médií. Ale rozhodol som sa, že by bolo logickejšie pokryť otázky ladenia remeselných filtrov súvisiacich s pohybom údajov a až potom zvážiť problémy s optimalizáciou výkonu.

Ladenie remeselných filtrov

Po tom, čo sme v predchádzajúcom článku preskúmali mechanizmus pohybu dát v mediálnom streameri, bolo by logické porozprávať o nebezpečenstvách, ktoré sa v ňom ukrývajú. Jednou z vlastností princípu „toku údajov“ je, že alokácia pamäte z haldy sa vyskytuje vo filtroch umiestnených v zdrojoch toku údajov a filtre umiestnené na konci toku údajov už uvoľňujú pamäť s návratom. do kopy. Okrem toho môže niekde v medziľahlých bodoch dôjsť k vytvoreniu nových údajov a ich zničeniu. Vo všeobecnosti uvoľnenie pamäte vykonáva iný filter ako ten, ktorý vytvoril dátový blok.

Z hľadiska transparentného sledovania pamäte by bolo rozumné, aby filter pri príjme vstupného bloku po spracovaní ihneď zlikvidoval, uvoľnil pamäť a na výstup dal novovytvorený blok s výstupnými dátami. V tomto prípade by sa únik pamäte vo filtri dal ľahko vysledovať — ak analyzátor zistil únik vo filtri, potom filter, ktorý ho nasleduje, správne nezničí prichádzajúce bloky a je v ňom chyba. Ale z hľadiska zachovania vysokého výkonu nie je tento prístup k práci s dátovými blokmi produktívny – vedie k veľkému množstvu operácií na pridelenie/uvoľnenie pamäte pre dátové bloky bez akéhokoľvek užitočného vyčerpania.

Z tohto dôvodu filtre media streamer, aby nespomalili spracovanie dát, využívajú funkcie, ktoré pri kopírovaní správ vytvárajú odľahčené kópie (hovorili sme o nich v minulom článku). Tieto funkcie vytvoria iba novú kópiu hlavičky správy tak, že k nej „priložia“ blok údajov zo skopírovanej „starej“ správy. Výsledkom je, že k jednému dátovému bloku sú pripojené dve hlavičky a referenčné počítadlo v dátovom bloku sa zvýši. Ale bude to vyzerať ako dve správy. Správ s takýmto „verejným“ dátovým blokom môže byť viac, napríklad filter MS_TEE vygeneruje desať takýchto svetelných kópií naraz a rozdelí ich medzi svoje výstupy. Ak všetky filtre v reťazci fungujú správne, na konci kanála by mal tento počet referencií dosiahnuť nulu a bude sa volať funkcia uvoľnenia pamäte: ms_free(). Ak k hovoru nedôjde, tak sa tento kúsok pamäte už nevráti na kopu, t.j. „vyteká“. Náklady na používanie ľahkých kópií sú stratou možnosti jednoducho určiť (ako by to bolo v prípade používania bežných kópií), v ktorom filtri grafu pamäť uniká.

Keďže zodpovednosť za nájdenie únikov pamäte v „natívnych“ filtroch leží na vývojároch streamera médií, s najväčšou pravdepodobnosťou ich nebudete musieť ladiť. Ale s vaším remeselným filtrom ste vy sami kobylkou svojho vlastného šťastia a čas, ktorý strávite hľadaním únikov vo vašom kóde, bude závisieť od vašej presnosti. Aby sme skrátili čas ladenia, musíme sa pri navrhovaní filtrov pozrieť na techniky lokalizácie úniku. Navyše sa môže stať, že netesnosť sa prejaví až pri aplikácii filtra v reálnom systéme, kde môže byť množstvo „podozrivých“ obrovské a čas na odladenie je obmedzený.

Ako sa prejavuje únik pamäte?

Je logické predpokladať, že vo výstupe programu top zobrazí rastúce percento pamäte obsadenej vašou aplikáciou.

Vonkajší prejav bude spočívať v tom, že v určitom bode bude systém pomaly reagovať na pohyb myši a pomaly prekresľovať obrazovku. Je tiež možné, že systémový denník narastie a zaberie miesto na pevnom disku. V takom prípade sa vaša aplikácia začne správať čudne, nereaguje na príkazy, nedokáže otvoriť súbor atď.

Na identifikáciu skutočnosti úniku použijeme analyzátor pamäte (ďalej len analyzátor). To môže byť valgrind (dobre článok o tom) alebo zabudované do kompilátora gcc MemorySanitizer alebo niečo iné. Ak analyzátor ukáže, že k úniku dochádza v jednom z grafových filtrov, znamená to, že je čas použiť jednu z nižšie opísaných metód.

Metóda troch borovíc

Ako je uvedené vyššie, v prípade úniku pamäte analyzátor ukáže na filter, ktorý si vyžiadal pridelenie pamäte z haldy. Ale neukáže na filter, ktorý ho „zabudol“ vrátiť, čo je v skutočnosti na vine. Analyzátor teda môže len potvrdiť naše obavy, ale neukázať na ich koreň.

Ak chcete zistiť umiestnenie „zlého“ filtra v grafe, môžete prejsť zmenšením grafu na minimálny počet uzlov, pri ktorých analyzátor stále deteguje netesnosť, a lokalizovať problematický filter vo zvyšných troch boroviciach.

Môže sa však stať, že znížením počtu filtrov v stĺpci narušíte normálny priebeh interakcie medzi filtrami a ostatnými prvkami vášho systému a netesnosť sa už nebude prejavovať. V tomto prípade budete musieť pracovať s grafom v plnej veľkosti a použiť prístup popísaný nižšie.

Metóda posuvného izolátora

Pre jednoduchosť prezentácie použijeme graf, ktorý pozostáva z jedného reťazca filtrov. Je zobrazená na obrázku.

Skúmanie enginu Mediastreamer2 VoIP. Časť 12

Obyčajný graf, v ktorom sú spolu s hotovými media streamer filtrami použité štyri remeselné filtre F1…F4, štyri rôzne typy, ktoré ste vyrobili už dávno a o ich správnosti nepochybujete. Predpokladajme však, že niekoľko z nich má únik pamäte. Pri spustení nášho programu dohľadu nad analyzátorom sa z jeho správy dozvieme, že určitý filter si vyžiadal určité množstvo pamäte a N-krát ho nevrátil na hromadu. Je ľahké uhádnuť, že tam bude odkaz na interné filtračné funkcie typu MS_VOID_SOURCE. Jeho úlohou je zobrať pamäť z kopy. Ostatné filtre by to tam mali vrátiť. Tie. nájdeme únik.

Aby sa určilo, v ktorej časti potrubia sa vyskytla nečinnosť, ktorá viedla k úniku pamäte, navrhuje sa zaviesť ďalší filter, ktorý jednoducho presúva správy zo vstupu na výstup, ale zároveň vytvára nesvetlú kópiu vstupu. správu do normálnej "ťažkej" kópie, potom úplne vymažete správu, ktorá prišla pri vchode. Takýto filter nazveme izolant. Veríme, že keďže je filter jednoduchý, je vylúčený únik v ňom. A ešte jedna pozitívna vlastnosť - ak ju pridáme na akékoľvek miesto v našom grafe, tak to nijako neovplyvní chod obvodu. Izolačný filter znázorníme ako kruh s dvojitým obrysom.

Povoľte izolátor hneď po filtri voidsourse:
Skúmanie enginu Mediastreamer2 VoIP. Časť 12

Znovu spustíme program s analyzátorom a vidíme, že tentoraz analyzátor zvalí vinu na izolátor. Koniec koncov, je to on, kto teraz vytvára bloky údajov, ktoré potom neznámy nedbalý filter (alebo filtre) stráca. Ďalším krokom je posunutie izolátora pozdĺž reťaze doprava, o jeden filter a opätovné spustenie analýzy. Takže krok za krokom, posúvaním izolátora doprava, dostaneme situáciu, keď sa počet "uniknutých" pamäťových blokov v ďalšej správe analyzátora zníži. To znamená, že v tomto kroku skončil izolant v reťazci hneď za problematickým filtrom. Ak bol iba jeden "zlý" filter, potom únik úplne zmizne. Preto sme lokalizovali problematický filter (alebo jeden z viacerých). Po „opravení“ filtra môžeme pokračovať v posúvaní izolátora doprava pozdĺž reťazca, kým sa úniky pamäte úplne neodstránia.

Implementácia izolačného filtra

Implementácia izolátora vyzerá rovnako ako bežný filter. Hlavičkový súbor:

/* Файл iso_filter.h  Описание изолирующего фильтра. */

#ifndef iso_filter_h
#define iso_filter_h

/* Задаем идентификатор фильтра. */
#include <mediastreamer2/msfilter.h>

#define MY_ISO_FILTER_ID 1024

extern MSFilterDesc iso_filter_desc;

#endif

Samotný filter:

/* Файл iso_filter.c  Описание изолирующего фильтра. */

#include "iso_filter.h"

    static void
iso_init (MSFilter * f)
{
}
    static void
iso_uninit (MSFilter * f)
{
}

    static void
iso_process (MSFilter * f)
{
    mblk_t *im;

    while ((im = ms_queue_get (f->inputs[0])) != NULL)
    {
        ms_queue_put (f->outputs[0], copymsg (im));
        freemsg (im);
    }
}

static MSFilterMethod iso_methods[] = {
    {0, NULL}
};

MSFilterDesc iso_filter_desc = {
    MY_ISO_FILTER_ID,
    "iso_filter",
    "A filter that reads from input and copy to its output.",
    MS_FILTER_OTHER,
    NULL,
    1,
    1,
    iso_init,
    NULL,
    iso_process,
    NULL,
    iso_uninit,
    iso_methods
};

MS_FILTER_DESC_EXPORT (iso_desc)

Spôsob nahradenia funkcií správy pamäte

Pre jemnejšie skúmanie poskytuje streamer médií možnosť nahradiť funkcie prístupu do pamäte vašimi vlastnými, ktoré okrem hlavnej práce budú zaznamenávať „Kto, kde a prečo“. Nahrádzajú sa tri funkcie. Toto sa vykonáva nasledujúcim spôsobom:

OrtpMemoryFunctions reserv;
OrtpMemoryFunctions my;

reserv.malloc_fun = ortp_malloc;
reserv.realloc_fun = ortp_realloc;
reserv.free_fun = ortp_free;

my.malloc_fun = &my_malloc;
my.realloc_fun = &my_realloc;
my.free_fun = &my_free;

ortp_set_memory_functions(&my);

Táto funkcia prichádza na pomoc v prípadoch, keď analyzátor spomalí filtre natoľko, že sa naruší činnosť systému, v ktorom je náš obvod zabudovaný. V takejto situácii musíte opustiť analyzátor a použiť náhradu pamäťových funkcií.

Zvažovali sme algoritmus akcií pre jednoduchý graf, ktorý neobsahuje vetvy. Ale tento prístup sa dá aplikovať aj na iné prípady, samozrejme s komplikáciami, ale myšlienka zostáva rovnaká.

V ďalšom článku sa pozrieme na problematiku odhadu zaťaženia tickera a na to, ako sa vysporiadať s nadmerným výpočtovým zaťažením v streameri médií.

Zdroj: hab.com

Pridať komentár