Meneroka enjin Mediastreamer2 VoIP. Bahagian 12

Bahan artikel diambil dari saya saluran zen.

Meneroka enjin Mediastreamer2 VoIP. Bahagian 12

Pada masa lalu artikel, saya berjanji untuk mempertimbangkan isu anggaran beban ticker dan cara menangani beban pengkomputeran yang berlebihan dalam strim media. Tetapi saya memutuskan bahawa adalah lebih logik untuk merangkumi isu penyahpepijatan penapis kraf yang berkaitan dengan pergerakan data dan hanya kemudian mempertimbangkan isu pengoptimuman prestasi.

Menyahpepijat penapis kraf

Selepas kita meneliti mekanisme pergerakan data dalam strim media dalam artikel sebelumnya, adalah logik untuk bercakap tentang bahaya yang tersembunyi di dalamnya. Salah satu ciri prinsip "aliran data" ialah peruntukan memori daripada timbunan berlaku dalam penapis yang terletak di sumber aliran data, dan penapis yang terletak di hujung laluan aliran sudah mengagihkan memori dengan pulangan. kepada timbunan. Di samping itu, penciptaan data baharu dan pemusnahannya boleh berlaku di suatu tempat di titik perantaraan. Secara umum, pelepasan memori dilakukan oleh penapis selain daripada yang mencipta blok data.

Dari sudut pandangan pemantauan telus ingatan, adalah munasabah untuk penapis, apabila menerima blok input, segera memusnahkannya selepas memproses, membebaskan memori, dan meletakkan blok yang baru dibuat dengan data output pada output. Dalam kes ini, kebocoran memori dalam penapis boleh dikesan dengan mudah β€” jika penganalisis mengesan kebocoran dalam penapis, maka penapis yang mengikutinya tidak memusnahkan blok masuk dengan betul dan terdapat ralat di dalamnya. Tetapi dari sudut pandangan mengekalkan prestasi tinggi, pendekatan untuk bekerja dengan blok data ini tidak produktif - ia membawa kepada sejumlah besar operasi untuk memperuntukkan / membebaskan memori untuk blok data tanpa sebarang ekzos yang berguna.

Atas sebab ini, penapis penstrim media, agar tidak melambatkan pemprosesan data, apabila menyalin mesej menggunakan fungsi yang mencipta salinan ringan (kami bercakap tentangnya dalam artikel sebelumnya). Fungsi ini hanya mencipta salinan baharu pengepala mesej dengan "melampirkan" blok data daripada mesej "lama" yang disalin kepadanya. Akibatnya, dua pengepala dilampirkan pada satu blok data dan kaunter rujukan dalam blok data ditambah. Tetapi ia akan kelihatan seperti dua mesej. Mungkin terdapat lebih banyak mesej dengan blok data "awam" sedemikian, sebagai contoh, penapis MS_TEE menjana sepuluh salinan ringan sedemikian sekaligus, mengedarkannya di antara outputnya. Jika semua penapis dalam rantai berfungsi dengan betul, pada penghujung saluran paip kiraan rujukan ini akan mencapai sifar dan fungsi deallocation memori akan dipanggil: ms_free(). Jika panggilan tidak berlaku, maka cebisan memori ini tidak akan dikembalikan ke timbunan, i.e. dia "bocor". Kos menggunakan salinan ringan ialah kehilangan keupayaan untuk menentukan dengan mudah (seperti yang berlaku dalam kes menggunakan salinan biasa) di mana penapis graf memori bocor.

Memandangkan tanggungjawab untuk mencari kebocoran memori dalam penapis "asli" terletak pada pembangun penstrim media, maka kemungkinan besar anda tidak perlu menyahpepijatnya. Tetapi dengan penapis kerajinan anda, anda sendiri adalah belalang kebahagiaan anda sendiri, dan masa yang anda luangkan untuk mencari kebocoran dalam kod anda akan bergantung pada ketepatan anda. Untuk mengurangkan masa penyahpepijatan anda, kami perlu melihat teknik penyetempatan kebocoran semasa mereka bentuk penapis. Di samping itu, mungkin berlaku bahawa kebocoran akan nyata hanya apabila menggunakan penapis dalam sistem sebenar, di mana bilangan "suspek" boleh menjadi besar, dan masa untuk nyahpepijat adalah terhad.

Bagaimanakah kebocoran ingatan menunjukkan dirinya?

Adalah logik untuk menganggap bahawa dalam output program bahagian akan menunjukkan peningkatan peratusan memori yang diduduki oleh aplikasi anda.

Manifestasi luaran akan terdiri daripada fakta bahawa pada satu ketika sistem akan bertindak balas perlahan-lahan terhadap pergerakan tetikus, perlahan-lahan melukis semula skrin. Ia juga mungkin bahawa log sistem akan berkembang, memakan ruang pada cakera keras. Dalam kes ini, aplikasi anda akan mula berkelakuan pelik, tidak bertindak balas kepada arahan, tidak boleh membuka fail, dsb.

Untuk mengenal pasti fakta kebocoran, kami akan menggunakan penganalisis memori (selepas ini dirujuk sebagai penganalisis). boleh jadi valgrind (baik artikel mengenainya) atau dibina ke dalam pengkompil gcc MemorySanitizer atau sesuatu yang lain. Jika penganalisis menunjukkan bahawa kebocoran berlaku dalam salah satu penapis graf, maka ini bermakna sudah tiba masanya untuk menggunakan salah satu kaedah yang diterangkan di bawah.

Kaedah Tiga Pine

