C#性能理解以及CTS

简介:

关于C#/.NET性能

在上次的例子里面,第二次执行Console.WriteLine()方法时,会完全跳过JITCompiler编译。因为第一次已经完全编译为了本地CPU指令并且返回了指令在内容里的入口地址,所以这一次会直接跳转到该方法的内存地址处执行代码,当然也会比第一次的性能要高。

C#性能较之C/C++低在哪?

在托管环境中,完成代码的编译会经历两个过程:

1.源码首先被编译为IL代码

2.执行代码时,IL会经历第二次编译为本地CPU指令,这个过程需要分配更多的内存和占用CPU资源。

怎么客观地看待这个部分?

1.首先必须承认二次编译的确损害了性能,并且分配了动态内存。分配动态内存意味着当程序终止时,编译的代码会被丢弃。再次运行程序或启动两个程序的实例,JIT编译器会再次将IL编译为本地CPU指令。非托管语言(C/C++)编译器会针对具体的CPU平台编译,调用时直接执行。

2.对大多数程序而言,都会反复多次调用同一个方法。这些方法仅仅在第一次被调用时会进行二次编译,从而降低了性能。其实,可能有时在一个方法里面执行的时间比调用一个方法的时间长的多,所以即使是第一次调用需要消耗性能,可能相对于在整个方法执行的时间来说只是占用了一小部分比例。

3.微软做了很多优化的工作来保证将性能的损耗降到最低。例如,在IL编译为本地CPU指令时,编译器能够比非托管编译器知道更多关于执行环境的信息。下面列举托管编译器胜过非托管编译器的几个方面:

①JIT编译器能够判定程序是否运行在Intel Pentium 4 CPU上,并且利用Pentium 4CPU提供的任何专用的指令的优势来生成本地CPU指令。通常,非托管程序会针对最普遍CPU情况编译,从而避免使用CPU提供的专用指令来提升性能。

②JIT编译器能够确定当一个测试在机器上运行时始终为false的情形。例如:if(numberOfCPUs>1){...}.如果宿主机器只有一个CPU,那么这段代码能够让JIT编译器不生成任何CPU指令。这种情形能够让本地CPU指令得到一些微调,从而让代码更小执行更快。

认识IL

IL是基于栈的,所有IL指令通过push操作到执行栈,并且通过pop操作将结果出栈。由于IL没有提供操作寄存器的指令,很容易让人们创造出针对CLR的语言和编译器。IL指令也是无类型的。例如,IL提供的Add指令(将最后两个操作push到栈)并没有两个针对32位和64位的Add指令。当Add指令执行时,它会决定栈上操作的类型并执行适合的操作。

IL的优点

1.从底层的CPU抽象出来

2.健壮性和安全性:IL编译为本地CPU指令时,CLR执行了一个审核过程,检查高级IL代码确保它们是安全的,例如方法被调用时,参数的个数和类型是否正确;如果有返回值,那么检查方法是否有return语句等等。托管模块的元数据包含了审核过程需要的所有方法和类型信息。在Windows中,每一个进程有它自己的虚拟地址空间,这很有必要,因为你不能信任一个程序的代码。程序完全有可能从一个未验证的内存地址读取或写入,放到独立的地址空间增强了程序的健壮性和稳定性。而且这样可以在一个Windows虚拟地址空间运行多个托管程序。

3.由于进程会占用Windows的资源,进程越多占用的越多。多个托管程序可以运行在一个操作系统进程从而提升了性能。

CLR怎么实现在一个进程运行多个托管程序?

每一个托管程序在一个应用程序域执行。默认情况下,每一个托管的exe文件运行具有一个应用程序域的独立地址空间,CLR的宿主进程能够运行多个应用程序域。

了解不安全代码

微软C#编译器默认生成的是安全代码——代码是经过安全审核的。C#编译器也允许开发这写不安全的代码——直接操作内存地址以及在内存中的字节。这个功能在我们与非托管代码交互时非常有用。所有方法在包含不安全代码时,必须标记unsafe。当JIT编译器试图编译一段不安全代码时,它会检查该代码是否通过设置System.Security.Permissions.SecurityPermissionFlag’s SkipVerification标志授权。如果设置了该标志位,CLR会信任该段代码并期望直接地址和字节操作不会引起任何损害。如果没有设置会抛异常。

