构建高性能ASP.NET站点 第七章 如何解决内存的问题(前篇)—托管资源优化—垃圾回收机制深度剖析

简介:
构建高性能ASP.NET 站点  第七章  如何解决内存的问题( 前篇)— 托管资源优化垃圾回收机制剖析
    前言:本章主要详细的讲述如何因内存问题而导致的性能问题,很多的时候都是深入.NET 内核进行分析,然后给出解决方案,同时,本系列的其他文章,也争取做到:深入浅出。
 
   本篇是为后面的做个铺垫,而且比较的精彩。只有真正的理解了本篇,后面才可以顺利的走下去。
 
本篇的议题如下:
内存问题概述( 前篇)
托管资源优化(前篇)
          对象的生命周期(前篇)
          对象的 代“(前篇)
          大对象堆(LOH)  (前篇)
         CLR 计数器的使用          (前篇)
         CLR Profiler 的使用(中篇)
          垃圾回收器的不同版本(中篇)
          对象使用注意事项(中篇)
          常用优化措施(后篇)
非托管资源优化
Session 会话的优化
 
   内存问题概述
    和CPU 一样,内存也是一个直接影响服务端性能的重要的硬件资源。
   一般来说,如果服务端内存不足,从导致以下两个问题产生:
1.        导致服务端把一些原本要写到内存中的数据,写到硬盘上面。这样不仅仅加大了CPU 和磁盘的I/O 操作,同时也延长了读取这些数据的时间。
2.        阻止了一些缓存策略的使用。
 
   对于内存不足,一直最快最直接的方式就是去买内存条加在服务器上面。但是这样存在一个隐患的问题就是:如果加了新的内存之后,服务端又面临内存不足的问题,我们不可能无止境的加内存条,那么我们就必须从站点本身来解决这个问题,例如从服务端的配置,对站点的代码进行分析,优化。
 
   托管资源优化
对于托管资源,相信大家并不陌生了,简单的说就是:在C# 的托管堆上面创建的资源,或者说通过new 产生的对象。
在深入讲解之前,我们首先来看看对象的生命周期
 
   对象的生命周期
当我们用new 关键字创建了一个对象的时候,这个对象就被分配到CRL 托管堆上面。这个托管堆是在内存中的。而且这个分配对象空间的速度是非常的快的,因为每次都是在托管堆的最后面划出一定的空间来给这个对象,不用去堆上面需找合适大小的空间。
        如果当托管堆准备为一个对象分配空间的时候,发现托管堆上面的空间太小了,不足以分配给这个新的对象,那么CLR 就开始运行垃圾回收机制了。我们知道:垃圾回收机制会把那些在托管堆上面没有了引用指向的那些对象都清理掉,同时也会把托管堆上面现存的对象进行压缩。
        但是有一点需要清楚:如果此时进行了垃圾回收的时候,清除了一些没有用的对象,但是只有在下一次来回收进行的时候,上次垃圾回收清除的对象才真正的从内存中消除( 此时,还有一些“对象复苏“等话题就不在赘述)
 
   下面就来讲述一些垃圾回收的话题。
 
   对象的 代“
CLR 进行垃圾回收的时候,垃圾回收器回去托管堆上面去检查对象是否可以被回收,这个检查过程是非常消耗资源的。为了避免每次垃圾回收都要便利托管堆上面的所有对象,CLR 给把托管堆上面的对象用来划分,例如,第一代,第二代。然后每次便利扫描托管堆的时候,就去扫描某一个中的对象,这样性能就好点。 
在托管堆上面,可以把对象分为三个”:0 代,1 代,2 代,仅此这三个代。每个对象都是从0 代开始的。一个对象每经历一次垃圾回收,并且这个对象还在使用中,那么这个对象的“代“就会增加1 代。例如,如果在0 代的对象,经历了一次垃圾回收之后,他的代就是1 代,如果是1 代的对象,最后就会变为2 代。如果对象本身已经是2 代了,不管经历多少次垃圾回收( 如果对象一直在使用) ,那么这个对象还是2 代。
 
