今天开始阅读《编写高性能的.net代码》,比起国内的类似博客介绍的书,整本书基本1/3都是废话,这本书堪称教科书级别,非常值得阅读,特意进行摘抄,制作脑图分享
本书的目标 https://github.com/micli/netcoredebugging (代码地址)
●本书的目标 https://github.com/micli/netcoredebugging (代码地址)
●.NET性能问题
●实际上都是由于编程模式不佳,或者是缺少.NET Framework环境的程序优化技能
●NET的快速开发特性会使得人们能够更迅速地编写出臃肿、缓慢、缺乏优化的代码
●导致代码质量低下的原因还有很多:编程水平有限、赶进度、不良设计、缺少人手、偷懒等
●本书目标
●教你如何让托管代码的性能最大化
同时不牺牲或尽量少牺牲.NET的特性优势。你将学到良好的编码技术,知道应该避免哪些做法。
●学习底层的公共语言运行时(Common Language Runtime,CLR)
了解它是如何完成内存管理、代码编译、并发处理等工作的。你将会了解.NET的架构,它既要让程序正常运行,又要安全、可控。你还将知道编程方式将会极大地影响程序的整体性能。
●充分了解.NET架构和高性能编码原则
●如果想获得极佳的性能,你最好要了解垃圾回收器对应用程序的影响
●如果你的目标是高可用性
那你多少都需要关心一下JIT编译过程。如果你用到了泛型系统,那就可能要考虑接口的分发(Dispatch)问题
●NET Framework类库自带的API有没有问题?会不会对性能造成负面影响?
●多种线程同步机制之间是否有优劣之分?
●讨论一些性能评估技术和流程
帮助你和你的团队建立追求性能的习惯。好的性能无法一蹴而就,必须持续改进和关注才能永不退化
●归根结底,你能对程序做出多少性能优化,不仅直接取决于你对自己的代码有多了解,还包括你对底层框架、操作系统、硬件环境的理解程度。这一点对于任何编程平台都是一样的
●为什么选用托管代码
●安全性
●全自动的内存管理
●更高级别的抽象
生产力更高、漏洞更少
●更先进的语言特性
委托、匿名方法和动态类型
●庞大的现成代码库
WCF WPF
●易扩展性
利用反射机制,延迟绑定(Late-bound)的功能模块能轻松地实现动态调用,满足可扩展架构的要求
●强大的调试特性
每个“异常”(Exception)都附带了大量的关联信息。每个对象也都携带了相关元数据,调试器可以详细分析堆内存和堆栈内存,通常都不需要用到调试符号文件(PDB)
●本机代码的使用场景
●有一种情况可以考虑使用本机代码,而不是托管代码
这就是需要使用完整的处理器指令集,特别是某些用到了SIMD(Single Instruction Multiple Data)指令的高级数据处理程序。不过这种情况也在改变
●使用大量已有本机代码库
在这种情况下,你可以考虑在新老代码之间建立接口。如果能把新老代码的关系定义成清晰的API,那就可以让新代码都成为可托管的,与本机代码的交互可以通过简单的接口层来实现。然后你可以逐步把本机代码迁移成托管代码。
●托管代码比本机代码慢吗?
●比较接近真相的说法是:如果你不够严谨,.NET平台能让你轻松写出性能低下的代码。
●JIT:
大部分的代码优化工作就在这一阶段进行。第一次运行时,的确会发生固定的性能损耗,但之后就一直会调用编译后的版本。后面我们将看到,必要时可以针对首次运行损耗采取多种措施来提高性能
●托管应用的稳定性能
●JIT编译器的质量
除少数情况外,即时编译所生成代码的质量一般都是很高的,而且质量还一直在进步,特别是近段时间以来
●Net服务的运行开销
NET提供的服务并非不需要开销,但比你预想的要低。想把这类开销降到零是没有必要的(这也不可能)。只要降到足够低,使得影响程序性能的其他因素变得更为明显就可以了
●内存分配
堆内存的分配不再是问题了,而本机代码应用则不然。垃圾回收过程确实会消耗一些时间,但即便是这点开销也大都能免除,这有赖于应用程序的配置参数
●内存碎片
对于长时间运行的大型本机代码应用而言,内存碎片是个普遍问题。随着时间的推移,碎片问题必定会越来越严重。对于.NET应用程序而言,这不算是个大问题,因为垃圾回收机制会对堆内存进行碎片整理
●经JIT编译的代码
因为代码在执行时要经过JIT编译,所以它们在内存中的位置可以比本机代码更为优化。存在关联的代码常常会被放在一起,很可能就置于同一个内存页中。这样触发缺页中断(Page Fault)的机会就会减少
●在绝大多数场合,“托管代码比本机代码慢吗?”的答案一定是“否”。当然,肯定存在一些场合,托管代码无法逾越运行环境的一些安全约束而影响性能。这种情况远比想象中的要少,而且绝大部分应用程序都无法得到明显改善。
●真的失去控制权了吗
●垃圾回收行为是确定的,通过对内存分配模式、对象作用域、垃圾回收配置参数的调控,你可以明确指定其运行时机。虽然控制的方式与本机代码不同,但控制能力依然存在
●善用而非抵触CLR
●只需善用CLR就能让性能大幅提升。所有框架的设计初衷都希望能被善加利用,.NET也不例外
●CLR的有些优点也是双刃剑。易用的profiling记录、足量的文档、丰富的元数据和ETW事件查看器,这些都有助于快速定位问题
●性能优化的层级
●算法
经验丰富的程序员总是假定是自己的代码有误,而不是去归咎于编译器、平台、操作系统或硬件。这无疑也适用于性能优化工作
●.Net Framework
NET Framework本身绝大部分都是用托管代码实现的,与你自己编写的程序一样
●CLR
CLR。它的组件既有托管代码编写的,又有非托管代码编写的,提供了垃圾回收、类型加载、JIT编译和其他所有.NET特性的支持
●汇编代码
●在做性能优化计划或研究时,应该自上而下地进行。先确保程序结构和算法的合理性,再往下面几层推进。宏观的优化(macro-optimization)总是比微观优化(micro-optimization)更加有效
共同学习,写下你的评论
评论加载中...
作者其他优质文章