图书目录

目  录

第1章  基本概念  1

1.1  内存相关术语  2

1.1.1  静态分配  6

1.1.2  寄存器机  6

1.1.3  堆栈(Stack)  7

1.1.4  堆栈机  11

1.1.5  指针  12

1.1.6  堆(Heap)  14

1.2  手动内存管理  15

1.3  自动内存管理  19

1.4  引用计数  23

1.5  跟踪回收器(Tracking Collector )  26

1.5.1  标记阶段  27

1.5.2  回收阶段  30

1.6  小历史  32

1.7  本章小结  34

规则1 – 自学  34

第2章  底层内存管理  37

2.1  硬件  37

2.1.1  内存  42

2.1.2  CPU  43

2.2  操作系统  55

2.2.1  虚拟内存  55

2.2.2  large page  59

2.2.3  虚拟内存碎片  59

2.2.4  通用内存布局  59

2.2.5  Windows内存管理  60

2.2.6  Windows内存布局  65

2.2.7  Linux内存管理  67

2.2.8  Linux内存布局  68

2.2.9  操作系统的影响  69

2.3  NUMA和CPU组  70

2.4  本章小结  71

规则2 – 避免随机访问,拥抱循序访问  71

规则3 – 提高空间和时间数据局部性  72

规则4 – 不要放弃使用更高级技巧的可能性  72

第3章  内存测量  73

3.1  尽早测量  74

3.1.1  开销和侵入性  74

3.1.2  采样与跟踪  75

3.1.3  调用树  75

3.1.4  对象图  76

3.1.5  统计  77

3.1.6  延迟与吞吐量  79

3.1.7  内存转储、跟踪、实时调试  80

3.2  Windows环境  81

3.2.1  概述  81

3.2.2  VMMap  81

3.2.3  性能计数器  82

3.2.4  Windows事件跟踪  87

3.2.5  Windows性能工具包  95

3.2.6  PerfView  104

3.2.7  ProcDump, DebugDiag  111

3.2.8  WinDbg  112

3.2.9  反汇编程序和反编译程序  114

3.2.10  BenchmarkDotNet  114

3.2.11  商业工具  115

3.3  Linux环境  123

3.3.1  概况  123

3.3.2  Perfcollect  124

3.3.3  Trace Compass  126

3.3.4  内存转储  134

3.4  本章小结  135

规则5 – 尽早测量GC  137

第4章  .NET基础知识  139

4.1  .NET版本  139

4.2  .NET内部原理  141

4.3  程序集和应用程序域  148

4.4  进程内存区域  150

4.4.1  场景4-1:我的程序占用了多大内存  153

4.4.2  场景4-2:我的程序的内存使用率持续攀升(1)  155

4.4.3  场景4-3:我的程序的内存使用率持续攀升(2)  157

4.4.4  场景4-4:我的程序的内存使用率持续攀升(3)  158

4.5  类型系统  161

4.5.1  类型的分类  161

4.5.2  类型的存储  162

4.5.3  值类型  163

4.5.4  引用类型  169

4.6  字符串  173

4.6.1  字符串暂存  178

4.6.2  场景4-5:我的程序的内存使用率太高  182

4.7  装箱与拆箱  185

4.8  按引用传递  188

4.8.1  按引用传递值类型实例  188

4.8.2  按引用传递引用类型实例  189

4.9  类型数据局部性  190

4.10  静态数据  193

4.10.1  静态字段  193

4.10.2  静态数据揭秘  194

4.11  本章小结  197

规则6 – 测量你的程序  197

规则7 – 不要假设内存泄漏不存在  198

规则8 – 考虑使用结构  198

规则9 – 考虑使用字符串暂存  198

规则10 – 避免装箱  198

第5章  内存分区  201

5.1  分区策略  201

5.2  按大小分区  202

5.2.1  小对象堆  203

5.2.2  大对象堆  203

