Bagikan melalui


Mengoptimalkan Performa: Perilaku Objek

Memahami perilaku intrinsik objek WPF akan membantu Anda melakukan tradeoff yang tepat antara fungsionalitas dan performa.

Tidak Menghapus Penanganan Aktivitas pada Objek dapat Menjaga Objek Tetap Hidup

Delegasi yang diteruskan objek ke peristiwanya secara efektif merupakan referensi ke objek tersebut. Oleh karena itu, penanganan aktivitas dapat menjaga objek tetap hidup lebih lama dari yang diharapkan. Saat melakukan pembersihan objek yang telah terdaftar untuk mendengarkan peristiwa objek, penting untuk menghapus delegasi tersebut sebelum merilis objek. Menjaga objek yang tidak dibutuhkan tetap hidup meningkatkan penggunaan memori aplikasi. Ini terutama berlaku ketika objek adalah akar pohon logis atau pohon visual.

WPF memperkenalkan pola pendengar peristiwa yang lemah untuk peristiwa yang dapat berguna dalam situasi di mana hubungan seumur hidup objek antara sumber dan pendengar sulit dilacak. Beberapa peristiwa WPF yang ada menggunakan pola ini. Jika Anda menerapkan objek dengan peristiwa kustom, pola ini mungkin digunakan untuk Anda. Untuk detailnya, lihat Pola Peristiwa Lemah.

Ada beberapa alat, seperti CLR Profiler dan Penampil Set Kerja, yang dapat memberikan informasi tentang penggunaan memori proses yang ditentukan. CLR Profiler mencakup sejumlah tampilan profil alokasi yang sangat berguna, termasuk histogram jenis yang dialokasikan, grafik alokasi dan panggilan, garis waktu yang menunjukkan pengumpulan sampah dari berbagai generasi dan status timbunan terkelola yang dihasilkan setelah koleksi tersebut, dan pohon panggilan yang menunjukkan alokasi per metode dan beban perakitan. Untuk informasi selengkapnya, lihat Performa.

Properti dan Objek Dependensi

Secara umum, mengakses properti dependensi dari DependencyObject tidak lebih lambat daripada mengakses properti CLR. Meskipun ada overhead performa kecil untuk menetapkan nilai properti, mendapatkan nilai secepat mendapatkan nilai dari properti CLR. Mengimbangi overhead performa kecil adalah fakta bahwa properti dependensi mendukung fitur yang kuat, seperti pengikatan data, animasi, warisan, dan gaya. Untuk informasi selengkapnya, lihat Gambaran Umum Properti Dependensi.

Pengoptimalan DependencyProperty

Anda harus menentukan properti dependensi dalam aplikasi Anda dengan sangat hati-hati. Jika Anda DependencyProperty hanya memengaruhi opsi metadata jenis render, bukan opsi metadata lainnya seperti AffectsMeasure, Anda harus menandainya dengan mengambil alih metadatanya. Untuk informasi selengkapnya tentang mengambil alih atau mendapatkan metadata properti, lihat Metadata Properti Dependensi.

Mungkin lebih efisien untuk memiliki handler perubahan properti yang membatalkan pengukuran, susun, dan render lolos secara manual jika tidak semua perubahan properti benar-benar memengaruhi pengukuran, pengaturan, dan render. Misalnya, Anda dapat memutuskan untuk merender kembali latar belakang hanya ketika nilai lebih besar dari batas yang ditetapkan. Dalam hal ini, handler perubahan properti Anda hanya akan membatalkan render ketika nilai melebihi batas yang ditetapkan.

Membuat DependencyProperty Inheritable Tidak Gratis

Secara default, properti dependensi terdaftar tidak dapat diwariskan. Namun, Anda dapat secara eksplisit membuat properti apa pun dapat diwariskan. Meskipun ini adalah fitur yang berguna, mengonversi properti menjadi dapat diwariskan berdampak pada performa dengan meningkatkan lamanya waktu untuk pembatalan properti.

Gunakan RegisterClassHandler Dengan Hati-hati

