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));
    }
View Code

 

我們把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的屬性系統真的沒有特別設計來優化內存。只是這種提供入口點的方式順帶就減少了內存的占用。

 

本文地址:http://www.cnblogs.com/santian/p/4372667.html

博客地址:http://www.cnblogs.com/santian/

轉載請以超鏈接形式標明文章原始出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM