.Net Discovery系列之-深入理解平台机制与性能影“.NET研究”响(下)

简介:   三.关于异常捕获机制   虽然我们已经很辛苦了,但是仍然有很多原因使代码运行失败,如引用null引用、索引越界、内存溢出、类型转换失败等等。这就需要我们的代码有足够的容错能力,在代码运行失败时,及时、主动的处理这些异常。

  三.关于异常捕获机制

  虽然我们已经很辛苦了,但是仍然有很多原因使代码运行失败,如引用null引用、索引越界、内存溢出、类型转换失败等等。这就需要我们的代码有足够的容错能力,在代码运行失败时,及时、主动的处理这些异常。

  ● 机制分析

  .Net 中基本的异常捕获与处理机制是由try…catch…finally块来完成的,它们分别完成了异常的监测、捕获与处理工作。一个try块可以对应零个或多个catch块,可以对应零个或一个finally块。不过没有catch的try似乎没有什么意义,如果try对应了多个catch,那么监测到异常后,CLR会自上而下搜索catch块的代码,并通过异常过滤器筛选对应的异常,如果没有找到,那么CLR将沿着调用堆栈,向更高层搜索匹配的异常,如果已到堆栈顶部依然没有找到对应的异常,就会抛出未处理的异常了,这时catch块中的代码并不会被执行。所以距离try最近的catch块将最先被遍历到。

  以下代码:

代码
 
  
try
{
Convert.ToInt32(
" Try " );
}
catch 上海网站建设tyle="color: #000000;"> (FormatException ex1)
{
string CatchFormatException = " C上海闵行企业网站设计与制作atchFormatException " ;
}
catch (NullReferenceException ex2)
{
string CatchNullReferenceException = " CatchNullReferenceException " ;
}
finally
{
string Finally = " Finally " ;
}
 对应IL如下:
.method private hidebysig instance void Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// Code size 53 (0x35)
.maxstack 1
.locals init ([
0] class [mscorlib]System.FormatException ex1,
[
1] string CatchFormatException,
[
2] class [mscorlib]System.NullReferenceException ex2,
[
3] string CatchNullReferenceException,
[
4] string Finally)
IL_0000: nop
IL_0001: nop
IL_0002: ldstr
"Try"
IL_0007: call int32 [mscorlib]System.Convert::ToInt32(
string)
IL_000c: pop
IL_000d: nop
IL_000e: leave.s IL_0026
IL_0010: stloc.0

IL_0011: nop
IL_0012: ldstr
"CatchFormatException"
IL_0017: stloc.
1
IL_0018: nop
IL_0019: leave.s IL_0026
IL_001b: stloc.
2
IL_001c: nop
IL_001d: ldstr
"CatchNullReferenceException"
IL_0022: stloc.
3
IL_0023: nop
IL_0024: leave.s IL_0026
IL_0026: nop
IL_0027: leave.s IL_0033
IL_0029: nop
IL_002a: ldstr
"Finally"
IL_002f: stloc.s Finally
IL_0031: nop
IL_0032: endfinally
IL_0033: nop
IL_0034: ret
IL_0035:
// Exception count 3
.try IL_0001 to IL_0010 catch [mscorlib]System.FormatException handler IL_0010 to IL_001b
.
try IL_0001 to IL_0010 catch
[mscorlib]System.NullReferenceException handler IL_001b to IL_0026
.
try IL_0001 to IL_0029 finally
handler IL_0029 to IL_0033
}
// end of method Form1::Form1_Load
 
 

  末尾的几行代码揭示出IL是怎样处理异常处理的。最后三行的每一个Item被称作Exception Handing Clause,EHC组成Exception Handing Table,EHT与正常代码之间由ret返回指令隔开。

  可以看出,FormatException排列在EHT的第一位。

  当代码成功执行或反之而返回后,CLR会遍历EHT:

  1. 如果抛出异常, CLR会根据抛出异常的代码的地址找到对应的EHC(IL_上海企业网站设计与制作0001 to IL_0010为检测代码的范围),这个例子中CLR将找到2条EHC, FormatException会最先被遍历到,且为适合的EHC。

  2. 如果返回的代码地址在IL_0001 to IL_0029内,那么还会执行finally handler 上海闵行企业网站制作g>即IL_0029 to IL_0033中的代码,不管是否因成功执行代码而返 回

  事实上,catch与finally的遍历工作是分开进行的,如上文所言,CLR首先做的是遍历catch,当找到合适的catch块后,再遍历与之对应finally;而且这个过程会递归进行至少两次,因为编译器将C#的try…catch…finally翻译成IL中的两层嵌套。

