记录由Equal基础知识引起的内存泄露

      在最近的公司框架开发中,利用了网上某大牛的反射缓存库作为辅助。在测试的时候发现出现了巨大的内存泄露,在频繁的操作后,内存不断的产生巨大的开销,10多分钟就占有了5,6m的内存。解决问题的时,公司不能上网,没有内存分析工具,没有我钟爱的ANTS Memory Profiler帮助下,我们只能靠简单的内存输出来二分查找缩小范围,利用

System.Diagnostics命名空间下的Process的WorkingSet64属性来统计两次输出的内存增长量(WorkingSet64:描述关联的进程分配的物理内存量(以字节为单位))。花了半天终于定位到了第三方的缓存块,一看吓一跳居然缓存了2,3万的对象。看到这里我很清楚的猜测到自定义缓存key一定没有重写来自Object的Equal方法,在三两下很快解决了这次问题。哎,本不该相信第三方,刚开始还以为我数据绑定注册的一大堆客户端控件的事件引起的,但是我实现了IDisposable并取消了事件的,必究事件代理是强类型引用。

    在这里我简单说说这个本是基础知识的东西。说道Equal,我们会联想到==操作符,==对于值类型表示的是值相等,除string类型(内部重写)外表示的是对象的引用,同一个引用地址才会相等。Equal描述的是对象的内容是否相等。但是在Object中默认实现是对引用reference的比较,我们要实现值的比较这必须重写Equal方法和GetHashCode方法,这两个是同时重写的。在我们的IList.Contains,IDictionary.Contains中利用对象的比较就是默认的Equal方法比较,所以我们必须重写这个方法,来达到我们实际的值比较。MSDN:Equals() 和运算符 == 的重写准则(C# 编程指南)

   然而在我们3.0后的表达式linq中对于对象的比较,我们需要实现的IEqualityComparer<T>接口,如下定义:

public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer);

在微软内部实现了5个重要的类,如下图(图来自博客园鹤冲天大牛):

在这里我不想在说很多,关于可以参见博客园鹤冲天大牛的c# 扩展方法奇思妙用基础篇八:Distinct 扩展何止 Linq 的 Distinct 不给力文章实战。

最后给初学者提醒一句,对于IList.Contains,IDictionary.Contains注意实现Equal和GetHashCode,Linq比较IEqualityComparer<TSource>。

本不该错的,应该是大牛忘写了吧,可是害惨了我。

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2011/12/30/2307894.html

时间: 2025-01-02 17:07:44

记录由Equal基础知识引起的内存泄露的相关文章

spark处理1153194条记录的mysql表,怎么就内存泄露?

问题描述 frompysparkimportSparkContext,SparkConffrompyspark.sqlimportSQLContextsc=SparkContext("local","SimpleApp")sqlContext=SQLContext(sc)url="jdbc:mysql://localhost:3306/stock_data?user=root&password=test"df=sqlContext.rea

JavaScript常用全局属性与方法记录积累_基础知识

最近,在学习JavaScript,Java作域链包含全局,记录下常用的全局属性与方法,就当是知识的积累,未列出全部,如需查看全部可参考JS相关的API文档. 常用的全局属性: 全局属性      作用                              Infinity 表示正无穷大的数值 NaN 非数字值  undefined 未定义的值 常用的全局方法:  全局方法      作用                              encodeURI() 返回参数的副本,其中某

javascript cookie基础应用之记录用户名的方法_基础知识

本文实例讲述了javascript cookie基础应用之记录用户名的方法.分享给大家供大家参考,具体如下: 前面有一篇关于cookie基础的文章,封装了 cookie.js,下面我们通过一个实例来应用这个 js. 最常见的就是记住用户名,当用户登录过一次后,通过 cookie 记录下该用户的账号和密码,这样下次打开页面的时候不用再次输入账号密码了.附上代码: <!DOCTYPE HTML> <html lang="en-US"> <head> &l

.NET简谈互操作(四:基础知识之Dispose非托管内存)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用)  .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习.前一篇文章中我们学习了基础知识中的DllImport关键特性:我们继续学习基础知识中的内存释放相关技术

常见内存型号基础知识介绍

DDR=DoubleDataRate双倍速率同步固态随机处理器 严格的说DDR应该叫DDRSDRAM,人们习惯称为DDR,部分初学者也常看到DDRSDRAM,就认为是SDRAM.DDRSDRAM是 DoubleDataRateSDRAM的缩写,是双倍速率同步动态随机存储器的意思.DDR内存是在SDRAM内存基础上发展而来的,仍然沿用 SDRAM生产体系,因此对于内存厂商而言,只需对制造普通SDRAM的设备稍加改进,即可实现DDR内存的生产,可有效的降低成本. 什么是DDR1? 有时候大家将老的存

js变量、作用域及内存详解_基础知识

基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的. (1)值类型:数值.布尔值.null.undefined. (2)引用类型:对象.数组.函数. 如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间.由于这种值的大小不固定(对象有很多属性和方法),因此不能把他们保存到栈内存中.但内存地址大小是固定的,因此可以将内存地址保存在栈内存中. <script type="

javascript的内存管理详解_基础知识

介绍 低层次的语言,如C,具有低级别的内存管理命令,如:malloc()和free(),需要开发者手工释放内存.然而像javascript这样的高级语言情况则不同,对象(objects, strings 等)创建的时候分配内存,当他们不在使用的时候内存会被自动回收,这个自动回收的过程被称为垃圾回收.因为垃圾回收的存在,让javascript等高级语言开发者产生了一个错误的认识,以为可以不用关心内存管理. 内存生命周期 不管什么样的编程语言,内存的生命周期基本上是一致的. 1.分配你需要的内存 2

javascript内存管理详细解析_基础知识

介绍 低层次的语言,如C,具有低级别的内存管理命令,如:malloc()和free(),需要开发者手工释放内存.然而像javascript这样的高级语言情况则不同,对象(objects, strings 等)创建的时候分配内存,当他们不在使用的时候内存会被自动回收,这个自动回收的过程被称为垃圾回收.因为垃圾回收的存在,让javascript等高级语言开发者产生了一个错误的认识,以为可以不用关心内存管理. 内存生命周期 不管什么样的编程语言,内存的生命周期基本上是一致的. 1.分配你需要的内存 2

【ASM】ASM基础知识

[ASM]ASM基础知识 市场占有率 ASM自动存储管理技术已经面世10多个年头,目前已经广泛使用于各个领域的数据库存储解决方案. 到2014年为止,ASM在RAC上的采用率接近60%,在单机环境中也超过了25%. RAC集群环境中3种存储解决方案: ASM.集群文件系统和裸设备: 虽然仍有部分用户坚持使用古老的裸设备,但随着版本的升级,更多用户开始采用ASM这种ORACLE提供的免费解决方案. 在国内使用ASM的场景一般均采用 External Redundancy(11gR2除了存放ocr/