Saat memanggil RegisterClassHandler memungkinkan Anda menyimpan status instans, penting untuk mengetahui bahwa handler dipanggil pada setiap instans, yang dapat menyebabkan masalah performa. Hanya gunakan RegisterClassHandler saat aplikasi Anda mengharuskan Anda menyimpan status instans Anda.

Atur Nilai Default untuk DependencyProperty selama Pendaftaran

Saat membuat DependencyProperty yang memerlukan nilai default, atur nilai menggunakan metadata default yang diteruskan sebagai parameter ke Register metode DependencyProperty. Gunakan teknik ini daripada mengatur nilai properti dalam konstruktor atau pada setiap instans elemen.

Atur Nilai PropertyMetadata menggunakan Daftar

Saat membuat DependencyProperty, Anda memiliki opsi untuk mengatur PropertyMetadata penggunaan Register metode atau OverrideMetadata . Meskipun objek Anda dapat memiliki konstruktor statis untuk memanggil OverrideMetadata, ini bukan solusi optimal dan akan berdampak pada performa. Untuk performa terbaik, atur PropertyMetadata selama panggilan ke Register.

Objek yang Dapat Dibekukan

adalah Freezable jenis objek khusus yang memiliki dua status: tidak dibekukan dan dibekukan. Membekukan objek jika memungkinkan meningkatkan performa aplikasi Anda dan mengurangi set kerjanya. Untuk informasi selengkapnya, lihat Gambaran Umum Objek Freezable.

Masing-masing Freezable memiliki Changed peristiwa yang dimunculkan setiap kali berubah. Namun, pemberitahuan perubahan mahal dalam hal performa aplikasi.

Pertimbangkan contoh berikut di mana masing-masing Rectangle menggunakan objek yang sama Brush :

rectangle_1.Fill = myBrush;
rectangle_2.Fill = myBrush;
rectangle_3.Fill = myBrush;
// ...
rectangle_10.Fill = myBrush;
rectangle_1.Fill = myBrush
rectangle_2.Fill = myBrush
rectangle_3.Fill = myBrush
' ...
rectangle_10.Fill = myBrush

Secara default, WPF menyediakan penanganan aktivitas untuk SolidColorBrush peristiwa objek Changed untuk membatalkan validasi Rectangle properti objek Fill . Dalam hal ini, setiap kali SolidColorBrush harus menyalakan peristiwanya Changed , diperlukan untuk memanggil fungsi panggilan balik untuk masing-masing Rectangle—akumulasi pemanggilan fungsi panggilan balik ini memberlakukan hukuman performa yang signifikan. Selain itu, sangat intensif performa untuk menambahkan dan menghapus handler pada saat ini karena aplikasi harus melintasi seluruh daftar untuk melakukannya. Jika skenario aplikasi Anda tidak pernah mengubah SolidColorBrush, Anda akan membayar biaya untuk mempertahankan Changed penanganan aktivitas secara tidak perlu.

Membekukan Freezable dapat meningkatkan performanya, karena tidak perlu lagi mengeluarkan sumber daya untuk mempertahankan pemberitahuan perubahan. Tabel di bawah ini menunjukkan ukuran sederhana SolidColorBrush ketika propertinya IsFrozen diatur ke true, dibandingkan dengan ketika tidak. Ini mengasumsikan menerapkan satu kuas ke Fill properti sepuluh Rectangle objek.

Solid Ukuran
Beku SolidColorBrush 212 Byte
Tidak beku SolidColorBrush 972 Byte

Sampel kode berikut menunjukkan konsep ini:

Brush frozenBrush = new SolidColorBrush(Colors.Blue);
frozenBrush.Freeze();
Brush nonFrozenBrush = new SolidColorBrush(Colors.Blue);

for (int i = 0; i < 10; i++)
{
    // Create a Rectangle using a non-frozed Brush.
    Rectangle rectangleNonFrozen = new Rectangle();
    rectangleNonFrozen.Fill = nonFrozenBrush;

    // Create a Rectangle using a frozed Brush.
    Rectangle rectangleFrozen = new Rectangle();
    rectangleFrozen.Fill = frozenBrush;
}
Dim frozenBrush As Brush = New SolidColorBrush(Colors.Blue)
frozenBrush.Freeze()
Dim nonFrozenBrush As Brush = New SolidColorBrush(Colors.Blue)