认识公共类型系统CTS

1.CTS:描述类型的定义及行为。

2.CTS规范声明了一个类型能够包含0个或多个成员:字段,方法,属性,事件。

3.CTS也规定类型及其成员的可访问性,下面列举出来:

Private:同一个类里面可以访问

Family:能够被派生类里面的成员访问,而不用考虑是否在同一个程序集里里面。C#里面用Protected修饰

Family and assembly:能够被在同一个程序集里面的派生类成员访问。C#及VB没有提供该访问控制修饰,IL汇编语言是可以的。

Assembly:同一个程序集可以访问。C#里面用internal修饰

Family or assembly:能够被派生类访问(不管是否在同一个程序集),也能够被同一个程序集的任何类型访问(不用考虑是否是派生类)。C#用protected internal修饰

public:没有限制。

4.CTS定义了类型继承的规则,虚方法,对象生命周期等等。

5.CTS规定所有类型必须从System.Object继承。Object是定义在System命名空间下的,是所有类型的根,这样可以保证所有的类型具有一个最小化的行为集合。System.Object定义下面几种行为:①两个实例的比较   ②获取实例的哈希代码   ③查询实例的真实类型   ④执行类型的浅复制  ⑤获取实例对象当前状态的字符串表示

注   《CLR via C#》(Jeffrey Richter著)——.NET 界的经典之作,读的过程写点笔记跟大家分享,我也推荐大家看英文版,能够直接领会原意 

本文转自Rt-张雪飞博客园博客,原文链接http://www.cnblogs.com/mszhangxuefei/archive/2012/07/10/clrnotes-2.html如需转载请自行联系原作者


张雪飞

相关文章
|
1月前
|
C#
24. C# 编程:用户设定敌人初始血值的实现
24. C# 编程:用户设定敌人初始血值的实现
18 0
|
2月前
|
SQL 数据库连接 应用服务中间件
C#WinForm基础编程(三)
C#WinForm基础编程
71 0
|
2月前
C#WinForm基础编程(二)
C#WinForm基础编程
55 0
|
2月前
|
C# 数据安全/隐私保护
C#WinForm基础编程(一)
C#WinForm基础编程
59 0
|
4月前
|
数据采集 前端开发 C#
C#编程艺术:Fizzler库助您高效爬取www.twitter.com音频
Twitter是全球最大的社交媒体平台之一,包含丰富的音频资源。用户可以在Twitter上发布、转发、评论和收听各种音频内容,如音乐、播客、新闻、故事等,直接从Twitter抓取音频数据并非易事,尤其是在考虑到可能的封锁和反爬虫机制。Twitter会对频繁访问的IP地址进行限制或封禁,以防止恶意爬虫的行为。因此,我们需要使用一些技术手段来规避这些障碍,确保稳定而高效的数据访问。
C#编程艺术:Fizzler库助您高效爬取www.twitter.com音频
|
3月前
|
程序员 C#
深入理解 C# 编程:枚举、文件处理、异常处理和数字相加
枚举是一个特殊的“类”,表示一组常量(不可更改/只读变量)。 要创建枚举,请使用 enum 关键字(而不是 class 或 interface),并用逗号分隔枚举项:
37 0
|
3月前
|
定位技术 C# 图形学
Unity和C#游戏编程入门:创建迷宫小球游戏示例
Unity和C#游戏编程入门:创建迷宫小球游戏示例
71 2
|
4月前
|
C# C++
C# 高效率编程 “多线程” 的基本使用
C# 高效率编程 “多线程” 的基本使用
|
6月前
|
开发框架 .NET 数据库
asp.net企业费用报销管理信息系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
asp.net 企业费用报销管理信息系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使 用c#语言开发 应用技术:asp.net c#+sqlserver 开发工具:vs2010 +sqlserver
49 0
|
7月前
|
Linux C# iOS开发
C#之十八 GUI用户界面编程
C#之十八 GUI用户界面编程
140 0