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自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 最近在网上搜集了一些资料,现整理如下: —————————————————————————————————————— ...
随机推荐
- javascript date picker
一个简洁的date picker <html><head><meta http-equiv="Content-Type" content=" ...
- AJAX实现跨域的三种种方法(代理,JSONP,XHR2)
由于在工作中需要使用AJAX请求其他域名下的请求,但是会出现拒绝访问的情况,这是因为基于安全的考虑,AJAX只能访问本地的资源,而不能跨域访问. 比如说你的网站域名是aaa.com,想要通过AJAX请 ...
- Apache 配置 WebSocket 协议
本文使用 http proxy 方式 实现 apache 支持 WebSocket 请求(JK 使用的 ajp 协议不能支持websocket) 通过 apache 访问 后端 tomcat上的 w ...
- PHP在linux上执行外部命令
PHP在linux上执行外部命令 一.PHP中调用外部命令介绍二.关于安全问题三.关于超时问题四.关于PHP运行linux环境中命令出现的问题 一.PHP中调用外部命令介绍在PHP中调用外部命令,可以 ...
- bat批处理重命名问题
因为要重命名的字符串中有文字,导致重命名出来的文件名都变为乱码了,查理一下需要加两句话 1. @Echo Off Chcp 65001>nul SetLocal EnableDelayedExp ...
- jquery 原理
/* * my-jquery-1.0 *//* * 网上也有很多实现的版本,不过这是我在我自己的理解下写的,加上注释,希望可以解释清楚.*//* * 整个jquery包含在一个匿名函数中,专业点叫闭包 ...
- oracle、mysql新增字段,字段存在则不处理
oracle: 表名:CHANNEL_TRADE_DETAIL列名:exchange_code declare v_rowcount integer; begin select count(*) in ...
- js中原型的概念
- 查linux端口连接情况用命令netstat
查linux端口连接情况用命令netstat netstat -apn |grep cdnbest 或netstat –apn | grep 3320
- Form提交是会刷新页面的
今天发现如果页面中有form,点击提交按钮是会刷新页面的,为了禁止页面刷新行为,可以这么做: <form class="form-horizontal" id="u ...