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 实例
您认为哪种方法最快?

MeasureTestB 和 MeasureTestC 这两个方法的唯一不同在于一个是创建类 一个是创建结构。
MeasureTestC 仅在17毫秒内完成分配并运行,比 MeasureTestB 方法快8.6倍!
为什么会出现这样的事情,这里发生了什么?
不同的在于结构和类如何存储在内存中。
下面是 PointClass 实例 内存布局:

该列表是一个局部变量,存放在堆栈中。引用堆上的一组 PointClass实例
PointClass 是一个引用类型,存放在堆上。
该列表仅维护一个数组,指向存储在堆上 PointClass 实例。
观察到上图的黄色箭头,在堆上引用了很多实例。
数组是一组相同的对象,MeasureTestB 这个方法是将一组相同的对象存放在数组中。
当访问指定数组元素时,.NET运行时需要检索对象引用,然后“跟随”引用以获取PointClass实例。
当数组元素超出范围时,.NET垃圾收集器就会开始回收PointClass对象内存,在 MeasureTestA 方法中 的PointClassFinalized类 其实增加了额外时间。
.NET Framework在单个线程上运行所有终结器,线程必须在垃圾回收器可以回收内存之前依次处理1,000,000个对象。
可以看到MeasureTestA比MeasureTestB慢1.7倍。
我们来看看 PointStruct 的内存布局:

结构是值类型,所有 PointStruct 实例都存储在数组本身中。堆上只有一个对象。
初始化数组,.NET运行库可以将X和Y值直接写入数组里。无需在堆上创建新对象,也不需要引用它。
当访问指定数组元素时,.NET运行时可以直接检索结构。
当超出范围时,.NET垃圾回收器只需要处理单个对象。
总结
我们总要使用结构吗?要分情况看:
- 当您存储超过30-40个字节的数据时,请使用类。
- 存储引用类型时,请使用类。
- 当您存储多于几千个实例时,请使用类。
- 如果列表是长的生命周期的,请使用类。
- 在所有其他情况下,使用结构。
相关链接:
C#中谁最快:结构还是类?的更多相关文章
- .net(C#)中结构和类的区别
static void Main(string[] args) { //类型 //结构:值类型 //类:引用类型 //声明的语法:class struct //在类中,构造函数里,既可以给字段赋值,也 ...
- C#中结构与类的区别
一.类与结构的示例比较: 结构示例: public struct Person { string Name; int height; int weight public bool overWeight ...
- .NET中结构和类的区别
最近在学习Swift语言,看到了枚举这一章,Swift可以支持在枚举中定义方法...于是想到了回顾一下.NET中枚举.结构.类之间区别. 枚举在.NET较为简单,这里就不作比较,只谈谈结构和类. 1. ...
- C++中结构和类的区别
首先从从语言角度来看,c语言是一种结构化的语言,便于按照模块化的方式来组织程序,易于程序员的调试和维护,而对于c++来说,我么可以认为它是标准c的超集.实际上所有的c程序也是c++程序.但两者之间还是 ...
- 如何使用CSS3中的结构伪类选择器和伪元素选择器
结构伪类选择器介绍 结构伪类选择器是用来处理一些特殊的效果. 结构伪类选择器属性说明表 属性 描述 E:first-child 匹配E元素的第一个子元素. E:last-child 匹配E元素的最后一 ...
- [AI开发]视频结构化类应用的局限性
算法不是通用的,基于深度学习的应用系统不但做不到通用,即使对于同一类业务场景,还需要为每个场景做定制.特殊处理,这样才能有可能到达实用标准.这种局限性在计算机视觉领域的应用中表现得尤其突出,本文介绍基 ...
- 5.Swift枚举|结构体|类|属性|方法|下标脚本|继承
1. 枚举: ->在Swift中依然适用整数来标示枚举值,需搭配case关键字 enum Celebrity{ case DongXie,XiDu,Nandi,BeiGai } // 从左 ...
- CSS3 结构伪类选择器 详解
1 CSS3 结构伪类选择器 1.E:root 匹配E元素所在的根元素 即:html 2. E:nth-child(n) (1)匹配E元素的父元素中第n个子元素,(2)且该位置的子元素类型必须是E类型 ...
- Atitit java的异常exception 结构Throwable类
Atitit java的异常exception 结构Throwable类 1.1. Throwable类 2.StackTrace栈轨迹1 1.2. 3.cause因由1 1.3. 4.Suppres ...
随机推荐
- 区块狗开发可以做出APP吗
区块狗系统开发林生▉l8l加4896微9698电同步▉,区块狗奖励系统开发,区块狗平台系统开发,区块狗系统开发软件,区块狗系统开发案例,区块狗源码系统开发. 本公司是软件开发公司,华登区块狗/十二生肖 ...
- Laravel --- 要点笔记
一.路由: // 常规用法 Route::get('/',function(){ return 'get'; }) // 匹配多个 Route::match(['get','post'],'/',fu ...
- Python自学day-11
一.RabbitMQ概述 RabbitMQ是一种消息队列,是一个公共的消息中间件,用于不同进程之间的通讯. 除了RabbitMQ以外,还有ZeroMQ.ActiveMQ等等. 前面学习了两种队列: 线 ...
- 浅谈IHttpHandler
在Web应用开发或接口开发时,处理请求接口IHttpHandler随处可见,那么我们这次来简单聊一下这个接口. ASP.NET响应Http请求时常用的两个处理接口,分别是IHttpHandler和IH ...
- 中转Webshell 绕过安全狗(一)
前言 听说中国菜刀里有后门.抓包我是没有监测到异常数据包.为了以防万一,且更好使用中国菜刀硬杠安全狗.笔者收集了一下资料.无耻的copy大佬的源码,只是在大佬的基础上简单修改了一下,达到Webshel ...
- 用ASP.NET Core重写了一款网络考试培训的免费软件
在IT圈混迹了近十年,今已正当而立之年却仍一事无成,心中倍感惶恐惭愧.面对竟争如此激列的环境,该如何应对?却也知不能让自已闲着,得转起来,动起来.于是,便想着利用最新技术栈将自已原来的收费产品重写一次 ...
- C# 连接数据库等
SqlConnection连接池:可以通过连接字符串配置连接池.对象池技术:HttpApplication :Asp.Net生产者 消费者. 线程.应用程序跟数据连接非常耗时,而且连接使用非常频繁,使 ...
- MySQL索引的数据结构-B+树介绍
目录 一.树 二.B+树 2.1 B+树性质 三.聚集索引和辅助索引 3.1 聚集索引 3.2 辅助索引 3.3 聚集索引和非聚集索引的区别 四.再看B+树 4.1 B+树的插入操作 4.2 B+树的 ...
- mysql双机热备实现方案
一.概念 1.热备份和备份的区别 热备份指的是:High Available(HA)即高可用,而备份指的是Backup,数据备份的一种.这是两种不同的概念,应对的产品也是两种功能上完全不同的产品.热备 ...
- 1.为什么会有Servlet?它解决了什么问题?
1. 为什么会出现Servlet? 因为web服务器(tomcat.Weblogic.iis.apache)没有处理动态资源请求的能力(即该请求需要计算),只能处理静态资源的请求(如果浏览器请求某个h ...