5.3  按生存期分区  207

5.3.1  场景5-1:我的程序健康吗?

实时的代大小  210

5.3.2  记忆集  214

5.3.3  卡表(Card Tables)  218

5.3.4  卡包(Card Bundles)  222

5.4  按物理分区  224

5.4.1  场景5-2:nopCommerce可能发生内存泄漏  229

5.4.2  场景5-3:大对象堆浪费了  236

5.4.3  段和堆解析  237

5.4.4  段重用  239

5.5  本章小结  241

规则11 – 监视代大小  241

规则12 – 避免不必要的堆引用  241

规则13 – 监视段使用情况  242

第6章  内存分配  243

6.1  内存分配简介  243

6.2  bump pointer分配  244

6.3  空闲列表分配  250

6.4  创建新对象  253

6.4.1  小对象堆分配  255

6.4.2  大对象堆分配  257

6.5  堆再平衡  260

6.6  OutOfMemoryException异常  262

场景6-1:OutOfMemoryException异常  263

6.7  堆栈分配  265

6.8  避免分配  266

6.8.1  显式的引用类型分配  267

6.8.2  隐式的分配  286

6.8.3  类库中的各种隐式分配  293

6.8.4  场景6-2:调查程序中的分配情况  297

6.8.5  场景6-3:Azure Functions  299

6.9  本章小结  300

规则14 – 在性能攸关的地方,

避免堆分配  300

规则15 – 避免过多的LOH分配  301

规则16 – 如果可行,在堆栈上分配  301

第7章  垃圾回收——简介  303

7.1  高层视图  303

7.2  GC过程的示例  304

7.3  GC过程的步骤  309

场景7-1:分析GC的使用情况  309

7.4  分析GC  313

7.5  垃圾回收性能调优数据  314

7.5.1  静态数据  314

7.5.2  动态数据  315

7.5.3  场景7-2:了解分配预算  317

7.6  回收触发器  325

7.6.1  分配触发器  326

7.6.2  显式触发器  326

7.6.3  场景7-3:分析显式GC调用  328

7.6.4  低内存级别系统触发器  333

7.6.5  各种内部触发器  333

7.7  EE挂起  334

场景7-4:分析GC挂起时间  335

7.8  要判决的代  336

场景7-5:被判决的代的分析  338

7.9  本章小结  339

第8章  垃圾回收——标记阶段  341

8.1  对象的遍历与标记  341

8.2  局部变量根  342

8.2.1  局部变量存储  343

8.2.2  堆栈根  343

8.2.3  词法作用域  343

8.2.4  存活堆栈根与词法作用域  344

8.2.5  带有激进式根回收的存活堆栈根  345

8.2.6  GC信息  350

8.2.7  固定局部变量  354

8.2.8  堆栈根扫描  356

8.3  终结根  357

8.4  GC内部根  357

8.5  GC句柄根  358

8.6  处理内存泄漏  363

8.6.1  场景8-1:nopCommerce可能

发生内存泄漏  365

8.6.2  场景8-2:找出最常出现的根  367

8.7  本章小结  369

第9章  垃圾回收——计划阶段  371

9.1  小对象堆  371

9.1.1  插头和间隙  371

9.1.2  场景9-1:具有无效结构的

内存转储  375

9.1.3  砖表  376

9.1.4  固定  377

9.1.5  场景9-2:调查固定  381

9.1.6  代边界  385

9.1.7  降级  385

9.2  大对象堆  389

9.3  压缩的决策  390

9.4  本章小结  391

第10章  垃圾回收——清除和压缩  393

10.1  清除阶段  393

10.1.1  小对象堆  393

10.1.2  大对象堆  394

10.2  压缩阶段  394

10.2.1  小对象堆  394

10.2.2  大对象堆  397

10.2.3  场景10-1:大对象堆的碎片化  398

10.3  本章小结  404

规则17 – 观察运行时挂起  405