CLR 垃圾回收中有句话要记得:”  ’ 数越大,被回收的可能性就越小。而且一些性能优化就是根据这个进行的。
 
每次CLR 在进行垃圾回收的时候,都会优先的去扫描第0 代的对象,所以,一些新的,临时使用的对象可以被立刻的清除。相比而言,垃圾回收器扫描第1 代对象的频率就没有第0 代强,扫描第2 代对象的频率就更低了。所以说:对象存活的时间越长,就越难被回收,而且一直占据CLR 的内存资源。
 
还有有点需要注意的就是 :如果CLR 决定要扫描了第1 代了,同时也用扫描第0 代的对象,同时如果,CLR 扫描第2 代对象,那么第0 代,第1 代对象都会被扫描。
 
所以,从这里可以得出:我们尽量避免把原本需要立刻回收的的对象变为长期存活的对象。通俗点说就是:如果一个对象本来已经存活在0 代的,然后用完就回收的,我们不要让这个对象一直存活到第1 代,甚至第2 代。在编程上面基本就是这样的实现思路:尽可能晚的实例化对象,尽可能早的释放对象。
 
     大对象堆 (Large Objecet Heap)
我们之前讲述了的一些话题,CLR 除了上面的一般的堆( 一般的new 对象分配空间的那个堆) CLR 中还存在另外的一个堆:专门用来放置那些大于了58k 的对象的堆,大对象堆
如果new 一个对象的时候,这个对象的大小超过了85k ,那么CLR 就会把这个对象放在LOH 上面。如果此时LOH 的空间不足了,那么CLR 就会启动垃圾回收器去扫描LOH 堆和那个一般堆上面的第2 代对象,我们之前说过,如果扫描第2 代对象,就同时扫描第1 代,第0 代,那么实际相当于扫描了整个托管堆,性能影响可想而知。
而且不想之前那个一般堆,在LOH 上面的对象被垃圾回收器回收之后,上面的大对象是不会被压缩的,那么LOH 这个堆上面就可能存在一些空间碎片,然后分配新的大对象的时候,就要找空间,甚至进行碎片的整理,大家可以联想一下我们电脑的磁盘碎片整理。
 
OK ,今天就讲到这里,理论有点多,但是都是基本要清楚和掌握的,希望多多理解。
 
















本文转自yanyangtian51CTO博客,原文链接:  http://blog.51cto.com/yanyangtian/495267 ,如需转载请自行联系原作者











