C# 程序性能提升篇-2、类型(字段类型、class和struct)的错误定义所影响性能浅析
前景提要:
编写程序时,也许你不经意间,就不知不觉的定义了错误的类型,从而发生了额外的性能消耗,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环、网络程序(不断请求处理的)等这些时候,减少了不必要额外的消耗,使优化程序提高效率的一种途径。不仅跬步,无以至千里,不积小流,无以至江河。优化从点点滴滴做起。
一、问题抛出:
大家先看这么一段定义
class ReserveData
{
public string ReserveId;
public string patient_id;
public string patient_name;
public string queue_type_id;
public string source_code;
public string IsCall;
public string date;
public string start_time;
public string end_time;
public string reserve_timespan_id;
}
这是真实的摘自同事代码,先不说命名规则,Pascal、骆驼命名,(其中我们自己定义来自数据库使用骆驼,自定义变量使用Pascal)
这段代码主要用途是向前台页面序列化ReserveData的List的json。
以前我从没感觉类型定义会是什么问题,这个谁会出什么问题呢,可是有人真的就这么干,最后还不以为然。
二、问题解析一——字段类型定义
在您这么定义的时候,您觉得可能这样定义并没有什么,甚至会说:“我都工作,两三年了,别对我指手画脚的”。
一共工作过两家公司,均有一些工作两三年的同事,这样使用。偶的神啊!
2.1 不同层面分析
2.1.1 从程序员角度理解
从程序员角度,我真的理解不了,你要表达的意思,明明是bool,一个true,false的意思,你变成string,datetime,也定义成string。 我去问他们,来了一句,“那怎么了,又不影响使用,你别纠结这些问题了,想想流程”。我不知该说什么。
2.1.2 从机器CLR去理解
确实,我够智能,你怎么着,我都给你正常编译、执行,但是正常干活已经够累的了,怎么还给我找事,告诉你,消耗cpu,内存过多,我就给你宕机去。
2.1.3 实际使用中的我
苦逼的我在前台js接收json时,针对bool怎么也是解析不出来,各种怪现象,看了源代码,有种想抽她的冲动,bool类型返回的是string类型的“True”,int32返回的也变成string类型数值,datetime类型也不是预想中的毫秒值,变成了string(2014/05/30 09:00:00),你说我能不抽她吗??
2.1.4 性能分析
现在咱们,就分析一下这段类型定义。
在这其中 ReserveId 其实是 int32
IsCall 其实是 bool
start_time、end_time 其实是 Datetime
patient_name 是 String 其他的也可能有别的类型,
这里主要指出的不按真实情况,定义应有的类型,接收应有的数据,而自以为事的胡乱定义。第一、原本是值类型的,如果您定义成了string引用类型,可能造成不必要的装箱,性能损失。(补充一句,谢谢网友“ 冰麟轻武”提醒,这里使用类接收或者承载数据库数据之后,需要对其进行操作的,string 类型的Datetime,需要使用类型装换,同时还有一些其他的操作,“可能”会造成装箱,拆箱。可能使用Convert、(Int)强转、int.Parse()等类似 值类型→引用类型,引用类型→值类型) 第二、原本是引用类型的,如果您定义成了Int32、Boolean等值类型,可能直接就会有语法错误。第三,增加程序员之间的配合难度。以及会是程序中出现各种怪问题。
装箱是很消耗性能的一种操作,这里不再详述:可参看:C# 程序性能提升篇-1、装箱和拆箱,枚举的ToString浅析
实际事例:像这种List<ReserveData>,可能会有多条,每次都会进行装箱,就按本例使用示例分析一下性能问题(以实际现状分析,本人从事医疗辅助软件开发)
(说明一下,一般医院给这种医疗辅助软件的服务器,就那么一台(四核八线程,4G内存),更有可能者,只给你一个虚拟机。web和DB在一台服务器,这还不止一个医疗辅助软件系统,还有其他的多媒体展示,或者其他医院系统)
示例:某医院有一百个终端屏幕(小医院的点数,大医院会上千),其实就是请求客户端。每个终端屏幕每隔60s请求一次(这一般是最小的),甚至有的医院要求5s刷新,每次列表有10个患者。ok,这是实际情景
咱们数学计算一下,预定义量,假设每次装箱耗时1ms、内存消耗1k,cpu使用0.001%
(以上使用10个字段,8个可能发生装箱,每次list按10个计算)
粗略计算一下100个同时请求的即时消耗
时间 100个屏幕*10个患者*8个装箱字段*1s时间*1ms额外消耗==8000ms =8s
内存 100个屏幕*10个患者*8个装箱字段*1s时间*1K 额外消耗==8000K =8M
CPU 100个屏幕*10个患者*8个装箱字段*1s时间*0.001%额外消耗==8%
这还仅仅是系统中的一角,如果有更多的这种额外消耗,那么程序就死定了
综上所述,额外消耗(可能所有的基数并不准确,但是消耗是一定的,你懒了,机器多干活了,必然会有多的消耗(能量守恒定律码)),只不过是微乎其微的消耗;
桌面程序,请求数少,可以忽略不计;
局域网程序,像我们这种,频繁多请求,在服务器cpu、内存控制下,就得考虑额外消耗;
互联网则更需要考虑,轻则上千,重则千万级别,再深了更别说了。这种额外的消耗(完全可以避免的消耗),并不在正常消耗之内的消耗,可能就是造成您的cpu,内存,居高不小的主要原因。
三、问题解析二——class和struct
3.1概念简述
3.1.1 不用多说,class 是引用类型,struct是值类型
3.1.2 补充一句,引用类型开辟内存栈指针,内存堆存放数据,具体内存等资源释放由CLR的GC处理,偏重型; 值类型,存放于内存栈中,在作用域结束释放,轻型
3.1.3 class与struct差不多一样,struct 是C、C++旧时代的产物,class才是王道,才是面向对象中使用的。C#中之所以有struct 是为了兼容C、C++程序员才过度的产物。估计很多您search过,都是这个答案吧。回忆,看过的教程、百度、google,博客园,甚至曾经的自己,都是这种想法。
3.2什么时候使用类、什么时候使用struct
google一下就很多了,不在深入抄袭,但是看到以上类似3.1.3的话您就别看了,我给您补充一下:
1.对于轻量级的数据组,类似上面的就是一些字段、属性的序列化,没有进一步抽象,继承的需求可以考虑使用Struct;
2.struct 类型是一种值类型,通常用来封装小型相关变量组(MSDN:http://msdn.microsoft.com/zh-cn/library/ah19swz4.aspx)
3..结构用于封装由相关字段组成的组。因为结构是值类型,所以它们的分配效率要比类略高些(来自MSDN:http://msdn.microsoft.com/zh-cn/library/ms228600(v=vs.90).aspx)
4.结构还可以包含构造函数、常量、字段、方法、属性、索引器、运算符、事件和嵌套类型,但如果同时需要上述几种成员,则应当考虑改为使用类作为类型(MSDN:http://msdn.microsoft.com/zh-cn/library/ah19swz4.aspx)
5.类是反映现实事物的一种抽象,而结构体的作用只是一种包含了具体不同类别数据的一种包装,结构体不具备类的继承多态特性 综上所述,您也知道了吧,还是那句话,什么时候什么场景该用什么类型就要用什么类型。
小结:
1.字段类型的定义,一定要符合实际,不要随便胡乱定义。要不然可能造成的后果,别人不理解您的程序,机器损失巨大性能。
2.class,struct,合适场景用合适的定义,不经意间提升你程序的性能。
3.程序进步、优雅,技能同时也会再进步,难道money还会少吗??
C# 程序性能提升篇-2、类型(字段类型、class和struct)的错误定义所影响性能浅析的更多相关文章
- C# 程序性能提升篇-1、装箱和拆箱,枚举的ToString浅析
前景提要: 编写程序时,也许你不经意间,就不知不觉的使程序代码,发生了装箱和拆箱,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环.网络程序(不断请求处理的)等这些时候,减少装箱和拆 ...
- Android中SQLite查询date类型字段出现有返回但是为错误值的情况
出现该情况的原因是因为查询精度与数据库中存储精度不相同造成的,例如,查询精度为 YYYY-MM-DD 但是存储精度为 YYYY-MM-DD HH:MM:SS,就会出现该错误. 更改查询精度为YYYY- ...
- 【mysql的设计与优化专题(3)】字段类型与合理的选择字段类型
本篇博客稍微有点长,它实际上包括两个内容:一是mysql字段类型的介绍,二是在mysql建表过程中是如何正确选择这些字段类型; 字段类型 数值 MySQL 的数值数据类型可以大致划分为两个类别,一个是 ...
- mysql数据库字段类型的选择原则
原文链接:http://blog.csdn.net/u013412790/article/details/51615407 数据库类型的选择对数据库的性能影响很大 1 . 数据类型会影响存储空间的开销 ...
- ORACLE插入DATE类型字段
1 怎样在ORACLE中输入DATE类型的字段 insert into table_name (date_column) values(to_date('2006-06-04','yyyy-mm-dd ...
- SolidWorks 2020新增功能之性能提升
SolidWorks解决方案组合的新功能和增强功能将帮助您最大程度地提高设计和制造资源的生产率,同时使您能够更快地交付创新产品.现在我们很激动地告诉你,三维设计SolidWorks 3D CAD 2 ...
- Solr字段类型field type的定义
摘要: Solr的字段类型定义了Solr如何解析字段数据并将数据检索出来,了解Solr的字段类型定义有助于更好的配置与使用Solr. 字段类型的定义 字段类型的定义主要包含如下四个方面的信息: 名称 ...
- mysql配置与存储引擎与字段类型与约束条件
目录 字符编码与配置文件 存储引擎 创建表的完整语法 字段类型 整型 浮点型 字符类型 数字的含义 枚举与集合 日期类型 约束条件 字符编码与配置文件 在MySQL5.X系列中,显示的字符编码有多种, ...
- 1.4.2 solr字段类型--(1.4.2.6)使用外部文件和程序
1.4.2 solr字段类型 (1.4.2.1) 字段类型定义和字段类型属性. (1.4.2.2) solr附带的字段类型 (1.4.2.3) 使用货币和汇率 (1.4.2.4) 使用Dates(日期 ...
随机推荐
- The breakpoint will not currently be hit. vs2005断点不被命中
用会了vs2005但是发现坑爹的连断点都不会命中,原来是默认设置的问题.要使断点命中: 1. 首先确保程序是在DEBUG模式下运行: 2. 确认正确的项目设置:链接器->调试->生成调试信 ...
- 织梦CMS后台卡死的解决办法
[复制来于网上]原文地址:http://www.sjyhome.com/dedecms-6.html 改过一次第二次忘记怎么改,还是转一下,下次忘记了翻翻文章就可以知道了.好记忆不如烂笔头 一.原因分 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(28)-系统小结
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(28)-系统小结 我们从第一节搭建框架开始直到二十七节,权限管理已经告一段落,相信很多有跟上来的园友,已经 ...
- 遍历datatable的几种方法【转载】
遍历datatable的方法2009-- :02方法一: DataTable dt = dataSet.Tables[]; ; i < dt.Rows.Count ; i++) { string ...
- Swift --- 面向对象中类和对象的属性
Swift中类和对象的属性分为三种:储存属性,计算属性和类属性. import Foundation class Person { // 储存属性必须赋初值 var score1: Int = 20 ...
- IntelliJ Idea 常用快捷键列表(精简版)
查找快捷键: Ctrl+N 查找类 Ctrl+shift+N 查找文件 Ctrl+B 找变量来源 Ctrl+E 最近打开的文件 Ctrl+Alt+B 选中方法的实现 Ctrl+F7 选中方法(属性. ...
- Java——(五)Collection之List集合、ArrayList和Vector实现类
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.List集合 List集合代表一个元素有序.客重复的集合,集合中每个元素都有其对应的顺序索引 ...
- ArcEngine:栅格分级渲染
ArcEngine对矢量数据进行风格化实在是得心应手,同样的对于栅格图像也能进行风格化!以前没接触过,今天正好需要,做出了栅格图像的渲染!下面实现的思路: 1.定义渲染的一系列接口 2.判断图像是否建 ...
- 利用switch语句进行多选一判断。
<!doctype html> <meta http-equiv="content-type" content="text/html" cha ...
- 过滤掉html 标签
/// <summary> /// 过滤掉html标签 /// </summary> /// <param name="Htmlstring"> ...