Menjelajahi mesin VoIP Mediastreamer2. Bagian 12

Materi artikel diambil dari saya saluran Zen.

Menjelajahi mesin VoIP Mediastreamer2. Bagian 12

Terakhir Artikel, saya berjanji untuk mempertimbangkan masalah estimasi beban ticker dan cara mengatasi beban komputasi yang berlebihan di media streamer. Tetapi saya memutuskan bahwa akan lebih logis untuk membahas masalah filter kerajinan debug yang terkait dengan pergerakan data dan baru kemudian mempertimbangkan masalah pengoptimalan kinerja.

Debugging filter kerajinan

Setelah kami memeriksa mekanisme pergerakan data di media streamer di artikel sebelumnya, masuk akal untuk membicarakan bahaya yang tersembunyi di dalamnya. Salah satu fitur dari prinsip "aliran data" adalah bahwa alokasi memori dari heap terjadi di filter yang terletak di sumber aliran data, dan filter yang terletak di ujung jalur aliran sudah membatalkan alokasi memori dengan pengembalian ke tumpukan. Selain itu, pembuatan data baru dan penghancurannya dapat terjadi di suatu tempat di titik tengah. Secara umum, pelepasan memori dilakukan oleh filter selain yang membuat blok data.

Dari sudut pandang pemantauan memori yang transparan, akan masuk akal jika filter, ketika menerima blok masukan, untuk segera menghancurkannya setelah diproses, membebaskan memori, dan meletakkan blok yang baru dibuat dengan data keluaran pada keluaran. Dalam hal ini, kebocoran memori di filter dapat dengan mudah dilacak β€” jika penganalisa mendeteksi kebocoran di filter, maka filter yang mengikutinya tidak menghancurkan blok yang masuk dengan benar dan ada kesalahan di dalamnya. Tetapi dari sudut pandang mempertahankan kinerja tinggi, pendekatan untuk bekerja dengan blok data ini tidak produktif - ini mengarah pada sejumlah besar operasi untuk mengalokasikan / membebaskan memori untuk blok data tanpa pembuangan yang berguna.

Untuk alasan ini, filter streamer media, agar tidak memperlambat pemrosesan data, saat menyalin pesan, gunakan fungsi yang membuat salinan ringan (kami membicarakannya di artikel sebelumnya). Fungsi-fungsi ini hanya membuat salinan baru dari header pesan dengan "melampirkan" blok data dari pesan "lama" yang disalin ke dalamnya. Akibatnya, dua header dilampirkan ke satu blok data dan penghitung referensi di blok data bertambah. Tapi itu akan terlihat seperti dua pesan. Mungkin ada lebih banyak pesan dengan blok data "publik" seperti itu, misalnya, filter MS_TEE menghasilkan sepuluh salinan ringan sekaligus, mendistribusikannya di antara keluarannya. Jika semua filter dalam rantai bekerja dengan benar, pada akhir pipa jumlah referensi ini harus mencapai nol dan fungsi alokasi memori akan dipanggil: ms_gratis(). Jika panggilan tidak terjadi, maka memori ini tidak akan dikembalikan lagi ke heap, mis. dia "bocor". Biaya menggunakan salinan ringan adalah hilangnya kemampuan untuk dengan mudah menentukan (seperti dalam kasus menggunakan salinan biasa) di mana filter grafik memori bocor.

Karena tanggung jawab untuk menemukan kebocoran memori di filter "asli" terletak pada pengembang streamer media, kemungkinan besar Anda tidak perlu men-debugnya. Tetapi dengan filter kerajinan Anda, Anda sendiri adalah belalang dari kebahagiaan Anda sendiri, dan waktu yang Anda habiskan untuk mencari kebocoran dalam kode Anda akan bergantung pada keakuratan Anda. Untuk mengurangi waktu debugging Anda, kami perlu melihat teknik pelokalan kebocoran saat merancang filter. Selain itu, mungkin saja kebocoran akan muncul dengan sendirinya hanya jika filter diterapkan dalam sistem nyata, di mana jumlah "tersangka" bisa sangat besar, dan waktu untuk debugging terbatas.

Bagaimana kebocoran memori memanifestasikan dirinya?

Adalah logis untuk mengasumsikan bahwa dalam keluaran program puncak akan menunjukkan peningkatan persentase memori yang ditempati oleh aplikasi Anda.

Manifestasi eksternal akan terdiri dari fakta bahwa di beberapa titik sistem akan bereaksi perlahan terhadap gerakan mouse, menggambar ulang layar secara perlahan. Mungkin juga log sistem akan bertambah, memakan ruang pada hard drive. Dalam hal ini, aplikasi Anda akan mulai berperilaku aneh, tidak merespons perintah, tidak dapat membuka file, dll.

Untuk mengidentifikasi fakta kebocoran, kami akan menggunakan penganalisa memori (selanjutnya disebut sebagai penganalisa). Bisa jadi valgrind (Bagus artikel tentang itu) atau dibangun ke dalam kompiler gcc Pembersih Memori atau sesuatu yang lain. Jika penganalisa menunjukkan bahwa kebocoran terjadi di salah satu filter grafik, maka ini berarti sudah waktunya untuk menerapkan salah satu metode yang dijelaskan di bawah ini.

