关于STRUCT优化的一个点
在西山居的这篇U3D cheatsheet中,提到: c12. 确保 struct 实现了 Equals() 和 GetHashCode()
这怎么理解?
首先,看下system.object.equals和 ReferenceEquals的实现:
public static bool ReferenceEquals (object objA, object objB)
{
return objA == objB;//这就说明 了==比较的是引用
}
public virtual bool Equals (object obj)
{
return object.InternalEquals (this, obj);
}
如果是引用类型,比较时只需比较两个引用的值(地址,指针)是否相等即可。
对于值类型的结构体,将发生由值到object的装箱操作,生成两个堆对象,地址分别存放在objA,objB中,objA==objB 必定不成立,因为没有任何两个结构体的内存地址会相同,那么它就进行InteranlEquals 的比较,这个比较是在DLL中写的,看不到源码,
通过对结构体进行1000000次equals测试发现,结构体中类型越多,越复杂,则equals越慢,而引用类型则不会这样。
测试及结论如下:
class Program
{
#region 结构体内存分配测试
struct ST
{
public float fx;
//public string name;
int ix;
double[] adx; public ST(float afx, string aName)
{
fx = afx;
//name = "10"; // "hello,world, 你好吗,!@#($)%%@$";
ix = ;
adx = new double[ix];
for(int i=; i< ix; ++i)
{
adx[i] = i * i;
}
}
}
class CX
{
public float fx;
string name = "hello,world, 你好吗,!@#($)%%@$";
string name2 = "11111122334dfasdfd";
string name3 = "xhello,world, dssccccc$aa$";
double[] adx = new double[]; }
static void testStructMem()
{
ST ot = new ST();
ST ot2 = new ST(); var st = Stopwatch.StartNew();
var t1 = st.ElapsedMilliseconds;
for(int i=; i<; ++i)
{
var eq = ot.Equals(ot2);
}
var t2 = st.ElapsedMilliseconds; //616ms,随着类的复杂度而上升,字符串类型,数组类型最消耗
//且,一个元素的数组与10000个元素的数组几乎没有区别,这说明消耗在类型而不在数据长度
//由此,可以判定,在进行结构体类型的比较时,是遍历结构内的所有成员,对每个成员先判断其类型,再进行哈希值比较
//为什么要先判类型?只比较字节码不行吗?显然不行,对相同的字节码作不同类型的解释得到的是不一样的结果
Console.WriteLine(t2 - t1); //616ms var oc = new CX();
var oc2 = new CX();
var st2 = Stopwatch.StartNew();
st2.Start();
var t11 = st2.ElapsedMilliseconds;
for(int i=; i<; ++i)
{
var eq = oc.Equals(oc2);
}
var t12 = st2.ElapsedMilliseconds;
Console.WriteLine(t12 - t11);//5ms,与类的复杂度无关,这说明比较的是引用(地址)
}
#endregion
关于STRUCT优化的一个点的更多相关文章
- VS编译器优化诱发一个的Bug
VS编译器优化诱发一个的Bug Bug的背景 我正在把某个C++下的驱动程序移植到C下,前几天发生了一个比较诡异的问题. 驱动程序有一个bug,但是这个bug只能 Win32 Release 版本下的 ...
- 一步步做程序优化-讲一个用于OpenACC优化的程序(转载)
一步步做程序优化[1]讲一个用于OpenACC优化的程序 分析下A,B,C为三个矩阵,A为m*n维,B为n*k维,C为m*k维,用A和B来计算C,计算方法是:C = alpha*A*B + beta* ...
- 重度使用示波器进行优化分析——一个DSDA项目回顾
这是若干年前一个项目,最近有时间整理一下.回忆起来,印象最深刻的就是重度使用示波器辅助分析,进行优化. 项目背景是在原有项目3G+项目基础上,增加一颗2G+ Modem,使支持DSDA功能. 在介绍D ...
- 重度使用示波器进行优化分析——一个DSDA项目回顾
这是若干年前一个项目,最近有时间整理一下.回忆起来,印象最深刻的就是重度使用示波器辅助分析,进行优化. 项目背景是在原有项目3G+项目基础上,增加一颗2G+ Modem,使支持DSDA功能. 在介绍D ...
- struct 模块 把一个类型,如数字,转成固定长度的bytes
该模块可以把一个类型,如数字,转成固定长度的bytes import struct headers=struct.pack('i',132333) print(headers,len(headers) ...
- 整型转字符串(convert int to char)优化实践——一个意外的BUG
convert_int_to_char函数在使用时出现过一个BUG. 当使用值是13200020099时,返回的字符串是"13200020111",结果是错误的. 在gcc编译器里 ...
- 简单聊聊TiDB中sql优化的一个规则---左连接消除(Left Out Join Elimination)
我们看看 TiDB 一段代码的实现 --- 左外连接(Left Out Join)的消除; select 的优化一般是这样的过程: 在逻辑执行计划的优化阶段, 会有很多关系代数的规则, 需要将逻辑执行 ...
- 转PostgreSQL 用游标优化的一个例子
一位PG社区的朋友提到的一个应用场景,目前遇到性能问题. 数据结构大概是这样的,包含一个主键,一个数组,一个时间,其他字段. 请求分析: 有检索需求,比较频繁.查找数组中包含某些元素的记录,并按时间排 ...
- 关于SQL语句优化的一个问题
今天写了一个很简单的存储过程,结果一执行,40多秒,后来调整了一句话写法,瞬间出来,其实差别不大,如下: select item_no=vpc.ITEM_ID ,BL_QTY=sum(vpc.QTY_ ...
随机推荐
- Android-PullToRefresh 下拉刷新增加setOnItemLongClickListener
项目地址:https://github.com/chrisbanes/Android-PullToRefresh 不知道为什么这个项目没有给listview 加 OnItemLongClickLis ...
- Unreal Engine 4 动态切割模型实现
转自:http://gad.qq.com/article/detail/33199 <合金装备:复仇>里面,有一个很有趣的设定,游戏里大部分的场景和物件都可以用主角的刀动态切割. UE4中 ...
- 安装MySQL_Python时出现is not a supported wheel on this platform.
MySQL-Python 数据库驱动安装 pip install mysql_python失败 不支持windows操作系统 解决: 自行下载安装 下载网站 http://www.lfd.uci.ed ...
- Linux线程池的实现
线程池的实现 1:自定义封装的条件变量 //condition.h #ifndef _CONDITION_H_ #define _CONDITION_H_ #include <pthread.h ...
- requests模块报错:Use body.encode('utf-8') if you want to send it encoded in UTF-8.
在做 企业向微信用户个人付款 功能时,调用第三方sdk,在 进行 requests 的post请求时, 代码如下 req = requests.post(url, data=data,cert(ap ...
- org.springframework.boot.builder.SpringApplicationBuilder.<init>
新建了一个Spring cloud项目,启动时报错org.springframework.boot.builder.SpringApplicationBuilder.<init> 翻阅资料 ...
- day15(模块引用笔记)
import spam文件名是spam.py,模块名则是spam# 首次导入模块发生?件事# 1. 会产生一个模块的名称空间# 2. 执行文件spam.py,将执行过程中产生的名字都放到模块的名称空间 ...
- vscode 正则 计算代码全部有效行数;清除文件空行
清除空行: 正则表达式:^\s*(?=\r?$)\n 计算全部代码行数: 正则表达式:b*[^:b#/]+.*
- Java Swing类 例子代码:将子类继承JFrame 并且接口按键监听ActionLisetener (将内容直接添加到JFrame不创建Contaniner)
package rom; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import ...
- 5、申请开发(Development)描述文件
申请开发(Development)描述文件 在“Certificates, Identifiers & Profiles”页面“Provisioning Profiles”下选择“Develo ...