Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 12

Հոդվածի նյութը վերցված է իմ զեն ալիք.

Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 12

Անցյալում Հոդված, ես խոստացել եմ դիտարկել տիկերի ծանրաբեռնվածության գնահատման հարցը և մեդիա հոսքի ավելորդ հաշվողական բեռի դեմ պայքարելու ուղիները։ Բայց ես որոշեցի, որ ավելի տրամաբանական կլինի լուսաբանել տվյալների շարժման հետ կապված արհեստագործական ֆիլտրերի վրիպազերծման խնդիրները և միայն դրանից հետո դիտարկել կատարողականի օպտիմալացման խնդիրները:

Արհեստների ֆիլտրերի վրիպազերծում

Այն բանից հետո, երբ նախորդ հոդվածում դիտարկեցինք մեդիա հոսքի միջոցով տվյալների տեղափոխման մեխանիզմը, տրամաբանական կլիներ խոսել դրա մեջ թաքնված վտանգների մասին։ «Տվյալների հոսքի» սկզբունքի առանձնահատկություններից մեկն այն է, որ հիշողությունը տեղաբաշխվում է կույտից ֆիլտրերում, որոնք գտնվում են տվյալների հոսքի աղբյուրում, և հիշողությունը ազատվում և վերադառնում է կույտ հոսքի վերջում գտնվող ֆիլտրերի միջոցով: ուղին. Բացի այդ, նոր տվյալների ստեղծումը և դրանց ոչնչացումը կարող են տեղի ունենալ ինչ-որ տեղ միջև: Ընդհանուր առմամբ, հիշողության թողարկումն իրականացվում է այլ զտիչով, քան այն, որը ստեղծել է տվյալների բլոկը:

Թափանցիկ հիշողության մոնիտորինգի տեսանկյունից խելամիտ կլինի, որ ֆիլտրը մուտքային բլոկ ստանալիս անմիջապես ոչնչացնի այն մշակելուց հետո, ազատելով հիշողությունը և թողարկի նորաստեղծ բլոկ՝ ելքային տվյալներով։ Այս դեպքում ֆիլտրում հիշողության արտահոսքը հեշտությամբ կհետևվի. եթե անալիզատորը հայտնաբերի ֆիլտրում արտահոսք, ապա հաջորդ ֆիլտրը պատշաճ կերպով չի ոչնչացնում մուտքային բլոկները և դրա մեջ սխալ կա: Բայց բարձր կատարողականությունը պահպանելու տեսանկյունից տվյալների բլոկների հետ աշխատելու այս մոտեցումը արդյունավետ չէ. այն հանգեցնում է մեծ թվով գործողությունների՝ տվյալների բլոկների համար հիշողություն հատկացնելու/ազատելու համար՝ առանց որևէ օգտակար արդյունքի:

Այդ իսկ պատճառով, մեդիա հոսքերի ֆիլտրերը, որպեսզի չդանդաղեցնեն տվյալների մշակումը, օգտագործում են գործառույթներ, որոնք հեշտ պատճեններ են ստեղծում հաղորդագրությունները պատճենելիս (դրանց մասին խոսեցինք նախորդ հոդվածում): Այս գործառույթները միայն ստեղծում են հաղորդագրության վերնագրի նոր օրինակ՝ դրան «կցելով» պատճենվող «հին» հաղորդագրության տվյալների բլոկն: Արդյունքում, երկու վերնագրեր կցվում են մեկ տվյալների բլոկին, և տվյալների բլոկի հղման հաշվիչը ավելանում է: Բայց դա նման կլինի երկու հաղորդագրությունների: Նման «սոցիալականացված» տվյալների բլոկով կարող են լինել ավելի շատ հաղորդագրություններ, օրինակ՝ MS_TEE ֆիլտրը ստեղծում է միանգամից տասնյակ նման լուսային պատճեններ՝ դրանք բաշխելով իր ելքերի միջև: Եթե ​​շղթայի բոլոր զտիչները ճիշտ են գործում, ապա խողովակաշարի վերջում այս հղման հաշվիչը պետք է հասնի զրոյի, և հիշողության թողարկման գործառույթը կկոչվի. ms_free (). Եթե ​​զանգը տեղի չի ունենում, ապա հիշողության այս կտորն այլևս չի վերադարձվի կույտ, այսինքն. այն «կթողնի». Թեթև պատճենների օգտագործման գինը հեշտորեն որոշելու ունակության կորուստն է (ինչպես սովորական պատճենների դեպքում), թե որ գրաֆիկի ֆիլտրն է արտահոսում հիշողությունը:

Քանի որ մեդիա հոսքի մշակողները պատասխանատու են բնիկ ֆիլտրերում հիշողության արտահոսք գտնելու համար, դուք, ամենայն հավանականությամբ, ստիպված չեք լինի դրանք վրիպազերծել: Բայց ձեր արհեստագործական ֆիլտրով դուք ձեր երջանկության մորեխն եք, և ձեր կոդում արտահոսք գտնելու համար ծախսած ժամանակը կախված կլինի ձեր ճշգրտությունից: Վրիպազերծման ժամանակը նվազեցնելու համար մենք պետք է դիտարկենք արտահոսքի հայտնաբերման տեխնիկան զտիչներ մշակելիս: Բացի այդ, կարող է պատահել, որ արտահոսքը դրսևորվի միայն այն ժամանակ, երբ ֆիլտրը կիրառվի իրական համակարգում, որտեղ «կասկածյալների» թիվը կարող է հսկայական լինել, իսկ վրիպազերծման ժամանակը ՝ սահմանափակ:

Ինչպե՞ս է դրսևորվում հիշողության արտահոսքը:

Տրամաբանական է ենթադրել, որ ծրագրի ելքում վերեւ ցույց կտա ձեր հավելվածի զբաղեցրած հիշողության աճող տոկոսը:

Արտաքին դրսևորումը կլինի այն, որ ինչ-որ պահի համակարգը կսկսի դանդաղ արձագանքել մկնիկի շարժմանը և կամաց-կամաց վերագծել էկրանը: Հնարավոր է նաև, որ համակարգի գրանցամատյանը մեծանա՝ տարածք խլելով ձեր կոշտ սկավառակի վրա: Այս դեպքում ձեր հավելվածը կսկսի տարօրինակ վարվել, չպատասխանել հրամաններին, չի կարող բացել ֆայլ և այլն:

Արտահոսքի առաջացումը հայտնաբերելու համար մենք կօգտագործենք հիշողության անալիզատոր (այսուհետ՝ անալիզատոր): Դա կարող է լինել Վալգրինդ (լավ հոդված դրա մասին) կամ ներկառուցված կոմպիլյատորում gcc Հիշողության ախտահանիչ կամ որևէ այլ բան: Եթե ​​անալիզատորը ցույց է տալիս, որ գրաֆիկական ֆիլտրերից մեկում արտահոսք է տեղի ունենում, ապա դա նշանակում է, որ ժամանակն է կիրառել ստորև նկարագրված մեթոդներից մեկը:

Երեք սոճիների մեթոդ

Ինչպես նշվեց վերևում, եթե առկա է հիշողության արտահոսք, անալիզատորը ցույց կտա ֆիլտրը, որը պահանջել է հիշողություն հատկացնել կույտից: Բայց դա չի մատնանշի այն ֆիլտրը, որը «մոռացել է» վերադարձնել այն, որն իրականում մեղավոր է։ Այսպիսով, անալիզատորը կարող է միայն հաստատել մեր վախերը, բայց ոչ նշել դրանց արմատը:

Գրաֆիկում «վատ» ֆիլտրի գտնվելու վայրը պարզելու համար կարող եք գնալ՝ գրաֆիկը նվազեցնելով մինչև հանգույցների նվազագույն թիվը, որոնցում անալիզատորը դեռ հայտնաբերում է արտահոսք և տեղայնացնել խնդրահարույց ֆիլտրը մնացած երեք սոճիներում:

Բայց կարող է պատահել, որ գրաֆիկում ֆիլտրերի քանակը նվազեցնելով, դուք կխախտեք ֆիլտրերի և ձեր համակարգի այլ տարրերի միջև փոխազդեցության բնականոն ընթացքը, և արտահոսքն այլևս չհայտնվի: Այս դեպքում դուք ստիպված կլինեք աշխատել ամբողջական չափի գրաֆիկի հետ և օգտագործել ստորև նշված մոտեցումը:

Լոգարիթմական մեկուսիչ մեթոդ

Ներկայացման պարզության համար մենք կօգտագործենք գրաֆիկ, որը բաղկացած է ֆիլտրերի մեկ շղթայից: Նա պատկերված է նկարում։

Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 12

Սովորական գրաֆիկ, որտեղ պատրաստի մեդիա հոսքի ֆիլտրերի հետ մեկտեղ օգտագործվում են չորս տարբեր տեսակի F1...F4 արհեստագործական ֆիլտրեր, որոնք դուք վաղուց պատրաստել եք և կասկած չունեք դրանց ճիշտության մեջ։ Այնուամենայնիվ, ենթադրենք, որ դրանցից մի քանիսը հիշողության արտահոսք ունեն։ Գործարկելով անալիզատորին վերահսկելու մեր ծրագիրը՝ մենք նրա զեկույցից տեղեկանում ենք, որ որոշակի զտիչ պահանջել է որոշակի քանակությամբ հիշողություն և այն բազմիցս չի վերադարձրել կույտ N-ին: Դուք հեշտությամբ կարող եք կռահել, որ կլինի հղում դեպի MS_VOID_SOURCE տիպի ներքին ֆիլտրի գործառույթները: Նրա խնդիրն է հիշողություն վերցնել կույտից: Այլ զտիչներ պետք է վերադարձնեն այն այնտեղ: Նրանք. մենք կբացահայտենք արտահոսքի փաստը.

Որոշելու համար, թե խողովակաշարի որ հատվածում է եղել անգործությունը, որը հանգեցրել է հիշողության արտահոսքի, առաջարկվում է ներդնել լրացուցիչ զտիչ, որը պարզապես հաղորդագրությունները տեղափոխում է մուտքից ելք, բայց միևնույն ժամանակ ստեղծում է մուտքային հաղորդագրության պատճենը, որը ոչ թեթև է: , այլ ավելի շուտ սովորական «ծանր», այնուհետև ամբողջությամբ ջնջում է մուտքի մոտ ստացված հաղորդագրությունը: Նման ֆիլտրը մենք կանվանենք մեկուսիչ: Մենք հավատում ենք, որ քանի որ ֆիլտրը պարզ է, դրա մեջ արտահոսք չկա: Եվ ևս մեկ դրական հատկություն. եթե այն ավելացնենք մեր գրաֆիկում որևէ տեղ, դա որևէ կերպ չի ազդի շղթայի աշխատանքի վրա: Զտիչ-մեկուսիչը կպատկերենք կրկնակի շղթայով շրջանագծի տեսքով։

Մենք միացնում ենք մեկուսիչը voidsource ֆիլտրից անմիջապես հետո.
Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 12

Մենք նորից գործարկում ենք ծրագիրը անալիզատորով, և տեսնում ենք, որ այս անգամ անալիզատորը մեղադրելու է մեկուսիչին։ Ի վերջո, նա է, ով այժմ ստեղծում է տվյալների բլոկներ, որոնք հետո կորցնում են անհայտ անփույթ զտիչը (կամ ֆիլտրերը): Հաջորդ քայլը մեկ ֆիլտրով մեկ ֆիլտրով մեկուսիչը տեղափոխելն է շղթայի երկայնքով և նորից սկսել վերլուծությունը: Այսպիսով, մեկուսարանը քայլ առ քայլ տեղափոխելով աջ, մենք կստանանք մի իրավիճակ, երբ հաջորդ անալիզատորի զեկույցում «արտահոսած» հիշողության բլոկների թիվը կնվազի: Սա նշանակում է, որ այս քայլում մեկուսիչը շղթայի մեջ էր խնդրահարույց ֆիլտրից անմիջապես հետո: Եթե ​​կար միայն մեկ «վատ» զտիչ, ապա արտահոսքն ընդհանրապես կվերանա: Այսպիսով, մենք տեղայնացրեցինք խնդրահարույց ֆիլտրը (կամ մի քանիսից մեկը): Ֆիլտրը «շտկելով»՝ մենք կարող ենք շարունակել մեկուսիչը շղթայի երկայնքով աջ տեղափոխել այնքան ժամանակ, մինչև ամբողջությամբ չհաղթահարենք հիշողության արտահոսքը:

Մեկուսիչ ֆիլտրի ներդրում

Մեկուսիչի ներդրումը կարծես սովորական զտիչ է: Վերնագրի ֆայլ.

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

Ֆիլտրն ինքնին.

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

Հիշողության կառավարման գործառույթների փոխարինման մեթոդ

Ավելի նուրբ հետազոտության համար մեդիա հոսքագիծը հնարավորություն է տալիս փոխարինել հիշողության հասանելիության գործառույթները ձեր սեփականով, որը, բացի հիմնական աշխատանքից, ձայնագրելու է «Ով, որտեղ և ինչու»: Փոխարինված են երեք գործառույթներ. Դա արվում է հետևյալ կերպ.

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);

Այս հատկությունը օգնում է այն դեպքերում, երբ անալիզատորն այնքան է դանդաղեցնում ֆիլտրերի աշխատանքը, որ այն համակարգի աշխատանքը, որտեղ կառուցված է մեր միացումը, խաթարվում է: Նման իրավիճակում դուք պետք է հրաժարվեք անալիզատորից և հիշողության հետ աշխատելու համար օգտագործեք գործառույթների փոխարինում:

Մենք դիտարկել ենք գործողությունների ալգորիթմ պարզ գրաֆիկի համար, որը ճյուղեր չի պարունակում: Բայց այս մոտեցումը կարող է կիրառվել այլ դեպքերում, իհարկե, ավելի բարդ, բայց գաղափարը մնում է նույնը։

Հաջորդ հոդվածում մենք կանդրադառնանք ցուցիչի ծանրաբեռնվածության գնահատման խնդրին և մեդիա հոսքի ավելորդ հաշվողական բեռի դեմ պայքարելու ուղիներին:

Source: www.habr.com

Добавить комментарий