For i As Integer = 0 To 9
    ' Create a Rectangle using a non-frozed Brush.
    Dim rectangleNonFrozen As New Rectangle()
    rectangleNonFrozen.Fill = nonFrozenBrush

    ' Create a Rectangle using a frozed Brush.
    Dim rectangleFrozen As New Rectangle()
    rectangleFrozen.Fill = frozenBrush
Next i

Handler yang Diubah pada Unfrozen Freezables dapat Menjaga Objek Tetap Hidup

Delegasi yang diteruskan objek ke Freezable peristiwa objek secara efektif merupakan referensi ke objek tersebut Changed . Oleh karena itu, Changed penanganan aktivitas dapat menjaga objek tetap hidup lebih lama dari yang diharapkan. Saat melakukan pembersihan objek yang telah terdaftar untuk mendengarkan Freezable peristiwa objek Changed , penting untuk menghapus delegasi tersebut sebelum merilis objek.

WPF juga menghubungkan Changed peristiwa secara internal. Misalnya, semua properti dependensi yang mengambil Freezable sebagai nilai akan mendengarkan Changed peristiwa secara otomatis. Properti Fill , yang mengambil Brush, mengilustrasikan konsep ini.

Brush myBrush = new SolidColorBrush(Colors.Red);
Rectangle myRectangle = new Rectangle();
myRectangle.Fill = myBrush;
Dim myBrush As Brush = New SolidColorBrush(Colors.Red)
Dim myRectangle As New Rectangle()
myRectangle.Fill = myBrush

Pada penetapan myBrush ke myRectangle.Fill, delegasi yang menunjuk kembali ke Rectangle objek akan ditambahkan ke SolidColorBrush peristiwa objek Changed . Ini berarti kode berikut tidak benar-benar memenuhi myRect syarat untuk pengumpulan sampah:

myRectangle = null;
myRectangle = Nothing

Dalam hal myBrush ini masih tetap myRectangle hidup dan akan memanggil kembali ketika peristiwa itu terjadi Changed . Perhatikan bahwa menetapkan myBrush ke properti baru Rectangle hanya akan menambahkan penanganan aktivitas lain ke myBrushFill .

Cara yang disarankan untuk membersihkan jenis objek ini adalah dengan menghapus Brush dari Fill properti , yang pada gilirannya Changed akan menghapus penanganan aktivitas.

myRectangle.Fill = null;
myRectangle = null;
myRectangle.Fill = Nothing
myRectangle = Nothing

Virtualisasi Antarmuka Pengguna

WPF juga menyediakan variasi StackPanel elemen yang secara otomatis "memvirtualisasikan" konten anak yang terikat data. Dalam konteks ini, kata virtualisasi mengacu pada teknik di mana subset objek dihasilkan dari sejumlah besar item data berdasarkan item mana yang terlihat di layar. Ini intensif, baik dalam hal memori dan prosesor, untuk menghasilkan sejumlah besar elemen UI ketika hanya beberapa yang mungkin ada di layar pada waktu tertentu. VirtualizingStackPanel (melalui fungsionalitas yang disediakan oleh VirtualizingPanel) menghitung item yang terlihat dan bekerja dengan ItemContainerGenerator dari ItemsControl (seperti ListBox atau ListView) untuk hanya membuat elemen untuk item yang terlihat.

Sebagai pengoptimalan performa, objek visual untuk item ini hanya dihasilkan atau tetap hidup jika terlihat di layar. Ketika mereka tidak lagi berada di area kontrol yang dapat dilihat, objek visual dapat dihapus. Ini tidak akan dikacaukan dengan virtualisasi data, di mana objek data tidak semuanya ada dalam koleksi lokal- agak dialirkan sesuai kebutuhan.

Tabel di bawah ini menunjukkan waktu yang berlalu menambahkan dan merender 5000 TextBlock elemen ke StackPanel dan VirtualizingStackPanel. Dalam skenario ini, pengukuran mewakili waktu antara melampirkan string teks ke ItemsSource properti ItemsControl objek ke waktu ketika elemen panel menampilkan string teks.

Panel host Waktu render (ms)
StackPanel 3210
VirtualizingStackPanel 46

Baca juga