我们有一个相当大的 Excel 工作簿。大约 3,300 列和数千行。我们发现,尝试对数据执行任何操作都会导致内存使用量很高,大约为 3 GB。似乎DocumentFormat.OpenXml包在迭代时将工作表的完整对象结构保留在内存中。一般来说,我们是这样做的:var workbookPart = _document.WorkbookPart;var worksheets = workbookPart.Workbook.Descendants<Sheet>();foreach(var worksheet in worksheets){ var worksheetPart = (WorksheetPart) workbookPart.GetPartById(worksheet.Id); foreach(var row in worksheetPart.Worksheet.Descendants<Row>()) { foreach(var cell in row.Descendants<Cell>()) { var (_, value) = ParseCell(cell); } }}ParseCell只需Cell通过从SharedStringTable工作簿上查找字符串值来获取 的内容,或者如果它是数字,则解析该数字。简单地运行这段代码,结果ParseCell仍然使用大量内存。当我们分析这段代码时,我们注意到Cell尽管我们尽了最大努力使用IEnumerable<T>API 来避免内存中的大型集合,但我们注意到堆上的每个单元格都在工作表中。这与此 Nuget 包的推荐用法非常接近。从分析来看,问题似乎是每个Cell都对下一个有很强的引用Cell,对于Row.每个Cell都有一个名为的字段,_next这使每个 Cell 具有强大的根。单元格 A 与单元格 B、B 至 C、C 至 D 具有强引用。Row具有类似的结构,其中第 0 行有一个_next指向第 1行的字段,依此类推,因此对于Row我们经过的每个,它都保持对下一个 的强引用Row。所以一切都联系在一起。当我在处理Row完最后一个之后用 WinDbg 查看这个时,Cell堆上的s数量正好!dumpheap -stat与工作簿包含的s相同。我们使用此 SDK 的方式不会扩展到更多行。有没有办法更有效地使用这个包并逐行处理工作表,而不会将整个工作表的对象图保存在内存中?
1 回答
- 1 回答
- 0 关注
- 196 浏览
添加回答
举报
0/150
提交
取消