Seperti yang dinyatakan di atas, sekiranya berlaku kebocoran memori, penganalisis akan menunjuk kepada penapis yang meminta peruntukan memori daripada timbunan. Tetapi ia tidak akan menunjuk kepada penapis yang "terlupa" untuk mengembalikannya, yang sebenarnya, harus dipersalahkan. Oleh itu, penganalisis hanya boleh mengesahkan ketakutan kita, tetapi tidak menunjukkan akarnya.

Untuk mengetahui lokasi penapis "buruk" dalam graf, anda boleh pergi dengan mengurangkan graf kepada bilangan minimum nod di mana penganalisis masih mengesan kebocoran dan mencari penapis yang bermasalah dalam baki tiga pain.

Tetapi mungkin berlaku bahawa dengan mengurangkan bilangan penapis dalam lajur anda akan mengganggu perjalanan biasa interaksi antara penapis dan elemen lain sistem anda dan kebocoran tidak akan muncul lagi. Dalam kes ini, anda perlu bekerja dengan graf bersaiz penuh dan menggunakan pendekatan yang diterangkan di bawah.

Kaedah penebat gelongsor

Untuk kesederhanaan pembentangan, kami akan menggunakan graf yang terdiri daripada satu rantai penapis. Dia ditunjukkan dalam gambar.

Meneroka enjin Mediastreamer2 VoIP. Bahagian 12

Graf biasa, di mana, bersama-sama dengan penapis strim media siap pakai, empat penapis kraf F1…F4 digunakan, empat jenis berbeza yang anda buat lama dahulu dan tidak ragu-ragu tentang ketepatannya. Walau bagaimanapun, anggap beberapa daripada mereka mempunyai kebocoran ingatan. Semasa menjalankan program penyeliaan penganalisis kami, kami mengetahui daripada laporannya bahawa penapis tertentu meminta jumlah memori tertentu dan tidak mengembalikannya ke timbunan N kali. Adalah mudah untuk meneka bahawa akan ada rujukan kepada fungsi penapis dalaman jenis MS_VOID_SOURCE. Tugasnya adalah untuk mengambil ingatan dari timbunan. Penapis lain harus mengembalikannya ke sana. Itu. kami akan mencari kebocoran.

Untuk menentukan bahagian mana saluran paip tidak aktif berlaku yang membawa kepada kebocoran memori, adalah dicadangkan untuk memperkenalkan penapis tambahan yang hanya mengalihkan mesej daripada input ke output, tetapi pada masa yang sama mencipta salinan bukan cahaya input. mesej menjadi salinan "berat" biasa, kemudian memadam sepenuhnya mesej yang tiba di pintu masuk. Kami akan memanggil penapis sedemikian sebagai penebat. Kami percaya bahawa kerana penapis adalah mudah, kebocoran di dalamnya dikecualikan. Dan satu lagi sifat positif - jika kita menambahkannya ke mana-mana tempat dalam graf kita, maka ini tidak akan menjejaskan operasi litar dalam apa jua cara. Kami akan menggambarkan penapis penebat sebagai bulatan dengan kontur berganda.

Dayakan pengasing sejurus selepas penapis voidsourse:
Meneroka enjin Mediastreamer2 VoIP. Bahagian 12

Kami menjalankan program dengan penganalisis sekali lagi, dan kami melihat bahawa kali ini, penganalisis akan meletakkan kesalahan pada pengasing. Lagipun, dialah yang kini mencipta blok data, yang kemudiannya hilang oleh penapis cuai yang tidak diketahui (atau penapis). Langkah seterusnya ialah mengalihkan penebat sepanjang rantai ke kanan, dengan satu penapis, dan mulakan analisis semula. Jadi, langkah demi langkah, mengalihkan pengasing ke kanan, kita mendapat situasi apabila bilangan blok memori "bocor" dalam laporan penganalisis seterusnya berkurangan. Ini bermakna bahawa pada langkah ini penebat berakhir dalam rantai sejurus selepas penapis yang bermasalah. Sekiranya terdapat hanya satu penapis "buruk", maka kebocoran akan hilang sama sekali. Oleh itu, kami menyetempatkan penapis yang bermasalah (atau salah satu daripada beberapa). Setelah "membetulkan" penapis, kami boleh terus mengalihkan pengasing ke kanan sepanjang rantai sehingga kebocoran memori dihapuskan sepenuhnya.

Melaksanakan penapis pengasing

Pelaksanaan pengasing kelihatan seperti penapis biasa. Fail pengepala:

/* Π€Π°ΠΉΠ» 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

Penapis itu sendiri:

/* Π€Π°ΠΉΠ» 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)

Kaedah menggantikan fungsi pengurusan memori

Untuk penyelidikan yang lebih halus, penstrim media menyediakan keupayaan untuk menggantikan fungsi akses memori dengan anda sendiri, yang, sebagai tambahan kepada kerja utama, akan menetapkan "Siapa, di mana dan mengapa." Tiga fungsi sedang diganti. Ini dilakukan dengan cara berikut:

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

Ciri ini datang untuk menyelamatkan dalam kes apabila penganalisis memperlahankan penapis sehingga operasi sistem di mana litar kami dibina terganggu. Dalam keadaan sedemikian, anda perlu meninggalkan penganalisis dan menggunakan penggantian fungsi ingatan.

Kami telah mempertimbangkan algoritma tindakan untuk graf ringkas yang tidak mengandungi cawangan. Tetapi pendekatan ini boleh digunakan untuk kes lain, sudah tentu dengan komplikasi, tetapi ideanya tetap sama.

Dalam artikel seterusnya, kita akan melihat isu anggaran beban ticker dan cara menangani beban pengkomputeran yang berlebihan dalam strim media.

Sumber: www.habr.com

Tambah komen