【问题标题】:Office JS setDataAsync function memory leakOffice JS setDataAsync 函数内存泄漏
【发布时间】:2017-03-20 16:48:37
【问题描述】:

在 Excel 2016 的 office js 的共享 API 中使用异步函数时,会导致内存泄漏,特别是调用 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;

它不会泄漏,但花费的时间是 setDataAsync 的 3 倍(1M 行 x 10 列大约需要 210 秒),而 setDataAsync 大约需要 70 秒,但当然会泄漏并在该请求中消耗 1.1 GB 内存.

我也试过table.rows.add(null, values);,但性能更差。

我在没有setdataAsync 的情况下测试了相同的代码(立即调用 next)并且没有发生内存泄漏。

有其他人经历过吗? 无论如何,它周围有释放记忆吗? 如果没有,除了这3种方法也很快,还有其他方法可以在Excel中填充大量数据吗?

【问题讨论】:

    标签: excel memory-leaks ms-office office-js office-addins


    【解决方案1】:

    添加绑定确实会增加内存消耗——但只是调用setDataAsync 绝对不应该(或者至少,不会超出您的预期,或者不会超过手动将数据复制粘贴到工作表中)。

    有一点要澄清:当你说:

    我也试过table.rows.add(null, values),但性能更差。

    我假设您的意思是使用 Excel.run(function(context) { ... });? 执行备用 Office 2016-wave-of-APIs 语法?我可以跟进 perf,但我很好奇当您使用新的 API 语法时是否也会发生内存泄漏。

    FWIW,在不久的将来会有一个 API 允许您在设置值时暂停计算——这应该会提高性能。但我确实想看看我们能否解决您指出的两个问题:setDataAsyncrange.values 调用上的内存泄漏。

    如果您可以从回答上面的问题开始(即使在range.values 中是否也会发生同样的泄漏),这将有助于缩小问题范围,然后我会跟进团队。

    谢谢!

    【讨论】:

    • 不,range.values(在Excel.run 内部)不会泄漏内存,但正如所说,它比 setDataAsync 慢得多(慢 3 倍)。我也尝试在每个setDataAsync 之后调用releaseByIdAsync,但内存仍然没有释放。
    • 好的,完美,感谢您提供的信息。让我把它交给团队调查。
    • 谢谢,新 API 上是否有任何 ETA 改进了设置值?
    • @MahmoudBahaa,最早可能是从现在开始的 3 个月(简单的物理学——1.5 ExcelApis 刚刚发货,应该在“完成”后的大约 2 个月内公开发布;所以既然它不是那列火车的一部分,它会是之后的东西。所以,虽然我不能保证任何事情,但 3-6 个月范围内的东西可能是一个不错的猜测)。
    【解决方案2】:

    我发现有一个布尔值window.Excel._RedirectV1APIs 可以设置为true,这使得setDataAsync 使用新的API。如果

    应该自动设置

    window.Office.context.requirements.isSetSupported("RedirectV1Api")

    return true 但不知何故该要求未设置,但如果您手动设置它就可以工作

    window.Excel._RedirectV1APIs = true

    但它仍然比原生 setDataAsync 慢得多,但比 range.values 手动方法稍快(160 秒 vs 180 秒,1M 行乘 10 列)并且不会导致内存泄漏。

    另外,我发现内存泄漏发生在 window.external.Execute(id, params, callback) 函数 id: 71 (setDataAsnyc) 之后并从该函数调用回调,所以似乎内存泄漏以某种方式发生在/因为外部代码Excel 本身(尽管内存泄漏是在 Internet Explorer 进程中)。如果你短路并直接调用回调而不是window.external.Execute,则不会发生内存泄漏,但当然也不会设置任何数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      • 2018-03-03
      • 1970-01-01
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多