繁体   English   中英

测量电子表格内置函数的执行时间

[英]Measurement of execution time of built-in functions for Spreadsheet

Spreadsheet 的内置函数完成后,是否有测量执行时间的方法? 当我使用几个内置函数(例如,IMPORTHTML 和 IMPORTXML)时,如果我知道平均执行时间,我就很容易使用和设计数据表。

我使用此脚本测量自定义函数。

function myFunction() {
  var start = new Date();

  // do something

  var end = new Date();
  var executiontime = end - start;
}

非常感谢您的时间和建议。

不幸的是,没有用于检索内置函数执行时间的测量工具。 @Rubén 已经对此发表了评论。 所以我想到了解决方法。 以下解决方法如何?

流程:

  1. 将值导入单元格。 值是好的,因为它被用作触发器。 请自行完成。
    • 自定义函数不能使用setValue() 所以我使用了onEdit()
  2. func1()导入一个公式,您希望通过触发器启动的脚本测量执行时间。
  3. func2() ,设置公式后,开始测量。 内置函数完成时的确认使用循环进行。
    • 通过测量每次调用getValue()的成本,发现大约为 0.0003 秒。 所以我认为这个可以使用。
  4. 测量结果可以在 Stackdriver 上看到,以毫秒为单位。

示例脚本:

function func1(range, formula){
  range.setFormula(formula);
}

function func2(range){
  var d = range.getValue();
  while (r == d) {
    var r = range.getValue();
  }
}

function onEdit(){
  var formula = '### Built-in function ###'; // Please set the built-in function you want to measure the execution time.

  var label = "Execution time for built-in functions.";
  var ss = SpreadsheetApp.getActiveSheet();
  var cell = ss.getActiveCell();
  var range = ss.getRange(cell.getRow(), cell.getColumn());
  func1(range, formula);
  console.time(label);
  func2(range);
  console.timeEnd(label);
}

注意:

  • 当测量时间很长的内置函数时, getValue()可能会发生错误。
    • 在我的环境中,10 秒的内置函数运行良好。

2020 年 11 月 11 日更新:

作为附加信息,我想再添加一个示例脚本,用于测量电子表格的内置函数完成时的执行时间以及使用该脚本的结果。

这是一个简单的示例脚本,用于测量单元上函数的过程成本。 一开始,为了确认这个脚本是否可以用于衡量一个单元格中函数的处理成本,使用了一个自定义函数。 因为在使用自定义函数时,可以通过Utilities.sleep(time)知道脚本的处理时间。

示例脚本:

当您测试此脚本时,请将以下脚本复制并粘贴到 Google 电子表格的容器绑定脚本中。 当您运行main()函数时,可以获得=SAMPLE(5000)的过程成本。

// This is a sample custom formula. This is used for testing.
function SAMPLE(time) {
  Utilities.sleep(time);
  return "ok";
}

// This is a script for measuring the process cost.
function main() {
  const obj = { formula: `=SAMPLE(5000)`, returnValue: "ok" }; // Set formula and response value.

  const label = "Execution time";
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
  const range = sheet.getRange("A1");
  range.clear();

  // start --- measure
  console.time(label);
  range.setFormula(obj.formula);
  SpreadsheetApp.flush();
  while (range.getDisplayValue() != obj.returnValue) {}
  console.timeEnd(label);
  // end --- measure

  range.clear();
}
  • 在此示例中,当将=SAMPLE(5000)放入单元格时,5 秒后单元格中会显示ok的值。 main()测量此的处理时间。
  • 此示例脚本检查函数的输出值。 所以请设置returnValue 请注意这一点。
  • 在Spreadsheet的公式中,当公式被放入单元格时,处理时间的测量就开始了。 所以在这个示例中,我包含了setFormulaflush到测量的过程成本。

实验结果:

在此处输入图片说明

作为一个实验,它显示了进程时间随着自定义函数睡眠时间的增加而发生的变化,如上图所示。 该结果表明处理时间随着睡眠时间的增加而线性增加。 发现处理时间至少比睡眠时间长,并且处理时间较大,以每个睡眠时间为偏移量在0.5 s左右。 认为这个偏移量包括setFormulaflushgetDisplayValue和 while 循环的过程成本。 但是,从这张图中,可以认为当使用上述脚本衡量各种公式的过程成本时,可以通过相对比较来比较。 并且从这个结果来看,可以认为上面的脚本可以用来测量函数在电子表格单元格中的执行时间。

参考:

Google 表格不包含用于测量重新计算时间的内置工具。

一种替代方法是使用Chrome 开发人员工具时间轴,但请记住,不会在每次电子表格执行时重新计算 IMPORTHTML 和 IMPORTXML 等功能(请参阅设置电子表格的位置和计算设置)。

相关问答

网络应用程序

可以制作一个命名为 Function(只是为了使其易于重用)来仅使用公式来衡量公式执行情况,而无需脚本。

BENCHMARK()

BENCHMARK() (以秒为单位返回执行时间):

=N(
  REDUCE(
    0,
    {0; 1; 0},
    LAMBDA(
      acc,
      cur,
      IF(
        cur = 0,
          LAMBDA(x, x)(NOW()) - acc,
          acc + 0 * ROWS(func())
      )
    )
  ) * 24 * 60 * 60
)