相关文章
|
30天前
|
存储 监控 NoSQL
Redis处理大量数据主要依赖于其内存存储结构、高效的数据结构和算法,以及一系列的优化策略
【5月更文挑战第15天】Redis处理大量数据依赖内存存储、高效数据结构和优化策略。选择合适的数据结构、利用批量操作减少网络开销、控制批量大小、使用Redis Cluster进行分布式存储、优化内存使用及监控调优是关键。通过这些方法,Redis能有效处理大量数据并保持高性能。
47 1
|
7天前
|
缓存 安全 前端开发
(转)浅谈tomcat优化(内存,并发,缓存,安全,网络,系统等)
(转)浅谈tomcat优化(内存,并发,缓存,安全,网络,系统等)
|
9天前
|
监控 算法 Java
Java性能优化(九)-多线程调优-垃圾回收机制优化
Java性能优化(九)-多线程调优-垃圾回收机制优化
17 0
|
20天前
|
机器学习/深度学习 缓存 算法
深入理解操作系统的虚拟内存管理利用机器学习技术优化数据中心能效
【5月更文挑战第25天】 在现代计算机系统中,虚拟内存是允许用户程序逻辑地址空间与物理内存解耦的关键概念。它为每个进程提供了一个独立的、连续的地址空间,通过内存管理单元(MMU)硬件的支持,将程序使用的虚拟地址映射到实际的物理内存地址。这种机制不仅简化了程序的编写和内存的管理,还提供了保护机制,防止不同进程之间的相互干扰。本文将探讨虚拟内存的工作原理、分页系统的实现以及虚拟内存带来的性能影响,并讨论操作系统如何优化内存使用和管理。
|
25天前
|
大数据 Python
【Python DataFrame专栏】DataFrame内存管理与优化:大型数据集处理技巧
【5月更文挑战第20天】本文介绍了使用Python的pandas库优化DataFrame内存管理的六个技巧:1) 查看DataFrame内存占用;2) 使用高效数据类型,如`category`和`int32`;3) 仅读取需要的列;4) 分块处理大数据集;5) 利用`inplace`参数节省内存;6) 使用`eval()`和`query()`进行快速筛选。这些方法有助于处理大型数据集时提高效率。
【Python DataFrame专栏】DataFrame内存管理与优化:大型数据集处理技巧
|
26天前
|
并行计算 索引 Python
讨论如何优化 DataFrame 操作,减少内存占用和提高执行速度
【5月更文挑战第19天】优化 DataFrame 操作涉及选择合适的数据类型、避免复制、使用向量化、高效迭代和设置索引。通过这些策略,如使用 `np.int8` 节省内存,直接修改列数据,利用 `itertuples`,设置分类数据类型,以及分块和并行计算,可以显著减少内存占用和提高执行速度,从而更好地处理大规模数据。实践中需结合具体情况综合运用,不断测试和优化。
39 2
|
30天前
|
缓存 监控 NoSQL
【MongoDB 专栏】MongoDB 的内存管理与优化
【5月更文挑战第11天】MongoDB的内存管理优化对性能至关重要,涉及数据缓存、索引及执行操作的内存使用。动态内存管理根据访问模式和负载调整,可通过配置参数优化,如设置合适缓存大小,调整内存分配参数。索引管理也很重要,需定期评估优化,避免内存占用过高。监控内存使用、数据清理压缩、架构规划也是优化手段。面对挑战,如高并发下的内存不足,需灵活调整策略,平衡系统资源。不断学习新方法,提升内存管理能力,以优化MongoDB性能。
【MongoDB 专栏】MongoDB 的内存管理与优化
|
30天前
|
机器学习/深度学习 自然语言处理 安全
【专栏】.NET 开发:构建智能应用的关键
【4月更文挑战第29天】本文探讨了.NET开发在构建智能应用中的关键作用,强调了其强大的框架、工具集、高效性能和跨平台支持。通过实例展示了.NET在人工智能、物联网及企业级应用中的应用。同时,指出了.NET开发面临的挑战,如技术更新的学习成本、性能优化、资源管理和安全隐私保护,并提出了应对策略。随着技术进步,.NET将在智能应用领域发挥更大作用,推动创新与便利。
|
30天前
|
中间件 Go API
Golang深入浅出之-Go语言标准库net/http:构建Web服务器
【4月更文挑战第25天】Go语言的`net/http`包是构建高性能Web服务器的核心,提供创建服务器和发起请求的功能。本文讨论了使用中的常见问题和解决方案,包括:使用第三方路由库改进路由设计、引入中间件处理通用逻辑、设置合适的超时和连接管理以防止资源泄露。通过基础服务器和中间件的代码示例,展示了如何有效运用`net/http`包。掌握这些最佳实践,有助于开发出高效、易维护的Web服务。
44 1
|
30天前
|
缓存 Java Android开发
安卓开发中的内存泄漏分析与优化策略
【4月更文挑战第27天】 在移动应用开发领域,性能优化始终是提升用户体验的关键因素之一。特别是对于安卓平台,由于设备的硬件配置差异较大,良好的内存管理对于保证应用流畅运行尤为重要。本文将深入探讨安卓开发中常见的内存泄漏问题,并提供一系列检测和解决内存泄漏的实用策略。通过对工具的使用、代码实践以及系统架构设计的多维度分析,旨在帮助开发者有效避免和处理内存泄漏,确保应用性能稳定。