在Excel 2016中的office js的共享API中使用Async函数时,会导致内存泄漏,特别是调用binding.setDataAsnyc
,它永远不会释放写入的数据。(泄漏发生在 Internet Explorer 进程在excel中运行插件(它是32位版本))。
示例:
//1 Miliion row by 10 columns data parsed from a csv usually in chunks
var data = [];
var i,j;
for (i=0; i<1000000; i++) {
row = [];
for(j=0; j<10; j++) {
row.push("data" + i + "" + j);
}
data.push(row);
}
var limit = 10000;
var next = function (step) {
var columnLetter = getExcelColumnName(data[0].length);
var startRow = step * limit + 1;
var endRow = start + limit;
if (data.length < startRow)
return;
var values = data.slice(startRow - 1, endRow - 1);
var range = "A" + startRow + ":" + columnLetter + "" + endRow;
Office.context.document.bindings.addFromNamedItemAsync(range,
Office.CoercionType.Matrix, { id: "binding" + step },
function (asyncResult) {
if (asyncResult.status == "failed") {
console.log('Error: ' + asyncResult.error.message);
return;
}
Office.select("bindings#binding" + step).setDataAsync(values,
{
coercionType: Office.CoercionType.Matrix
}, function (asyncResult) {
//Memory keeps Increasing on this callback
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
console.log("Action failed with error: " + asyncResult.error.message);
return;
}
next(step++);
});
});
}
next(0);
我尝试在setDataAsync
之后释放每个绑定,但仍然存在内存。回收内存的唯一方法是重新加载插件。
我尝试了另一种为范围分配值的方法:
range.values = values;
它没有泄漏但是需要3倍于setDataAsync
(对于1M行乘以10列大约210秒),而setDataAsync
大约需要70秒,但当然泄漏并消耗1.1该请求中的GB内存。
我也试过table.rows.add(null, values);
,但表现得更差。
我在没有setdataAsync
的情况下测试了相同的代码(立即调用)并且没有发生内存泄漏。
有没有人遇到过这种情况? 反正它是否有释放那个记忆? 如果没有另外的方法来填充Excel中的大量数据,除了这三种方法也很快?
答案 0 :(得分:0)
添加绑定确实会增加内存消耗 - 但只是调用setDataAsync
肯定不应该(或者至少不是超出预期,或者通过手动将数据复制粘贴到工作表中)会是)。
有一点需要澄清:当你说:
我也试过了
table.rows.add(null, values)
,但效果更差。
我假设您的意思是使用Excel.run(function(context) { ... });
执行备用Office 2016 wave-of-API语法?关于perf,我可以跟进,但是我很好奇当你使用新的API语法时是否发生了内存泄漏。
FWIW,有一个近期未来的API将允许您在设置值时暂停计算 - 这应该可以提高性能。但我确实想知道我们是否能找出你指出的两个问题:setDataAsync
和range.values
电话上的内存泄漏。
如果您可以从回答上述问题开始(即使在range.values
中是否发生同样的泄漏),这将有助于缩小问题范围,然后我会跟进团队。
谢谢!
答案 1 :(得分:0)
我发现有一个布尔window.Excel._RedirectV1APIs
可以设置为true
,使setDataAsync
使用新的API。如果
window.Office.context.requirements.isSetSupported("RedirectV1Api")
返回true但不知何故该要求未设置,但如果您手动设置
则它可以正常工作 window.Excel._RedirectV1APIs = true
但它仍然比原始setDataAsync
慢得多,但比range.values
手动方法略快(对于1M行乘以10列,160s对180s)并且不会导致内存泄漏。
另外,我发现内存泄漏发生在id {71(window.external.Execute(id, params, callback)
)的setDataAsnyc
函数之后,并且在从该函数调用回调时,似乎内存泄漏在某种程度上发生在/中Excel本身的外部代码(虽然内存泄漏是在Internet Explorer的过程中)。如果你短路并直接调用回调而不是window.external.Execute
没有发生内存泄漏,当然,也没有设置数据。