规则18 – 避免“中年危机”  406

规则19 – 避免老的代和LOH碎片化  406

规则20 – 避免显式GC  407

规则21 – 避免内存泄漏  407

规则22 – 避免固定  407

第11章  GC风格  409

11.1  模式概述  409

11.1.1  工作站模式与服务器模式  409

11.1.2  非并发模式与并发模式  411

11.2  模式配置  411

11.2.1  .NET Framework  412

11.2.2  .NET Core  412

11.3  GC停顿和开销  413

11.4  模式描述  414

11.4.1  非并发工作站模式  415

11.4.2  并发工作站模式(4.0版本之前)  416

11.4.3  后台工作站模式  417

11.4.4  非并发服务器模式  423

11.4.5  后台服务器模式  425

11.5  延迟模式  426

11.5.1  批处理模式  426

11.5.2  交互式模式  426

11.5.3  低延迟模式  427

11.5.4  持续低延迟模式  427

11.5.5  无GC区域模式  429

11.5.6  延迟优化目标  430

11.6  选择GC风格  431

11.6.1  场景11-1:检查GC设置  432

11.6.2  场景11-2:对不同GC模式进行基准测试  433

11.7  本章小结  438

规则23 – 有意识地选择GC模式  439

规则24 – 记住延迟模式的相关知识  439

第12章  对象生存期  441

12.1  对象与资源的生命周期  441

12.2  终结  442

12.2.1  简介  443

12.2.2  激进式根回收问题  446

12.2.3  关键终结器  449

12.2.4  终结的内部实现  449

12.2.5  场景12-1:由于终结而导致的内存泄漏  455

12.2.6  复活(Resurrection)  460

12.3  Disposable对象  463

12.4  安全句柄  468

12.5  弱引用  473

12.5.1  缓存  477

12.5.2  弱事件模式  479

12.5.3  场景12-2:由于事件导致的内存泄漏  484

12.6  本章小结  486

规则25 – 避免终结器  486

规则26 – 首选显式清理  487

第13章  其他主题  489

13.1  依赖句柄  489

13.2  线程局部存储  494

13.2.1  线程静态字段  494

13.2.2  线程数据插槽  497

13.2.3  线程局部存储的内部  498

13.2.4  使用场景  503

13.3  托管指针  504

13.3.1  ref局部变量  505

13.3.2  ref返回值  505

13.3.3  只读ref变量和in参数  507

13.3.4  ref类型的内部  511

13.3.5  C#中的托管指针——ref变量  521

13.4  关于结构的更多知识  526

13.4.1  只读结构  526

13.4.2  ref结构(类似于托管指针的类型)  528

13.4.3  固定大小的缓冲区  529

13.5  对象/结构布局  533

13.6  非托管约束  541

13.7  本章小结  546

第14章  高级技巧  547

14.1  Span<T>和Memory<T>  547

14.1.1  Span<T>  547

14.1.2  Memory<T>  560

14.1.3  IMemoryOwner<T>  562

14.1.4  Memory<T>的内部实现  566

14.1.5  Span<T>和Memory<T>使用准则  568

14.2  Unsafe  568

14.3  面向数据设计  573

14.3.1  战术型设计  574

14.3.2  战略型设计  576

14.4  未来特性  585

14.4.1  可为空引用类型  585

14.4.2  Pipelines  590

14.5  本章小结  595

第15章  编程API  597

15.1  GC API  597

15.1.1  收集数据和统计  597

15.1.2  GC通知  604

15.1.3  控制非托管内存压力  606

15.1.4  显式回收  606

15.1.5  无GC区域  606

15.1.6  终结(Finalization)管理  606

15.1.7  内存使用率  607

15.1.8  GC类中的内部调用  608

15.2  CLR Hosting  609

15.3  ClrMD  616

15.4  TraceEvent库  621

15.5  自定义GC  623

15.6  本章小结  626