专栏首页DotNet程序园C#中谁最快:结构还是类?

C#中谁最快:结构还是类?

前言

在内存当道的日子里,无论什么时候都要考虑这些代码是否会影响程序性能呢? 在现在的世界里,几乎不会去考虑用了几百毫秒,可是在特别的场景了,往往这几百毫米确影响了整个项目的快慢。 通过了解这两者之间的性能差异,希望帮助大家在合适的场景里选择正确的编码。

实例

Copy
public class PointClass
{
    public int X { get; set; }
    public int Y { get; set; }
    public PointClass(int x, int y)
    {
        X = x;
        Y = y;
    }
}

public class PointClassFinalized : PointClass
{
    public PointClassFinalized(int x, int y) : base(x, y)
    {
    }
    ~PointClassFinalized()
    {
        // added a finalizer to slow down the GC

    }
}

public struct PointStruct
{
    public int X { get; set; }
    public int Y { get; set; }
    public PointStruct(int x, int y)
    {
        X = x;
        Y = y;
    }
}

public class StructsTest : PerformanceTest
{
    protected override bool MeasureTestA()
    {
        // access array elements
        var list = new PointClassFinalized[Iterations];
        for (int i = 0; i < Iterations; i++)
        {
            list[i] = new PointClassFinalized(i, i);
        }
        return true;
    }

    protected override bool MeasureTestB()
    {
        // access array elements
        var list = new PointClass[Iterations];
        for (int i = 0; i < Iterations; i++)
        {
            list[i] = new PointClass(i, i);
        }
        return true;
    }

    protected override bool MeasureTestC()
    {
        // access array elements
        var list = new PointStruct[Iterations];
        for (int i = 0; i < Iterations; i++)
        {
            list[i] = new PointStruct(i, i);
        }
        return true;
    }
}

有一个PointClass和一个 PointStruct ,这两者用于存放X 和Y 两个变量,而且还有一个 PointClassFinalized

方法 MeasureTestA 创建了100万个 PointClassFinalized 实例

方法 MeasureTestB 创建了100万个 PointClass 实例

方法 MeasureTestC 创建了100万个 PointStruct 实例

您认为哪种方法最快?

MeasureTestBMeasureTestC 这两个方法的唯一不同在于一个是创建类 一个是创建结构。

MeasureTestC 仅在17毫秒内完成分配并运行,比 MeasureTestB 方法快8.6倍!

为什么会出现这样的事情,这里发生了什么?

不同的在于结构和类如何存储在内存中。

下面是 PointClass 实例 内存布局:

该列表是一个局部变量,存放在堆栈中。引用堆上的一组 PointClass实例

PointClass 是一个引用类型,存放在堆上。

该列表仅维护一个数组,指向存储在堆上 PointClass 实例。

观察到上图的黄色箭头,在堆上引用了很多实例。

数组是一组相同的对象,MeasureTestB 这个方法是将一组相同的对象存放在数组中。

当访问指定数组元素时,.NET运行时需要检索对象引用,然后“跟随”引用以获取PointClass实例。

当数组元素超出范围时,.NET垃圾收集器就会开始回收PointClass对象内存,在 MeasureTestA 方法中 的PointClassFinalized类 其实增加了额外时间。

.NET Framework在单个线程上运行所有终结器,线程必须在垃圾回收器可以回收内存之前依次处理1,000,000个对象。

可以看到MeasureTestAMeasureTestB慢1.7倍。

我们来看看 PointStruct 的内存布局:

结构是值类型,所有 PointStruct 实例都存储在数组本身中。堆上只有一个对象。

初始化数组,.NET运行库可以将X和Y值直接写入数组里。无需在堆上创建新对象,也不需要引用它。

当访问指定数组元素时,.NET运行时可以直接检索结构。

当超出范围时,.NET垃圾回收器只需要处理单个对象。

总结

我们总要使用结构吗?要分情况看:

  • 当您存储超过30-40个字节的数据时,请使用类。
  • 存储引用类型时,请使用类。
  • 当您存储多于几千个实例时,请使用类。
  • 如果列表是长的生命周期的,请使用类。
  • 在所有其他情况下,使用结构。

相关链接:

作者:androllen

出处:https://www.cnblogs.com/luquanmingren/p/11263161.html

本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。

本文分享自微信公众号 - DotNet程序园(dotnetblog)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 上车时机已到--.NETCore是适应时代发展的雄鹰利剑

    随着 .NET Core 3.0-prevew7 的发布,开源社区的一支重要力量重要即将起飞;官方指出,该预览版为可能为最终版本,在很长一段时间内,.NETCo...

    梁规晓
  • Orleans 知多少 | 2. 核心概念一览

    上面已经提到,Grain是Virtual Actor的具体表现。那如何理解Grain呢。

    Edison.Ma
  • 【译】宣告推出.NET Core 3.0 Preview 7(英雄的黎明)

    今天,我们宣布推出.NET Core 3.0 Preview 7。我们已经从创建新特性阶段过渡到了完善版本阶段。对于接下来的预览版,我们将把重点放在质量(改进)...

    Edison.Ma
  • 浅谈.Net反射 11

    浅谈.Net反射系列基本来到了尾声,本文主要从.Net Framework的源码角度去分析:

    小蜜蜂
  • ASP.NET Core 中的管道机制

    在开始之前,我们需要明确的一个概念是,在 Web 程序中,用户的每次请求流程都是线性的,放在 ASP.NET Core 程序中,都会对应一个 请求管道(requ...

    Edison.Ma
  • 数组(ArrayPool数组池、Span<T>结构)

      如果需要使用相同的类型的多个对象,就可以使用集合和数组,这一节主要讲解数组,其中会重点涉及到Span<T>结构和ArrayPool数组池。我们也会先涉及到简...

    小世界的野孩子
  • 浅谈.Net反射 3

    在.NET中,提供了System.Type类和System.Reflection命名空间实现了反射的功能。

    小蜜蜂
  • 云服务模型:控制与规模经济的博弈

    感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学...

    ayqy贾杰
  • 构建可读性更高的 ASP.NET Core 路由

      不知你在平时上网时有没有注意到,绝大多数网站的 URL 地址都是小写的英文字母,而我们使用 .NET/.NET Core MVC 开发的项目,因为在 C# ...

    程序员宇说
  • 一种小型后台管理系统通用开发框架中的Cache缓存设计

    本篇博客记录一下我在实习的公司的后台管理系统开发框架中学习到的一种关于网站的缓存(Cache)的实现方法,我会在弄懂的基础上,将该方法在.net core上进行...

    CherishTheYouth

扫码关注云+社区

领取腾讯云代金券