Mediastreamer2:n VoIP-moottorin tutkiminen. Osa 12

Artikkelin materiaali on otettu minun zen kanava.

Mediastreamer2:n VoIP-moottorin tutkiminen. Osa 12

Viimeisessä статьеLupasin harkita ticker-kuormituksen arviointia ja tapoja käsitellä liiallista laskentakuormaa mediastriimerissä. Mutta päätin, että olisi loogisempaa käsitellä tietojen liikkumiseen liittyvien veneiden suodattimien virheenkorjausta ja vasta sitten pohtia suorituskyvyn optimointia.

Käsityösuodattimien virheenkorjaus

Tutkittuamme edellisessä artikkelissa datan liikkumismekanismia mediastriimerissä, olisi loogista puhua siihen piilevistä vaaroista. Yksi "datavirtaus"-periaatteen piirteistä on, että muistin varaaminen kasasta tapahtuu tietovirran lähteillä sijaitsevissa suodattimissa ja virtauspolun päässä sijaitsevat suodattimet vapauttavat muistin jo palautumalla. kasaan. Lisäksi jossain välipisteissä voi tapahtua uuden tiedon syntymistä ja tuhoamista. Yleensä muistin vapauttamisen suorittaa jokin muu suodatin kuin se, joka loi tietolohkon.

Muistin läpinäkyvän valvonnan kannalta olisi järkevää, että suodatin vastaanottaessaan tulolohkon tuhoaisi sen välittömästi käsittelyn jälkeen vapauttaen muistia ja laittaisi ulostuloon vasta luotu lohko lähtötiedoilla. Tässä tapauksessa suodattimen muistivuoto oli helposti jäljitettävissä – jos analysaattori havaitsi vuodon suodattimessa, sitä seuraava suodatin ei tuhoa kunnolla saapuvia lohkoja ja siinä on virhe. Mutta korkean suorituskyvyn ylläpitämisen kannalta tämä lähestymistapa tietolohkojen kanssa työskentelemiseen ei ole tuottava - se johtaa suureen määrään operaatioita muistin varaamiseksi / vapauttamiseksi tietolohkoille ilman hyödyllistä pakottamista.

Tästä syystä mediasuorittimet, jotta ne eivät hidasta tietojenkäsittelyä, käyttävät viestejä kopioitaessa toimintoja, jotka luovat kevyitä kopioita (puhuimme niistä edellisessä artikkelissa). Nämä toiminnot luovat vain uuden kopion viestin otsikosta "liittämällä" siihen datalohkon kopioidusta "vanhasta" viestistä. Tämän seurauksena yhteen tietolohkoon liitetään kaksi otsikkoa ja datalohkon viitelaskuria kasvatetaan. Mutta se näyttää kahdelta viestiltä. Tällaisella "julkisella" datalohkolla voi olla useampia viestejä, esimerkiksi MS_TEE-suodatin muodostaa kymmenen tällaista valokopiota kerralla jakaen ne ulostuloilleen. Jos kaikki ketjun suodattimet toimivat oikein, liukuhihnan loppuun mennessä tämän viitemäärän pitäisi saavuttaa nolla ja muistin purkamisfunktiota kutsutaan: ms_free(). Jos kutsua ei tapahdu, tämä muistipala ei enää palaudu kasaan, ts. hän "vuotaa". Kevyiden kopioiden käytön kustannukset ovat menetys kyvystä helposti määrittää (kuten tavallisten kopioiden tapauksessa), missä kuvaajasuodattimessa muisti vuotaa.

Koska vastuu muistivuotojen löytämisestä "alkuperäisistä" suodattimista on mediasuojien kehittäjillä, sinun ei todennäköisesti tarvitse korjata niitä. Mutta käsityösuodattimesi avulla olet itse oman onnellisuutesi heinäsirkka, ja aika, jonka käytät koodin vuotojen etsimiseen, riippuu tarkkuudestasi. Jotta voimme lyhentää virheenkorjausaikaasi, meidän on tarkasteltava vuotojen lokalisointitekniikoita suodattimia suunnitellessa. Lisäksi voi käydä niin, että vuoto ilmenee vasta suodatinta käytettäessä todellisessa järjestelmässä, jossa "epäiltyjen" määrä voi olla valtava ja virheenkorjausaika on rajallinen.

Miten muistivuoto ilmenee?

On loogista olettaa, että ohjelman lähdössä ylin näyttää kasvavan prosenttiosuuden sovelluksesi käyttämästä muistista.

Ulkoinen ilmentymä muodostuu siitä, että jossain vaiheessa järjestelmä reagoi hitaasti hiiren liikkeeseen ja piirtää näytön hitaasti uudelleen. On myös mahdollista, että järjestelmäloki kasvaa ja kuluttaa tilaa kiintolevyltä. Tässä tapauksessa sovelluksesi alkaa käyttäytyä oudosti, ei vastaa komentoihin, ei voi avata tiedostoa jne.

Vuodon tosiasian tunnistamiseen käytämme muistianalysaattoria (jäljempänä analysaattori). Se voisi olla valgrind (hyvä artikkeli siitä) tai sisäänrakennettuna kääntäjään gcc MemorySanitizer tai jotain muuta. Jos analysaattori osoittaa, että vuoto tapahtuu jossakin kuvaajasuodattimesta, se tarkoittaa, että on aika käyttää jotakin alla kuvatuista menetelmistä.

Kolmen männyn menetelmä

