欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-26 17:46:39
前言 在内存当道的日子里,无论什么时候都要考虑这些代码是否会影响程序性能呢? 在现在的世界里,几乎不会去考虑用了几百毫秒,可是在特别的场景了,往往这几百毫米确影响了整个项目的快慢。 通过了解这两者之间的性能差异,希望帮助大家在合适的场景里选择正确的编码。 实例 c public class Poin ......

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

前言

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

实例

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 实例

您认为哪种方法最快?

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

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

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

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

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

下面是 pointclass 实例 内存布局:

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

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

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

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

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

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

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

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

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

可以看到measuretestameasuretestb慢1.7倍。

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

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

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

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

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

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

总结

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

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

相关链接:

上一篇:

下一篇: