OleDb 内存泄露问题
近期在定位问题时发现使用OleDb打开很大的Excel文件后,即使什么都不操作Colse掉,内存释放了部分,但是并未回到打开前的水平。在Excel 150M,解压缩后900M的场景下,打开后直接Close,内存比打开前多了近90M。如果再次打开关闭,内存不会再增加。但是如果是依此打开多个不同的大型Excel文件,程序很容易内存溢出崩掉。
在会用Red Gate进行内存分析时,发现确实是Excel非托管代码,在不断累积内存,想了很久,目前想到的有3种解决方案。
首先,先上问题复现的代码,很简单,就是使用OleDb打开一个150M左右的Excel
|
1
2
3
4
5
6
7
8
9
10
11
|
private static void Test() { Console.Read(); using (var con=new OleDbConnection(string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source='{0}';Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'",@"F:/1.xls"))) { con.Open(); con.Close(); } GC.Collect(); Console.Read(); } |
复现步骤:
1,准备一个150M的Excel
2,打开任务管理器,打开程序。
3,记录当前程序内存。
4,回车,等到文件读取完毕,并Close释放内存稳定后,再记录当前程序内存。
5,发现多处了70-90M
解决方案
1,经过验证,CSV类型,使用OleDb打开后没有出现类似的内存泄露。所以,可以先把xls、xlsx转为csv,再对csv使用oleDb打开进行操作,最后删掉该csv即可。
如果使用该方法需要注意,csv读取不能根据Sheet读取,只能读整个文件。
xls、xlsx的转化需要使用Microsoft.Office.Interop.Excel.Apllication ,所以需要把当前所需的数据库操作封装一层。
2,直接使用Microsoft.Office.Interop.Excel.Apllication进行Excel操作,并在操作后直接杀掉Excel进程。
但是该方法因为Microsoft.Office.Interop.Excel.Apllication进行Excel读取,每个Range每个Range的读取,都是进程间进行数据交换,性能太渣。唯一可行的是,一大块一大块的读数据,但是没有找到对应的方法。
3,另起一个进程,使用OleDb对Excel进行操作,操作后杀掉该进程。
这个方案可行度也不高,在C#下,要另起进程,带来的稳定性、性能开销都比较大,特别是如果是频繁读取Excel的场景下。
需要解决的问题
1,还有没有更好的办法,在不使用Microsoft.Office.Interop.Excel.Apllication的情况下,解决这一问题。因为使用Microsoft.Office.Interop.Excel.Apllication,就意味着要开个Excel进程,意味着性能开销。
2,OleDb在打开Excel文件时,会进行解压缩,150M 的文件,Open完毕后,程序进程能增加900多M。而使用Microsoft.Office.Interop.Excel.Apllication进行打开,发现只增加了150M。能否在使用OleDb的情况下,减小这部分的内存增加,要知道在程序本身就很耗内存的情况下,打开个Excel就陡增了900M,是很容易崩掉的。
以下是微软提供的解决办法
http://support.microsoft.com/kb/319998
OleDb 内存泄露问题的更多相关文章
- java: web应用中不经意的内存泄露
前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...
- 查看w3wp进程占用的内存及.NET内存泄露,死锁分析
一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- 基于HTML5的WebGL应用内存泄露分析
上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...
- android:布局、绘制、内存泄露、响应速度、listview和bitmap、线程优化以及一些优化的建议!
1.布局优化 首先删除布局中无用的控件和层级,其次有选择地使用性能较低的viewgroup,比如布局中既可以使用RelativeLayout和LinearLayout,那我们就采用LinearLayo ...
- js内存泄露的几种情况详细探讨
内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.在C++中,因为是手动管理内存,内存泄露是经常出现的事情.而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使 ...
- 使用Xcode7的Instruments检测解决iOS内存泄露
文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 作为一名iOS开发攻城狮, ...
- 使用Visual Leak Detector for Visual C++ 捕捉内存泄露
什么是内存泄漏? 内存泄漏(memory leak),指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段 ...
- java内存溢出和内存泄露
虽然jvm可以通过GC自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 最近在网上搜集了一些资料,现整理如下: —————————————————————————————————————— ...
随机推荐
- 一个C#语法高亮插件
语法高亮对程序员阅读代码来说有着不小的帮助,虽然VisualStudio本身支持C#语法高亮,但也只是对关键字.类名.字符串等少数元素加了标记,而我们代码中主题:变量.函数.属性.事件等都没有进行高亮 ...
- 软件工程练习, 模块化,单元测试,回归测试,TDD
这是<构建之法>实战教学的一部分.适合作为同学们的第二个程序作业. 第一个程序作业: 请看 “概论” 一章的练习,或者老师的题目,例如这个. 作业要求: 软件工程的作业越来越有意思了, 我 ...
- List 泛型 集合中 Find 的用法
以前在开发中为了对List,String[].Array进行元素的查找一般都是这样做:List lists = new List();list.add("111");.....fo ...
- convert return char from sql server 2008 r2 or below version to c#
C# string.Replace((char)13, ' ') //newline char; string.Replace((char)10, ' ') //return char;
- 1-13 代理ARP和RARP
一.代理ARP(Proxy ARP) 因为路由器有阻住广播的作用,如果我们要访问一台远端的主机,那么我们封装的并不是远端的目的MAC地址,而是我们网关的MAC地址. 当我们的网关出现故障,就需要给他重 ...
- 关于js中的for(var in)遍历属性报错问题
之前遇到过这个问题,但是没找到问题的所在,将for(var i in array){} 改成了for(var i ;i<array.length;i++)循环,但是今天又遇到了,mark一下错 ...
- 处理数组的forEach map filter的兼容性
处理数组的forEach //forEach处理 if(!Array.prototype.forEach) { Array.prototype.forEach = function (callback ...
- cookie小记
清除cookie可用下面2种的方法.注意如果要清除的cookie的域是指定的,则这里也应该指定,否则无效 1: Response.Cooki ...
- 驱动开发学习笔记. 0.02 基于EASYARM-IMX283 烧写uboot和linux系统
驱动开发读书笔记. 0.02 基于EASYARM-IMX283 怎么烧写自己裁剪的linux内核?(非所有arm9通用) 手上有一块tq2440,但是不知道什么原因,没有办法烧boot进norflas ...
- 后台dom拼接xml,动态显示统计图
这个东西让我好生头疼,贴代码吧 // 两秒后模拟点击 setTimeout(function() { // IE if(document.all) { document.getElementById( ...