它的单个参数是func - 一个 function 来运行和计时它的执行。 您只需得到一个工作公式,将其包含在LAMBDA()中并传递给BENCHMARK() 例子在底部。

BENCHMARKN()

BENCHMARKN()

=N(
  REDUCE(
    0,
    {0; SEQUENCE(number); 0},
    LAMBDA(
      acc,
      cur,
      IF(
        cur = 0,
          LAMBDA(x, x)(NOW()) - acc,
          acc + 0 * ROWS(func())
      )
    )
  ) * 24 * 60 * 60 / number
)

还有一个参数number : func会循环执行number次。 然后总执行时间将除以number以获得平均执行时间。

UPD:LAMBDA(x, x)(NOW())中包含NOW() () 会冻结该值并防止因工作表中的任何更改而导致的重新计算。 这里得到它。

例子

比方说,我们想要对从 1 到 1000000 的所有自然数的平方求和。所以我们有我们的公式:

=SUM(ARRAYFORMULA(SEQUENCE(1000000)))

我们这样计时:

=BENCHMARK(LAMBDA(SUM(ARRAYFORMULA(SEQUENCE(1000000)^2))))

在这样的 10 步循环中:

=BENCHMARKN(LAMBDA(SUM(ARRAYFORMULA(SEQUENCE(1000000)^2))), 10)

在此处输入图像描述

这是我计算 ArrayFormulas 之间差异的选项:

  1. 使用示例数据创建模板
  2. 设置脚本:更改包含公式的数组、模板电子表格 ID、设置公式的单元格地址、迭代值的单元格地址。

这个 function 将测试 2 个或更多公式:

  1. 复制示例文件以隔离先前迭代的影响。
  2. 设置公式并计算第一次计算的时间
  3. 在循环中编辑源数据并计算公式重新计算所需的时间。

样本 output,绘制在表格中:

公式速度测试 ↑ 测试公式取自这个问题

y-axis是处理时间, bars是脚本的迭代。

  • 低条是插入公式的时间,
  • 更高的条是值更改时重新计算公式的时间。

代码

function test_formulas_speed() {

  /**  Options ↓ ********************************************************************************************* */
  // https://docs.google.com/spreadsheets/d/1vQu7hVr7FwH8H5N8JOlOGfvjlJgKtpfoM2DPPjgUaLo/template/preview
  var testSpreadsheetId = '1vQu7hVr7FwH8H5N8JOlOGfvjlJgKtpfoM2DPPjgUaLo';
  var formulas = [
    '=INDEX(if(A2:A="",,LAMBDA(srt, SORT(SCAN(0,MAP(SEQUENCE(ROWS(A2:A)),LAMBDA(v,if(v=1,0,if(INDEX(srt,v,1)<>INDEX(srt,v-1,1),1,0)))),LAMBDA(ini,v,IF(v=1,1,ini+1))),index(srt,,2),1) ) (SORT({A2:A,SEQUENCE(ROWS(A2:A))}))))',

    '=LAMBDA(a,INDEX(if(a="",,COUNTIFS(a,a,row(a),"<="&row(a)))))(A2:A)'

  ];
  // value from the first cell of arrayformula ↓
  var returnValue = 1;
  // range to insert the formula
  var rA1 = 'B2';
  var sheetName = 'Sheet1';
  var iterations = 5;

  var testChangeRaangeA1 = 'A5';
  var sub_iterations = 5; // the number of times to change the value
  /**  Options ↑ ********************************************************************************************* */

  
  var results = [];
  var file = DriveApp.getFileById(testSpreadsheetId);
  var results = []
  var testOne_ = function(formula, indx) {
    // prepare
    var copy = file.makeCopy();
    var id = copy.getId();
    var ss = SpreadsheetApp.openById(id);
    var s = ss.getSheetByName(sheetName);
    var r = s.getRange(rA1);
    var rCh = s.getRange(testChangeRaangeA1);
    var addToResult = function(t) {
      var result = new Date() - t;
      if (results[indx]) {
        results[indx].push(result);
      } else {
        results[indx] = [result];
      }
    }

    // measure time
    var t = new Date();
    r.setFormula(formula);
    SpreadsheetApp.flush();
    // loop until expected value is returned
    while (r.getDisplayValue() != returnValue) {}
    addToResult(t);
    for (var i = 0; i < sub_iterations; i++) {
      t = new Date();
      // clear the cells, because of the internal cache
      rCh.clearContent();
      rCh.setValue(i);
      SpreadsheetApp.flush();
      addToResult(t);
    }

    // clean up
    copy.setTrashed(true);

    return 0;
  }

  for (var i = 0; i < iterations; i++) {
    formulas.forEach(testOne_);
  }
  
  console.log(results);

}

参考:

这个基准来自@Tanaikech

要添加另一个选项,您可以执行以下操作:

function myFunction() {
  console.time('someFunction');

  // do something

  console.timeEnd('someFunction');
}

然后查看函数执行的 Stackdriver 日志。

示例输出将是:

Jul 3, 2020, 1:03:00 AM Debug someFunction: 80ms

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM