کاوش در موتور VoIP Mediastreamer2. قسمت 12

مطالب مقاله از من گرفته شده است کانال ذن.

کاوش در موتور VoIP Mediastreamer2. قسمت 12

در آخر مقاله، قول دادم که موضوع تخمین بار تیک و راه های مقابله با بار محاسباتی بیش از حد را در استریمر مدیا در نظر بگیرم. اما من تصمیم گرفتم که منطقی تر است که مسائل مربوط به اشکال زدایی فیلترهای صنایع دستی مربوط به حرکت داده را پوشش دهم و تنها پس از آن مسائل بهینه سازی عملکرد را در نظر بگیرم.

رفع اشکال فیلترهای صنایع دستی

پس از اینکه در مقاله قبلی مکانیسم حرکت داده ها را در استریمر رسانه بررسی کردیم، منطقی است که در مورد خطرات نهفته در آن صحبت کنیم. یکی از ویژگی های اصل "جریان داده" این است که تخصیص حافظه از پشته در فیلترهایی که در منابع جریان داده قرار دارند اتفاق می افتد و فیلترهای واقع در انتهای مسیر جریان از قبل حافظه را با بازگشت تخصیص می دهند. به پشته علاوه بر این، ایجاد داده های جدید و تخریب آنها می تواند در جایی در نقاط میانی رخ دهد. به طور کلی، آزادسازی حافظه توسط فیلتری غیر از فیلتری که بلوک داده را ایجاد کرده انجام می شود.

از نقطه نظر نظارت شفاف بر حافظه، منطقی است که فیلتر هنگام دریافت بلوک ورودی، بلافاصله آن را پس از پردازش، آزاد کردن حافظه از بین ببرد و یک بلوک جدید ایجاد شده با داده های خروجی را روی خروجی قرار دهد. در این مورد، نشت حافظه در فیلتر را می توان به راحتی ردیابی کرد - اگر آنالیزور نشتی در فیلتر را تشخیص داد، فیلتری که از آن پیروی می کند به درستی بلوک های ورودی را از بین نمی برد و خطا در آن وجود دارد. اما از نقطه نظر حفظ عملکرد بالا، این رویکرد برای کار با بلوک های داده مولد نیست - منجر به تعداد زیادی عملیات برای تخصیص / حافظه آزاد برای بلوک های داده بدون اگزوز مفید می شود.

به همین دلیل، فیلترهای پخش کننده رسانه برای کاهش سرعت پردازش داده ها، هنگام کپی کردن پیام ها از عملکردهایی استفاده می کنند که کپی های سبک ایجاد می کنند (ما در مقاله قبلی در مورد آنها صحبت کردیم). این توابع فقط یک کپی جدید از هدر پیام را با "پیوست کردن" بلوک داده از پیام "قدیمی" کپی شده به آن ایجاد می کنند. در نتیجه، دو هدر به یک بلوک داده متصل شده و شمارنده مرجع در بلوک داده افزایش می یابد. اما شبیه دو پیام خواهد بود. ممکن است پیام های بیشتری با چنین بلوک داده "عمومی" وجود داشته باشد، برای مثال، فیلتر MS_TEE ده نسخه نوری از این دست را به طور همزمان تولید می کند و آنها را بین خروجی های خود توزیع می کند. اگر تمام فیلترهای زنجیره به درستی کار کنند، در پایان خط لوله، این تعداد مرجع باید به صفر برسد و تابع تخصیص حافظه فراخوانی می شود: ms_free(). اگر تماس رخ ندهد، این قطعه حافظه دیگر به پشته بازگردانده نمی شود، یعنی. او "نشت می کند". هزینه استفاده از کپی‌های سبک از دست دادن توانایی تشخیص آسان (همانطور که در مورد استفاده از نسخه‌های معمولی می‌شود) است که در کدام فیلتر گراف حافظه نشت می‌کند.

از آنجایی که مسئولیت یافتن نشت حافظه در فیلترهای "بومی" بر عهده توسعه دهندگان پخش کننده رسانه است، به احتمال زیاد شما مجبور نخواهید بود آنها را اشکال زدایی کنید. اما با فیلتر ساخت خود، شما خود ملخ خوشبختی خود هستید و زمانی که صرف جستجوی نشت در کد خود می کنید به دقت شما بستگی دارد. برای کاهش زمان اشکال‌زدایی، باید تکنیک‌های محلی‌سازی نشتی را هنگام طراحی فیلترها بررسی کنیم. علاوه بر این، ممکن است اتفاق بیفتد که نشت تنها هنگام اعمال فیلتر در یک سیستم واقعی، جایی که تعداد "مظنونان" می تواند زیاد باشد و زمان رفع اشکال محدود است، خود را نشان دهد.

نشت حافظه چگونه خود را نشان می دهد؟

منطقی است که در خروجی برنامه فرض کنیم بالا درصد فزاینده ای از حافظه اشغال شده توسط برنامه شما را نشان می دهد.

تظاهرات خارجی در این واقعیت است که در نقطه ای سیستم به آرامی به حرکت ماوس واکنش نشان می دهد و به آرامی صفحه را دوباره ترسیم می کند. همچنین این امکان وجود دارد که گزارش سیستم رشد کند و فضای روی هارد دیسک را اشغال کند. در این حالت، برنامه شما شروع به رفتار عجیب می کند، به دستورات پاسخ نمی دهد، نمی تواند فایل را باز کند و غیره.

برای شناسایی واقعیت نشتی، از یک تحلیلگر حافظه (که از این پس آنالایزر نامیده می شود) استفاده خواهیم کرد. میتوانست باشد والگریند (خوب مقاله در مورد آن) یا در کامپایلر تعبیه شده است gcc ضد عفونی کننده حافظه یا چیز دیگری. اگر تحلیلگر نشان دهد که نشت در یکی از فیلترهای گراف رخ می دهد، به این معنی است که زمان اعمال یکی از روش های شرح داده شده در زیر فرا رسیده است.

روش سه کاج

همانطور که در بالا ذکر شد، در صورت نشت حافظه، آنالایزر به فیلتری اشاره می کند که درخواست تخصیص حافظه از پشته را داشته است. اما به فیلتری اشاره نخواهد کرد که "فراموش کرده" آن را برگرداند، که در واقع مقصر است. بنابراین، تحلیلگر فقط می تواند ترس های ما را تأیید کند، اما به ریشه آنها اشاره نمی کند.

برای پیدا کردن محل فیلتر «بد» در نمودار، می‌توانید با کاهش نمودار به حداقل تعداد گره‌هایی که تحلیلگر هنوز نشت را تشخیص می‌دهد، بروید و فیلتر مشکل‌دار را در سه پین ​​باقی‌مانده پیدا کنید.

اما ممکن است با کاهش تعداد فیلترها در ستون، روند عادی تعامل بین فیلترها و سایر عناصر سیستم شما مختل شود و دیگر نشت ظاهر نشود. در این مورد، شما باید با یک نمودار با اندازه کامل کار کنید و از روشی که در زیر توضیح داده شده است استفاده کنید.

روش عایق کشویی

برای سادگی ارائه، از نموداری استفاده خواهیم کرد که از یک زنجیره واحد از فیلترها تشکیل شده است. او در تصویر نشان داده شده است.

کاوش در موتور VoIP Mediastreamer2. قسمت 12

یک نمودار معمولی که در آن به همراه فیلترهای مدیا استریمر آماده، از چهار فیلتر کاردستی F1…F4 استفاده شده است، چهار نوع مختلف که خیلی وقت پیش ساخته اید و در صحت آنها شکی ندارید. با این حال، فرض کنید که تعدادی از آنها نشت حافظه دارند. هنگام اجرای برنامه نظارت بر تحلیلگر، از گزارش آن متوجه می‌شویم که فیلتر خاصی مقدار مشخصی حافظه را درخواست کرده و آن را N بار به پشته برنگردانده است. به راحتی می توان حدس زد که اشاره ای به عملکردهای فیلتر داخلی از نوع MS_VOID_SOURCE وجود خواهد داشت. وظیفه او برداشتن حافظه از پشته است. فیلترهای دیگر باید آن را به آنجا برگردانند. آن ها ما نشت را پیدا خواهیم کرد.

به منظور تعیین اینکه در کدام بخش از خط لوله عدم فعالیت رخ داده است که منجر به نشت حافظه شده است، پیشنهاد می شود یک فیلتر اضافی معرفی شود که به سادگی پیام ها را از ورودی به خروجی منتقل می کند، اما در عین حال یک غیر سبک و معمولی ایجاد می کند. کپی "سنگین" از پیام ورودی، سپس به طور کامل پیامی را که به خروجی رسیده است حذف کنید. ما چنین فیلتری را عایق می نامیم. ما معتقدیم که از آنجایی که فیلتر ساده است، نشت در آن منتفی است. و یک ویژگی مثبت دیگر - اگر آن را به هر مکانی در نمودار خود اضافه کنیم، این به هیچ وجه بر عملکرد مدار تأثیر نمی گذارد. فیلتر عایق را به صورت دایره ای با کانتور دوتایی به تصویر می کشیم.

جداساز را درست بعد از فیلتر voidsourse فعال کنید:
کاوش در موتور VoIP Mediastreamer2. قسمت 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);

این ویژگی در مواقعی به کمک می آید که آنالایزر فیلترها را به قدری کند می کند که عملکرد سیستمی که مدار ما در آن ساخته شده است دچار اختلال می شود. در چنین شرایطی باید آنالایزر را رها کرده و از جایگزینی توابع حافظه استفاده کنید.

ما الگوریتمی از اقدامات را برای یک نمودار ساده در نظر گرفته‌ایم که شامل شاخه‌ها نیست. اما این رویکرد را می توان در موارد دیگر البته با پیچیدگی اعمال کرد، اما ایده همان است.

در مقاله بعدی به مسئله تخمین بار تیک و نحوه برخورد با بار محاسباتی بیش از حد در استریمر رسانه خواهیم پرداخت.

منبع: www.habr.com

اضافه کردن نظر