关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » .NET »WPF 属性系统 依赖属性之内存占用分析

    WPF 属性系统 依赖属性之内存占用分析

    2015-03-28 00:00:00 出处:richieyang
    分享

    关于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的属性系统真的没有特别设计来优化内存。只是这种提供入口点的方式顺带就减少了内存的占用。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    小米路由器买哪款?Miwifi热门路由器型号对比分析

    IT头条

    Synology 对 Office 套件进行重大 AI 更新,增强私有云的生产力和安全性

    01:43

    StorONE 的高效平台将 Storage Guardian 数据中心占用空间减少 80%

    11:03

    年赚千亿的印度能源巨头Nayara 云服务瘫痪,被微软卡了一下脖子

    12:54

    国产6nm GPU新突破!砺算科技官宣:自研TrueGPU架构7月26日发布

    01:57

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    技术热点

    如何删除自带的不常用应用为windows 7减负

    MySQL中多表删除方法

    改进的二值图像像素标记算法及程序实现

    windows 7 32位系统下手动修改磁盘属性例如M盘修改为F盘

    windows 7中怎么样在家庭组互传文件

    Linux应用集成MySQL数据库访问技巧

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。