1.对于韩国人写得jxl的问题(原创工作总结)
最近用jxl做得模板导出数据出现了严重的性能问题:
(1)在main方法中运行此业务逻辑时间大约1.662秒,打印时间如图:
虚拟机运行情况如图:
(2)在Tomcat中运行此业务逻辑时间大约62.182秒,打印时间如图:
虚拟机运行情况如图:
(3)分析情况
通过数据和图表认真分析,main方法之所以运行快,因为JVM里面没有大量的垃圾回收,占用的内存又不是很大,jxl进行垃圾回收时,占用的消耗时间不大。
在tomcat运行中,可以看到JVM里面程序占用的内存比较大,有垃圾存在,每次进行垃圾回收,都会占用大量的时间。
通过数据分析,main方法的垃圾回收时间很多安基本上忽略不计,而在tomcat里,由于模板总共有47个模板工作表,每个工作表获取数据,要调用3次垃圾回事,每次大约用时0.4秒多,每个工作表用时1.3秒以上,通过计算,大约是60秒以上,可见对整个数据导出占用了大量的时间。
(4)源码分析
代码调用处:
Workbook wb = Workbook.getWorkbook(file);
WritableWorkbook wwb = Workbook.createWorkbook(new File(dstFile),wb);
此程序相当于打开一个文件的副本,进行修改数据,然后回写到源文件
产生慢的原因:
产生一个workbook,读取文件
/**
* A factory method which takes in an excel file and reads in the contents.
*
* @exception IOException
* @exception BiffException
* @param file the excel 97 spreadsheet to parse
* @return a workbook instance
*/
public static Workbook getWorkbook(java.io.File file)
throws IOException, BiffException
{
return getWorkbook(file, new WorkbookSettings());
}
下面这个类的一些参数就是在读取或写入工作簿时用到的(根据一些参数处理)
/**
* This is a bean which client applications may use to set various advanced
* workbook properties. Use of this bean is not mandatory, and its absence
* will merely result in workbooks being read/written using the default
* settings
*/
public final class WorkbookSettings
看一下它的构造器:
/**
* Default constructor
*/
public WorkbookSettings()
{
initialFileSize = DEFAULT_INITIAL_FILE_SIZE;
arrayGrowSize = DEFAULT_ARRAY_GROW_SIZE;
localeFunctionNames = new HashMap();
excelDisplayLanguage = CountryCode.USA.getCode();
excelRegionalSettings = CountryCode.UK.getCode();
refreshAll = false;
template = false;
excel9file = false;
windowProtected = false;
hideobj = HIDEOBJ_SHOW_ALL;
// Initialize other properties from the system properties
try
{
boolean suppressWarnings = Boolean.getBoolean("jxl.nowarnings");
setSuppressWarnings(suppressWarnings);
drawingsDisabled = Boolean.getBoolean("jxl.nodrawings");
namesDisabled = Boolean.getBoolean("jxl.nonames");
gcDisabled = Boolean.getBoolean("jxl.nogc");
rationalizationDisabled = Boolean.getBoolean("jxl.norat");
mergedCellCheckingDisabled =
Boolean.getBoolean("jxl.nomergedcellchecks");
formulaReferenceAdjustDisabled =
Boolean.getBoolean("jxl.noformulaadjust");
propertySetsDisabled = Boolean.getBoolean("jxl.nopropertysets");
ignoreBlankCells = Boolean.getBoolean("jxl.ignoreblanks");
cellValidationDisabled = Boolean.getBoolean("jxl.nocellvalidation");
autoFilterDisabled = !Boolean.getBoolean("jxl.autofilter");
// autofilter currently disabled by default
useTemporaryFileDuringWrite =
Boolean.getBoolean("jxl.usetemporaryfileduringwrite");
String tempdir =
System.getProperty("jxl.temporaryfileduringwritedirectory");
if (tempdir != null)
{
temporaryFileDuringWriteDirectory = new File(tempdir);
}
encoding = System.getProperty("file.encoding");
}
catch (SecurityException e)
{
logger.warn("Error accessing system properties.", e);
}
// Initialize the locale to the system locale
try
{
if (System.getProperty("jxl.lang") == null ||
System.getProperty("jxl.country") == null)
{
locale = Locale.getDefault();
}
else
{
locale = new Locale(System.getProperty("jxl.lang"),
System.getProperty("jxl.country"));
}
if (System.getProperty("jxl.encoding") != null)
{
encoding = System.getProperty("jxl.encoding");
}
}
catch (SecurityException e)
{
logger.warn("Error accessing system properties.", e);
locale = Locale.getDefault();
}
}
其中, gcDisabled = Boolean.getBoolean("jxl.nogc");这个是读取这个是否垃圾回收的参数,默认是false
就是这个这个参数导致读取sheet对象非常的慢,下面会继续进行分析。
Workbook.createWorkbook(new File(dstFile),wb); 这个方法调用了WorkBook
咱们来进行一些简单的分析:
/**
* Creates a writable workbook with the given filename as a copy of
* the workbook passed in. Once created, the contents of the writable
* workbook may be modified
*
* @param file the output file for the copy
* @param in the workbook to copy
* @return a writable workbook
* @exception IOException
*/
public static WritableWorkbook createWorkbook(java.io.File file,
Workbook in)
throws IOException
{
return createWorkbook(file, in, new WorkbookSettings());
}
这个类相当于产生对Excel修改对象,产生的是一个原文件副本的修改回写
/**
* Creates a writable workbook with the given filename as a copy of
* the workbook passed in. Once created, the contents of the writable
* workbook may be modified
*
* @param file the output file for the copy
* @param in the workbook to copy
* @param ws the configuration for this workbook
* @return a writable workbook
*/
public static WritableWorkbook createWorkbook(java.io.File file,
Workbook in,
WorkbookSettings ws)
throws IOException
{
FileOutputStream fos = new FileOutputStream(file);
WritableWorkbook w = new WritableWorkbookImpl(fos, in, true, ws);
return w;
}
此处分析下:WritableWorkbook w = new WritableWorkbookImpl(fos, in, true, ws);中的WritableWorkbookImpl类。
/**
* A pseudo copy constructor. Takes the handles to the font and formatting
* records
*
* @exception IOException
* @param w the workbook to copy
* @param os the output stream to write the data to
* @param cs TRUE if the workbook should close the output stream, FALSE
* @param ws the configuration for this workbook
*/
public WritableWorkbookImpl(OutputStream os,
Workbook w,
boolean cs,
WorkbookSettings ws) throws IOException
{。。。。。。。。。。。。。。。。。。。}
这个构造方法中调用了copyWorkbook(w);,实现了对原Excel文件数据对象的拷贝,相当于一个副本
/**
* Produces a writable copy of the workbook passed in by
* creating copies of each sheet in the specified workbook and adding
* them to its own record
*
* @param w the workbook to copy
*/
private void copyWorkbook(Workbook w)
{
int numSheets = w.getNumberOfSheets();
wbProtected = w.isProtected();
Sheet s = null;
WritableSheetImpl ws = null;
long start= System.currentTimeMillis();
for (int i = 0 ; i < numSheets; i++)
{
long starts= System.currentTimeMillis();
s = w.getSheet(i);
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"+( System.currentTimeMillis() - starts)/1000.0+" 秒");
long start3= System.currentTimeMillis();
ws = (WritableSheetImpl) createSheet(s.getName(),i, false);
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"+s.getName());
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"+( System.currentTimeMillis() - start3)/1000.0+" 秒");
long start2= System.currentTimeMillis();
ws.copy(s);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"+( System.currentTimeMillis() - start2)/1000.0+" 秒");
}
long start1= System.currentTimeMillis();
System.out.println("********************************************************************"+(start1 - start)/1000.0+" 秒");
}
分析下这个影响性能的地方:s = w.getSheet(i);
sheet的实现类是:SheetImpl (public class SheetImpl implements Sheet)
这个类的构造器:
SheetImpl(File f,
SSTRecord sst,
FormattingRecords fr,
BOFRecord sb,
BOFRecord wb,
boolean nf,
WorkbookParser wp)
throws BiffException
{
excelFile = f;
sharedStrings = sst;
formattingRecords = fr;
sheetBof = sb;
workbookBof = wb;
columnInfosArray = new ArrayList();
sharedFormulas = new ArrayList();
hyperlinks = new ArrayList();
rowProperties = new ArrayList(10);
columnInfosInitialized = false;
rowRecordsInitialized = false;
nineteenFour = nf;
workbook = wp;
workbookSettings = workbook.getSettings();
}中的workbookSettings = workbook.getSettings();就是WorkBook的参数的传递,里面有垃圾回收的控制参数
看一下WorkBook具体实现类WorkbookParser获取sheet的方法:
/**
* Gets the specified sheet within this workbook
*
* @param index the zero based index of the required sheet
* @return The sheet specified by the index
*/
public Sheet getSheet(int index)
{
// First see if the last sheet index is the same as this sheet index.
// If so, then the same sheet is being re-requested, so simply
// return it instead of rereading it
if ((lastSheet != null) && lastSheetIndex == index)
{
return lastSheet;
}
// Flush out all of the cached data in the last sheet
if (lastSheet != null)
{
lastSheet.clear();
if (!settings.getGCDisabled())
{
System.gc();
}
}
lastSheet = (SheetImpl) sheets.get(index);
lastSheetIndex = index;
lastSheet.readSheet();
return lastSheet;
}
从此方法中可以看出调用了垃圾回收 if (!settings.getGCDisabled()){
System.gc();
}
在 lastSheet.clear();中看下clear方法也调用垃圾回收方法
final void clear()
{
cells = null;
mergedCells = null;
columnInfosArray.clear();
sharedFormulas.clear();
hyperlinks.clear();
columnInfosInitialized = false;
if (!workbookSettings.getGCDisabled())
{
System.gc();
}
}
在readSheet()方法中也调用了垃圾回收方法
/**
* Reads in the contents of this sheet
*/
final void readSheet()
if (!workbookSettings.getGCDisabled())
{
System.gc();
}
可以源码分析到复制副本,一个sheet总共用了3次垃圾回收,导致时间消耗很大。
为了提高性能,做了如下程序的修改:
jxl在读取excel的时候,关闭了手工垃圾回收
System.setProperty("jxl.nogc","true");
或者
fis = new FileInputStream(file);
WorkbookSettings wbs = new WorkbookSettings();
wbs.setGCDisabled(true);
wb = Workbook.getWorkbook(fis,wbs);
WorkbookSettings wbss = new WorkbookSettings();
wbss.setGCDisabled(true);
wwb = Workbook.createWorkbook(new File(dstFile),wb,wbss);
垃圾回收器"也许并不像许多人想象的一样会立即执行(当堆中的资源需要释放时),而是在引用类型的引用被删除和它在"堆"中的对象实例被删除中间有个间隔,为什么呢? 因为"垃圾回收器"的调用是比较消耗系统资源的,因此不可能经常被调用! (当然,用户代码可以用方法System.GC.Collect()来强制执行"垃圾回收器")
相关推荐
3. **1.7万+**:标题中提到的数字表示词库包含超过1.7万个词汇或短语,这代表了一个相当大的资源库,对于内容创作者来说,可以提供丰富的选择来替换原文中的词语,增强文章的原创性。 4. **最新词库**:标签中的...
版权法保护原创性的文学、艺术作品,如书籍、音乐、电影等。创作者拥有对其作品的复制、发行、展示和改编等权利。作品一旦完成,版权自动产生,无需注册。然而,为了更好地保护权益,通常会进行版权登记。 五、商业...
6. **数据驱动**:利用数据分析工具,收集并分析相关数据,通过数据背后的故事揭示新的知识或见解。 7. **创新思维**:尝试打破常规,运用创新的思维方式,提出新颖的观点和策略。 在创作过程中,我们还需要注意...
为了深入研究,文章采用了案例搜集的方法,收集了9个相关案例,其中3个涉及作品设计方案征集竞赛,虽然并非严格意义上的招投标,但同样反映了知识产权侵权问题。这些案例涵盖了工程招标、货物采购等多个领域,揭示了...
3. **内容处理**:抓取到的内容通过伪原创算法进行关键词替换,使每篇内容尽可能地显得独特,减少被搜索引擎视为重复内容的风险。 4. **发布与更新**:处理后的数据可以发布到用户的网站或者存储起来,以供后续使用...
3. **调查单位与调查对象**:调查单位是调查中具体收集数据的对象,而调查对象是调查所覆盖的整个群体。 4. **调查表**:它是数据收集的工具,有多种类型,如简单表、复合表和复合分组表。 5. **统计调查的种类**:...
不同于农业经济依赖土地和自然资源,工业经济依赖技术、资本和劳动力,服务经济依赖各种非实体服务,知识经济中的知识具有原创性和创新性,不再局限于传统传承,而是直接应用于生产过程,成为主要的生产要素。知识...
研究目的:“知识”一词被认为是每个教育机构中最重要的资产,管理知识被认为很难在教育机构中取得成功... 原创性:本文的主要目标是研究位于钦奈地区的工程学院和艺术与科学学院的学术人员之间知识共享的决定性因素。
3. 数据库管理:数据库系统如MySQL、MongoDB等用于存储用户信息、订单记录、知识内容等数据。 4. 支付接口:集成微信支付SDK,实现用户支付功能,确保交易安全。 三、知识付费小程序的运营策略 1. 内容质量:提供...
3. **时间管理**:时间管理关乎项目的进度,涉及规划进度管理,确定活动的开始和结束时间;活动定义,识别项目中的所有任务;排序活动顺序,确定逻辑关系;估算活动资源,预测所需的人力和其他资源;估算活动持续...
3. 消化信息:收集的信息需要经过分析和理解才能真正转化为自己的知识。通过分析图片的构图、排版、色彩、光影等方面,结合设计目的理解设计师的意图和使用的方法。 4. 回顾、思考、创新:定期回顾已消化的知识,...
根据提供的信息,我们可以总结出以下相关的C#知识点: ### C#常用函数库 - 对象转换与压缩解压 #### 对象转换为byte数组 在C#编程中,经常需要将对象序列化为byte数组以便于在网络中传输或者保存到文件中。这个...
3. **知识产权代理的重要性**: - 保护创新:知识产权代理有助于保护企业的核心竞争力,防止技术泄露或被竞争对手抄袭。 - 市场竞争:通过注册商标和专利,企业可以树立品牌形象,阻止他人仿冒,增强市场竞争力。 ...
- 软件复杂性增加,开发成本高,且大多数是原创开发。 - 社会因素对软件工程有重要影响。 4. **遗留软件与软件演化**: - 系统演化以适应新技术、业务需求和网络环境的变化。 - 30年来软件发展的规律,如持续...
这篇硕士学位论文的原创声明和使用授权说明涉及到两个主要方面,一是学术诚信,二是知识产权和版权管理。 首先,原创性声明是学术研究中的重要环节,它表明作者对其论文内容的原创性和独立性负责。在这份声明中,...
这些特性使得大数据的收集、处理和利用变得复杂,同时也对传统知识产权法提出了新的要求。 在大数据的收集过程中,涉及的知识产权问题主要是数据的来源与所有权。原始数据可能包含他人的知识产权,如版权、数据库...
3) 在知识产权管理方面,大数据的自动化能力简化了管理流程,降低了人力和成本,推动了企业知识产权管理的创新。 然而,大数据也带来了消极影响,尤其是在知识产权授权和专利保护上。大数据导致数据量急剧增加,...
统计学是研究数据收集、分析、解释和呈现的科学,对于理解和决策有着至关重要的作用。在统计学的学习中,理解并掌握各个章节的关键知识点至关重要,尤其是对于期末复习和考试而言。以下是对统计学各章节复习知识点的...
如果不对数据库的知识产权进行保护,原创者的辛勤努力可能会被忽视,导致原创者失去应有的回报,不利于激励更多的创新活动。 (三)维护市场竞争秩序数据库作为一种重要的信息资源,如果缺乏有效的知识产权保护,...