近期在定位问题时发现使用OleDb打开很大的Excel文件后,即使什么都不操作Colse掉,内存释放了部分,但是并未回到打开前的水平。在Excel 150M,解压缩后900M的场景下,打开后直接Close,内存比打开前多了近90M。如果再次打开关闭,内存不会再增加。但是如果是依此打开多个不同的大型Excel文件,程序很容易内存溢出崩掉。
在会用Red Gate进行内存分析时,发现确实是Excel非托管代码,在不断累积内存,想了很久,目前想到的有3种解决方案。

首先,先上问题复现的代码,很简单,就是使用OleDb打开一个150M左右的Excel

C# code

 

?

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 内存泄露问题的更多相关文章

  1. java: web应用中不经意的内存泄露

    前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...

  2. 查看w3wp进程占用的内存及.NET内存泄露,死锁分析

    一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...

  3. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  4. 基于HTML5的WebGL应用内存泄露分析

    上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...

  5. android:布局、绘制、内存泄露、响应速度、listview和bitmap、线程优化以及一些优化的建议!

    1.布局优化 首先删除布局中无用的控件和层级,其次有选择地使用性能较低的viewgroup,比如布局中既可以使用RelativeLayout和LinearLayout,那我们就采用LinearLayo ...

  6. js内存泄露的几种情况详细探讨

    内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.在C++中,因为是手动管理内存,内存泄露是经常出现的事情.而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使 ...

  7. 使用Xcode7的Instruments检测解决iOS内存泄露

    文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 作为一名iOS开发攻城狮, ...

  8. 使用Visual Leak Detector for Visual C++ 捕捉内存泄露

    什么是内存泄漏? 内存泄漏(memory leak),指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段 ...

  9. java内存溢出和内存泄露

    虽然jvm可以通过GC自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 最近在网上搜集了一些资料,现整理如下: —————————————————————————————————————— ...

随机推荐

  1. 转载-V.I.Arnold, beyond a mathematician

    转自-http://blog.renren.com/blog/248100754/471276636 在AMS的首页上找到了三条讣告,依次是V.I.Arnold(1937-2010),W.Rudin( ...

  2. Centos安装lnmp环境

    1:查看环境: [root@10-4-14-168 html]# cat /etc/redhat-release CentOS release 6.5 (Final) 2:关掉防火墙 [root@10 ...

  3. Centos7上安装dnf-plugins-core

    为了在Centos上使用dnf copr命令,需要安装dnf-plugins-core,找了很长时间,包括试了源码编译安装都不行,最后找到了方法,执行下面的命令就可以了. 需要root权限 wget ...

  4. --- shell 扩展的顺序

    1. 扩展(expansion)是bash 解释器的重要的概念: 2. 命令替换是扩展里面的一种 3. 基本结构是: “字符串准备(花括号,波浪线,参数和变量扩展,命令替换),单词分割,路径扩展” h ...

  5. 锋利的js之验证身份证号

    我们在做互联网网站时,注册个人资料时,经常要用到身份证号,我们需要对身份证进验证,不然别人随便输个号码就通过,让你感觉这个网站做得很shit. 身份证号是有规则的. 结构和形式 1.号码的结构  公民 ...

  6. 一、prolog简介

    一般来说,人工智能语言应具备如下特点: 1.具有符号处理能力(即非数值处理能力): 2.适合于结构化程序设计,编程容易: 3. 具有递归功能和回溯功能: 4. 具有人机交互能力: 5. 适合于推理: ...

  7. JENKINS基础使用

    JENKINS总结 修改时间 修改内容 修改人 2016.3.12 创建 刘永志 2016.5.22 添加tomcat+jenkins 刘永志 2016.6.14 添加tomcat找不到ant解决方案 ...

  8. 【原】git如何删除本地和远程的仓库

    今天操作git时遇到一个小问题:如何删除本地和远程的仓库,在网上巴拉一番解决了这个问题. 方法1: $rm testfile$git add -u $git commit -m "delet ...

  9. Math Start!

    (1)Add Digits 解题思路: 基于同余的数学属性. 数字的根(即题目所要求返回的最终结果)与该数字除以9时的余数相同(并且该余数将始终为单个数字). take 438 as an examp ...

  10. thinkphp学习简易教程(一) thinkphp创建项目

    1.在本地服务器根目录下创建项目目录,如命名为app: 2.把thinkphp的压缩包解压到与项目同级目录下,如app是放在目录APP下面,即项目目录路径为'APP/app/',则thinkphp应解 ...