当然如果没有找到对应的catch块,那么CLR会直接执行finally,然后立即中断所有线程。Finally块中的代码肯定会被执行,无论try是否检测到了异常。

  ● 性能影响与改进建议

  异常捕获与处理是有性能代价的,虽然这种代价在托管环境中度量起来比较困难,但是这个过程毕竟经过一系列的遍历。所以仅从性能方面考虑,一般建议有以下几点准则:

  1.尽量给CLR一个明确的异常信息,不要使用Exception去过滤异常

  2.尽量不要将try…catch写在循环中

  3. try尽量少的代码,如果有必要可以使用多个catch块,并且将最有可能抛出的异常类型,书写在距离try最近的位置

  4.不要只声明一个Exception对象,而不去处理它

  5.使用性能计数器实用工具的CLR Exceptions检测异常情况,并适当优化

  6.使用成员的Try-Parse模式,如果抛出异常,那么用false代替它

  四.关于字符串拼接

  ● 机制分析

  .Net字符串型的变量有一个很特殊的机制,这个机制叫做字符串的驻留,其变现为字符串恒定不可改变。

  简单的说,字符串一旦建立,就会永久驻留在内存中,当你修改这个字符串变量时,CLR会在内存中新建一个新值,并不会修改旧值,旧值只有被垃圾回收器回收后,那部分被占用的空间才会释放掉。

  这样设计的目的无疑是为了提高字符串型变量的建立,因为新建字符串型变量时,CLR首先做的是在驻留池中遍历是否有相同的值的字符串,如果有则直接挂接变量指针,否则才会新建,但是在某些情况下,性能却反而降低。

  ● 性能影响与改进建议

  下面通过例子简单的说一下字符串驻留机制,假设有如下代码:

 
 
string str = ""
string a = " str_1 " 上海企业网站制作e="color: #000000;"> + str;
a
= " str_2 " + str;

  第三行C#代码(a = "str_2"+ str;)的样子看起来是在修改变量a的旧值"str_1",但实际上是创建了一个新的字符串"str_2",然后将变量a的指针指向了"str_2"的内存地址,而"str_1"依然在内存中没有受到任何影响 ---这就是字符串的驻留,如果下一次有变量b的值被赋值为str_1,CLR不会重新为这个变量重新分配内存,而是直接将该变量的指针指向str_1,这样就提高了该变量的初始化速度,但是如果没有这样的一个b变量,那么str_1就会一直占用内存,直至垃圾收集,这样做浪费了内存资源。

  同样ToUpper、SubString、Trim、Replace、加号连接等操作都会产生驻留的字符串,各位在设计程序时要特别注意。

  经常看到有的同学使用Replace替换一个网页整个HTML的某些关键字,其实这样会极大的浪费内存,给垃圾回收器的策略引擎以错误的信号,使其频繁启动,从而导致性能的降低。

  所以,有以下建议供大家参考:

  1.在用Replace做大量字符串操作时,最好仅仅对最小单元进行操作

  上海徐汇企业网站设计与制作2在尽量少的字符串中替换,有必要时还要配合正则的使用,在替换完毕后最好根据上下文的代龄情况,手动调用一次GC的回收方法;

  3.对大规模的字符串拼接操作,则推荐使用StringBuilder

  4.能用常量赋值的就别用变量。因为常量赋值的字符串是在编译器生成在字符串常量池的,关于常量池请参考Aicken以前的文章。

  相关文章:.Net Discovery系列-深入理解平台机制与性能影响(上)

                      .Net Discovery系列之-深入理解平台机制与性能影响 (中)

目录
相关文章
|
17天前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
46 13
|
15天前
|
Linux API C#
基于 .NET 开发的多功能流媒体管理控制平台
基于 .NET 开发的多功能流媒体管理控制平台
|
1月前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
111 13
|
2月前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
42 5
|
2月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
49 4
|
2月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
47 3
|
2月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
40 3
|
2月前
|
人工智能 Java 编译器
.NET 9 发布 性能提升、AI 支持与全方位改进
【11月更文挑战第5天】.NET 9 引入了多项改进,包括性能提升、AI 支持和全方位功能优化。性能方面,编译器增强、服务器 GC 优化、矢量化和硬件支持等提升了执行效率。AI 方面,新增学习材料、合作伙伴生态、原生支持和生成式 AI 集成。此外,.NET Aspire 组件升级、编程语言新功能和开发工具更新进一步提升了开发体验。
|
2月前
|
存储 设计模式 编解码
.NET 8.0 通用管理平台,支持模块化、WinForms 和 WPF
【11月更文挑战第5天】本文分析了.NET 8.0 通用管理平台在模块化、WinForms 和 WPF 方面的优势。模块化设计提升了系统的可维护性和可扩展性,提高了代码复用性;WinForms 提供了丰富的控件库和简单易用的开发模式,技术成熟稳定;WPF 支持强大的数据绑定和 MVVM 模式,具备丰富的图形和动画功能,以及灵活的布局系统。
|
5月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
89 0