Metode Tiga Pinus

Seperti disebutkan di atas, jika terjadi kebocoran memori, penganalisa akan menunjuk ke filter yang meminta alokasi memori dari heap. Tapi itu tidak akan menunjuk ke filter yang "lupa" mengembalikannya, yang sebenarnya harus disalahkan. Jadi, penganalisa hanya dapat memastikan ketakutan kita, tetapi tidak menunjukkan akarnya.

Untuk mengetahui lokasi filter "buruk" dalam grafik, Anda dapat melanjutkan dengan mengurangi grafik ke jumlah minimum node di mana penganalisa masih mendeteksi kebocoran dan menemukan filter yang bermasalah di tiga pinus yang tersisa.

Tetapi mungkin terjadi bahwa dengan mengurangi jumlah filter di kolom Anda akan mengganggu interaksi normal antara filter dan elemen lain dari sistem Anda dan kebocoran tidak akan muncul lagi. Dalam hal ini, Anda harus bekerja dengan grafik ukuran penuh dan menggunakan pendekatan yang dijelaskan di bawah ini.

Metode isolator geser

Untuk kesederhanaan penyajian, kami akan menggunakan grafik yang terdiri dari rangkaian filter tunggal. Dia ditampilkan dalam gambar.

Menjelajahi mesin VoIP Mediastreamer2. Bagian 12

Grafik biasa, di mana, bersama dengan filter streamer media yang sudah jadi, empat filter kerajinan F1…F4 digunakan, empat jenis berbeda yang Anda buat sejak lama dan tidak diragukan lagi kebenarannya. Namun, misalkan beberapa dari mereka mengalami kebocoran memori. Saat menjalankan program pengawasan penganalisis kami, kami mengetahui dari laporannya bahwa filter tertentu meminta sejumlah memori tertentu dan tidak mengembalikannya ke tumpukan sebanyak N kali. Mudah ditebak bahwa akan ada referensi ke fungsi filter internal dari tipe MS_VOID_SOURCE. Tugasnya adalah mengambil memori dari heap. Filter lain harus mengembalikannya ke sana. Itu. kita akan menemukan kebocorannya.

Untuk menentukan di bagian mana dari ketidakaktifan pipa terjadi yang menyebabkan kebocoran memori, diusulkan untuk memperkenalkan filter tambahan yang hanya menggeser pesan dari input ke output, tetapi pada saat yang sama membuat non-ringan, normal salinan "berat" dari pesan masukan, lalu menghapus sepenuhnya pesan yang sampai di keluaran pintu masuk. Kami akan menyebut filter semacam itu sebagai isolator. Kami percaya bahwa karena filternya sederhana, kebocoran di dalamnya tidak termasuk. Dan satu lagi properti positif - jika kita menambahkannya ke sembarang tempat di grafik kita, ini tidak akan memengaruhi pengoperasian sirkuit dengan cara apa pun. Kami akan menggambarkan filter isolator sebagai lingkaran dengan kontur ganda.

Aktifkan isolator tepat setelah filter voidsourse:
Menjelajahi mesin VoIP Mediastreamer2. Bagian 12

Kami menjalankan program dengan penganalisis lagi, dan kami melihat bahwa kali ini, penganalisa akan menyalahkan isolator. Lagi pula, dialah yang sekarang membuat blok data, yang kemudian hilang oleh filter (atau filter) lalai yang tidak diketahui. Langkah selanjutnya adalah menggeser isolator di sepanjang rantai ke kanan, dengan satu filter, dan memulai analisis lagi. Jadi, selangkah demi selangkah, dengan memindahkan isolator ke kanan, kita mendapatkan situasi ketika jumlah blok memori yang "bocor" di laporan penganalisa berikutnya berkurang. Ini berarti bahwa pada langkah ini isolator berakhir di rantai segera setelah filter bermasalah. Jika hanya ada satu filter yang "buruk", maka kebocorannya akan hilang sama sekali. Jadi, kami melokalkan filter yang bermasalah (atau salah satu dari beberapa). Setelah "memperbaiki" filter, kita dapat terus memindahkan isolator ke kanan sepanjang rantai hingga kebocoran memori benar-benar hilang.

Menerapkan filter isolator

Implementasi isolator terlihat seperti filter biasa. Berkas tajuk:

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

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

Metode penggantian fungsi manajemen memori

Untuk penelitian yang lebih halus, streamer media menyediakan kemampuan untuk mengganti fungsi akses memori dengan milik Anda, yang, selain pekerjaan utama, akan memperbaiki "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);

Fitur ini datang untuk menyelamatkan jika penganalisa sangat memperlambat filter sehingga pengoperasian sistem tempat sirkuit kami dibangun terganggu. Dalam situasi seperti itu, Anda harus meninggalkan penganalisa dan menggunakan substitusi fungsi memori.

Kami telah mempertimbangkan algoritme tindakan untuk graf sederhana yang tidak mengandung cabang. Tetapi pendekatan ini dapat diterapkan pada kasus lain, tentu saja dengan komplikasi, tetapi idenya tetap sama.

Pada artikel selanjutnya, kita akan melihat masalah estimasi beban ticker dan cara mengatasi beban komputasi yang berlebihan di media streamer.

Sumber: www.habr.com

Tambah komentar