WPF 屬性系統 依賴屬性之記憶體佔用分析
關於WPF的屬性系統園子內有不少這方面的文章。裡面大都提到了WPF依賴屬性的在記憶體方面的優化。但是裡面大都一筆帶過。那麼WPF到底是怎麼樣節約記憶體的。我們通過WPF屬性和普通的CLR屬性對比來看一下WPF屬性在節約記憶體方面的優勢在哪裡。
普通的CLR屬性
public partial class WindowMemory : Window { Student0 stu; public WindowMemory() { InitializeComponent(); List<Student0> list = new List<Student0>(); for (int i = 0; i < 10000000; i++) { stu = new Student0(); list.Add(stu); } } }
public class Student0 { public double Name { get; set; } public double Name1 { get; set; } public double Name2 { get; set; } public double Name3 { get; set; } public double Name4 { get; set; } public double Name5 { get; set; } public double Name6 { get; set; } public double Name7 { get; set; } public double Name8 { get; set; } public double Name9 { get; set; } public double Name10 { get; set; } }
我們宣告一個Student0類,裡面放入十個屬性。然後new 一千萬個student 的例項載入到記憶體中。在工作管理員中看一下記憶體佔用。
我們看到程式大概佔用了一個G的記憶體。計算一下。因為c#中的屬性是通過get set方法對一個私有欄位的封裝,也就是說這個類裡面有十個double型別的私有欄位。double型別佔8個位元組。一兆是1048576個位元組,131072個double型別。一千萬個double大概佔用76兆的記憶體。我們這兒宣告瞭十個也就是760兆。另外還有student物件佔用的記憶體。所以這兒程式佔用記憶體大概是一個G;
依賴屬性
public class Student0 : DependencyObject { public double Name { get { return (double)GetValue(NameProperty); } set { SetValue(NameProperty, value); } } public double Name1 { get { return (double)GetValue(Name1Property); } set { SetValue(Name1Property, value); } } public double Name2 { get { return (double)GetValue(Name2Property); } set { SetValue(Name2Property, value); } } public double Name3 { get { return (double)GetValue(Name3Property); } set { SetValue(Name3Property, value); } } public double Name4 { get { return (double)GetValue(Name4Property); } set { SetValue(Name4Property, value); } } public double Name5 { get { return (double)GetValue(Name5Property); } set { SetValue(Name5Property, value); } } public double Name6 { get { return (double)GetValue(Name6Property); } set { SetValue(Name6Property, value); } } public double Name7 { get { return (double)GetValue(Name7Property); } set { SetValue(Name7Property, value); } } public double Name8 { get { return (double)GetValue(Name8Property); } set { SetValue(Name8Property, value); } } public double Name9 { get { return (double)GetValue(Name9Property); } set { SetValue(Name9Property, value); } } public double Name10 { get { return (double)GetValue(Name10Property); } set { SetValue(Name10Property, value); } }public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name1Property = DependencyProperty.Register("Name1", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name2Property = DependencyProperty.Register("Name2", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name3Property = DependencyProperty.Register("Name3", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name4Property = DependencyProperty.Register("Name4", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name5Property = DependencyProperty.Register("Name5", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name6Property = DependencyProperty.Register("Name6", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name7Property = DependencyProperty.Register("Name7", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name8Property = DependencyProperty.Register("Name8", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name9Property = DependencyProperty.Register("Name9", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name10Property = DependencyProperty.Register("Name10", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); }
我們把student類修改為依賴物件,在裡面實現十個依賴屬性,此時來檢視一下記憶體佔用
此時只有三百多兆的記憶體佔用。那麼WPF的屬性到底是如何節約記憶體的呢。因為CLR屬性是在例項宣告的時候就分配好了記憶體空間的。所以就算例項裡面沒有寫入值,或者仍然是預設值,仍然會分配好記憶體空間。但是WPF的依賴屬性不同。wpf的依賴屬性是如下宣告的
public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
注意上面的這條語句才是依賴屬性的宣告。而類似下面這樣的是我們通過clr屬性對依賴屬性NameProperty進行了包裝,使我們訪問起來更方便。就想普通的屬性那樣。
public double Name { get { return (double)GetValue(NameProperty); } set { SetValue(NameProperty, value); } }
也就是說我們其實可以直接這樣來宣告Student0物件
public class Student0 : DependencyObject { public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name1Property = DependencyProperty.Register("Name1", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name2Property = DependencyProperty.Register("Name2", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name3Property = DependencyProperty.Register("Name3", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name4Property = DependencyProperty.Register("Name4", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name5Property = DependencyProperty.Register("Name5", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name6Property = DependencyProperty.Register("Name6", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name7Property = DependencyProperty.Register("Name7", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name8Property = DependencyProperty.Register("Name8", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name9Property = DependencyProperty.Register("Name9", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); public static readonly DependencyProperty Name10Property = DependencyProperty.Register("Name10", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55)); }
然後通過setvalue,getvalue來存取值
注意其實依賴屬性的宣告,在這裡或者用註冊來形容更貼切,只是一個入口點。也就是我們平常常說的單例模式。屬性的值其實都放在依賴物件的一個雜湊表裡面。這裡資料很多,大家隨便找下就可以找到。
所以依賴屬性正在節約記憶體就在於這兒的依賴屬性是一個static readonly 屬性。所以不需要在物件每次例項化的時候都分配相關屬性的記憶體空間,而是提供一個入口點。
知道了這些我們再看一個沒什麼實際意義的例子。將student0物件修改如下。
public class Student0 { public double Name { get { return 1.00; } set { Name = 1.00; } } public double Name1 { get { return 1.00; } set { Name1 = 1.00; } } public double Name2 { get { return 1.00; } set { Name2 = 1.00; } } public double Name3 { get { return 1.00; } set { Name3 = 1.00; } } public double Name4 { get { return 1.00; } set { Name4 = 1.00; } } public double Name5 { get { return 1.00; } set { Name5 = 1.00; } } public double Name6 { get { return 1.00; } set { Name6 = 1.00; } } public double Name7 { get { return 1.00; } set { Name7 = 1.00; } } public double Name8 { get { return 1.00; } set { Name8 = 1.00; } } public double Name9 { get { return 1.00; } set { Name9 = 1.00; } } public double Name10 { get { return 1.00; } set { Name10 = 1.00; } } }
此時程式只佔用了不到200兆記憶體。因為屬性的本質其實就是一個get set 方法。而方法是不需要例項化的,只需要一個指標指向就可以了。這兒我沒沒有在屬性get;set;這種簡化寫法下宣告的私有欄位。所以沒有了這些私有欄位佔用的記憶體。記憶體佔用大大減少。
仔細對比我們就會發現。wpf的屬性系統真的沒有特別設計來優化記憶體。只是這種提供入口點的方式順帶就減少了記憶體的佔用。
相關文章
- WPF 之 依賴屬性與附加屬性(五)
- [WPF]淺析依賴屬性(DependencyProperty)
- 淺談WPF之屬性系統
- WPF依賴屬性的正確學習方法
- knockout原始碼分析之computed(依賴屬性)原始碼
- 依賴屬性之“風雲再起”薦
- [UWP]依賴屬性1:概述
- Spring 原始碼分析之 bean 依賴注入原理(注入屬性)Spring原始碼Bean依賴注入
- WPF and Silverlight 學習筆記(十三):依賴項屬性和路由事件筆記路由事件
- CMake 屬性之全域性屬性
- WPF進階技巧和實戰08-依賴屬性與繫結03
- WPF進階技巧和實戰08-依賴屬性與繫結02
- iOS全域性變數與屬性的記憶體管理iOS變數記憶體
- iOS開發-屬性的記憶體管理iOS記憶體
- CMake 屬性之目標屬性
- CMake 屬性之目錄屬性
- 【譯】為什麼命名“它”為依賴屬性(DependencyProperty)
- Spring原始碼系列:依賴注入(三)-屬性注入Spring原始碼依賴注入
- MIUI 9系統新屬性曝光:手機記憶體大瘦身UI記憶體
- WPF SL 屬性生成器
- WPF使用MVVM(一)-屬性繫結MVVM
- WPF 使用附加屬性宣告 ICommand
- Mac系統檔案屬性Mac
- iOS動畫 屬性屬性解析iOS動畫
- defer 屬性和 async 屬性
- flutter 屬性記錄Flutter
- EF Core 三 、 騷操作 (導航屬性,記憶體查詢...)記憶體
- CSS 屬性篇(七):Display屬性CSS
- win10系統屬性在哪裡 快速開啟win10系統屬性的方法Win10
- HCNP Routing&Switching之BGP團體屬性和團體屬性過濾器過濾器
- wpf xaml binding靜態類的屬性
- SQL Server 生成C#公共實體屬性和私有屬性SQLServerC#
- JavaScript私有屬性和靜態屬性JavaScript
- orcale 之遊標的屬性
- React之props屬性React
- Android屬性之excludeFromRecentsAndroid
- .net框架筆記——屬性框架筆記
- echarts常用屬性記錄Echarts