Kuten edellä mainittiin, muistivuodon sattuessa analysaattori osoittaa suodattimeen, joka pyysi muistin varausta kasasta. Mutta se ei osoita suodattimeen, joka "unohti" palauttaa sen, mikä itse asiassa on syyllinen. Siten analysaattori voi vain vahvistaa pelkomme, mutta ei osoittaa niiden juurta.

Selvittääksesi "huonon" suodattimen sijainnin kaaviossa, voit pienentää kaavion vähimmäismäärään solmuja, joissa analysaattori vielä havaitsee vuodon, ja paikantaa ongelmallisen suodattimen jäljellä olevista kolmesta männystä.

Mutta voi käydä niin, että vähentämällä suodattimien määrää sarakkeessa häiritset normaalia vuorovaikutusta suodattimien ja järjestelmän muiden osien välillä eikä vuotoa enää näy. Tässä tapauksessa sinun on käytettävä täysikokoista kuvaajaa ja käytettävä alla kuvattua lähestymistapaa.

Liukuva eristemenetelmä

Esityksen yksinkertaistamiseksi käytämme kaaviota, joka koostuu yhdestä suodatinketjusta. Hän näkyy kuvassa.

Mediastreamer2:n VoIP-moottorin tutkiminen. Osa 12

Tavallinen graafi, jossa valmiiden mediastriimaussuodattimien ohella on käytössä neljä askartelusuodatinta F1…F4, neljä eri tyyppiä, jotka olet tehnyt kauan sitten ja joiden oikeellisuudesta ei ole epäilystäkään. Oletetaan kuitenkin, että useilla niistä on muistivuoto. Kun suoritamme analysaattorin valvontaohjelmaamme, opimme sen raportista, että tietty suodatin pyysi tietyn määrän muistia eikä palauttanut sitä kasaan N kertaa. On helppo arvata, että siellä on viittaus MS_VOID_SOURCE-tyypin sisäisiin suodatintoimintoihin. Hänen tehtävänsä on ottaa muisto kasasta. Muiden suodattimien pitäisi palauttaa se sinne. Nuo. löydämme vuodon.

Sen määrittämiseksi, missä liukuhihnan osassa tapahtui epäaktiivisuus, joka johti muistivuotoon, ehdotetaan lisäsuodattimen käyttöönottoa, joka yksinkertaisesti siirtää viestit tulosta lähtöön, mutta samalla luo ei-kevyt, normaali "raskas" kopio syöttöviestistä ja poistaa sitten kokonaan ulostuloon saapunut viesti. Kutsumme tällaista suodatinta eristeeksi. Uskomme, että koska suodatin on yksinkertainen, vuodot siinä on poissuljettu. Ja vielä yksi positiivinen ominaisuus - jos lisäämme sen mihin tahansa paikkaan kaaviossamme, tämä ei vaikuta piirin toimintaan millään tavalla. Kuvaamme eristesuodattimen ympyränä, jossa on kaksoisääriviiva.

Ota isolaattori käyttöön heti voidsourse-suodattimen jälkeen:
Mediastreamer2:n VoIP-moottorin tutkiminen. Osa 12

Suoritamme ohjelman uudelleen analysaattorilla ja näemme, että tällä kertaa analysaattori syyttää isolaattoria. Loppujen lopuksi hän luo nyt tietolohkoja, jotka sitten menetetään tuntemattoman huolimattoman suodattimen (tai suodattimien) toimesta. Seuraava askel on siirtää eristettä ketjua pitkin oikealle yhden suodattimen verran ja aloittaa analyysi uudelleen. Joten askel askeleelta siirtämällä isolaattoria oikealle, saadaan tilanne, jossa "vuotaneiden" muistilohkojen määrä analysaattorin seuraavassa raportissa vähenee. Tämä tarkoittaa, että tässä vaiheessa eriste päätyi ketjuun heti ongelmallisen suodattimen jälkeen. Jos oli vain yksi "huono" suodatin, vuoto katoaa kokonaan. Siten lokalisoimme ongelmallisen suodattimen (tai yhden useista). Kun suodatin on "korjattu", voimme jatkaa isolaattorin siirtämistä oikealle ketjua pitkin, kunnes muistivuodot on poistettu kokonaan.

Eristinsuodattimen käyttöönotto

Isolaattoritoteutus näyttää aivan tavalliselta suodattimelta. Otsikkotiedosto:

/* Файл 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

Itse suodatin:

/* Файл 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)

Menetelmä muistinhallintatoimintojen korvaamiseksi

Tarkempaa tutkimusta varten mediastriimeri tarjoaa mahdollisuuden korvata muistin käyttötoiminnot omalla, mikä päätyön lisäksi korjaa "Kuka, missä ja miksi". Kolme toimintoa korvataan. Tämä tehdään seuraavalla tavalla:

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ämä ominaisuus tulee apuun tapauksissa, joissa analysaattori hidastaa suodattimia niin paljon, että sen järjestelmän toiminta, johon piirimme on rakennettu, häiriintyy. Tällaisessa tilanteessa sinun on hylättävä analysaattori ja käytettävä muistitoimintojen korvaamista.

Olemme tarkastelleet toimintoalgoritmia yksinkertaiselle graafille, joka ei sisällä haaroja. Mutta tätä lähestymistapaa voidaan soveltaa muihin tapauksiin, tietysti monimutkaisin, mutta ajatus pysyy samana.

Seuraavassa artikkelissa tarkastellaan ticker-kuormituksen arviointia ja sitä, kuinka käsitellä liiallista laskentakuormaa mediasuorassa.

Lähde: will.com

Lisää kommentti