【问题标题】:Bug when attempting to time my JavaScript functions尝试对我的 JavaScript 函数计时时出现错误
【发布时间】:2016-07-06 16:47:50
【问题描述】:

我面临的挑战本质上是:给定一个数字数组作为输入,在 j input[j] 的情况下,找出任意两个数字之间的最大差。

我写了两个解决方案,一个是蛮力双嵌套循环,另一个是我尝试优化它。它们如下:

// Brute Force Method
function findGreatestDiffV1(nums) {
  let start = new Date().getTime();
  let greatestDiff = 0;
  for (let i = 1; i < nums.length; i++) {
    for (let j = 0; j < i; j++) {
      let diff = nums[i] - nums[j];
      if (diff > greatestDiff) greatestDiff = diff;
    }
  }
  console.log(((new Date().getTime() - start) / 1000.0) + " Seconds");
  return greatestDiff;
}

// Optimized method
function findGreatestDiffV2(nums) {
  let start = new Date().getTime();
  let smallestNum = nums[0];
  let greatestDiff = 0;
  for (let i = 1; i < nums.length; i++) {
    if (nums[i] < smallestNum) smallestNum = nums[i];
    if ((nums[i] - smallestNum) < greatestDiff) continue;
    for (let j = 0; j < i; j++) {
      let diff = nums[i] - nums[j];
      if (diff > greatestDiff) greatestDiff = diff;
    }
  }
  console.log(((new Date().getTime() - start) / 1000.0) + " Seconds");
  return greatestDiff;
}

这些工作正常,并且输出正确的结果以及预期的运行时间,即对于较大数据集的 V2 显着降低。

然后我将它们修改为只返回运行时间:

function findGreatestDiffV1Time(nums) {
  let start = new Date().getTime();
  let greatestDiff = 0;
  for (let i = 1; i < nums.length; i++) {
    for (let j = 0; j < i; j++) {
      let diff = nums[i] - nums[j];
      if (diff > greatestDiff) greatestDiff = diff;
    }
  }
  return ((new Date().getTime() - start) / 1000.0);
}

function findGreatestDiffV2Time(nums) {
  let start = new Date().getTime();
  let smallestNum = nums[0];
  let greatestDiff = 0;
  for (let i = 1; i < nums.length; i++) {
    if (nums[i] < smallestNum) smallestNum = nums[i];
    if ((nums[i] - smallestNum) < greatestDiff) continue;
    for (let j = 0; j < i; j++) {
      let diff = nums[i] - nums[j];
      if (diff > greatestDiff) greatestDiff = diff;
    }
  }
  return ((new Date().getTime() - start) / 1000.0);
}

我创建了这个辅助函数,它生成长度为 numOfDiffs 和最大个体数 maxDiff 的输入:

function generateDiffs(numOfDiffs, maxDiff) {
  let diffs = [];
  for (let i = 0; i < numOfDiffs; i++) {
    diffs.push(Math.floor(Math.random() * maxDiff));
  }
  return diffs;
}

但是,这就是事情出问题的地方,我不知道为什么。

当使用仅返回运行时的版本时,无论输入的大小如何,V1 的时间都为 0。 V2 正在返回任何大小集的正确时间,但 V1 几乎立即继续逃逸并返回 0。

最可能的问题是我在某处有一个明显的错误,但我想知道这是否可能是对 JavaScript 如何执行某些功能的一些误解,甚至是某处的范围溢出。但无论如何,我找不到它,这让我发疯。

【问题讨论】:

  • 我怀疑 Javascript 编译器已经注意到你在循环之后从不使用任何变量,所以它优化了整个循环。
  • 我不确定为什么 V2 不会发生这种情况,可能循环太复杂而无法分析。
  • 尝试更改它们以返回包含最大差异和时间的对象。
  • 您可以使用performance.now 进行计时。
  • 非常有趣。无论你在哪里运行它都会这样做吗?我无法在我的任何浏览器中重现:jsfiddle.net/b0dm98ds

标签: javascript debugging time


【解决方案1】:

所以,@Barmar 就是这里的人。 Chrome 绝对是在尝试通过跳过它所看到的所有内容从未被函数返回来优化我的代码。一旦我将返回值更改为

return [((new Date().getTime() - start) / 1000.0), greatestDiff];

我开始得到预期的结果。

有趣的是我没有在 V2 中获得这个;正如 Barmar 所说,更复杂的指令很可能导致 Chrome 在谨慎方面犯错。

另外,为了记录,这是我编写的用于计算运行时间的函数。

function runTimes(numOfDiffs, maxDiff) {
  let runTimeDiffs = generateDiffs(numOfDiffs, maxDiff)
  let timesV1 = 0;
  let timesV2 = 0;
  for (let x = 0; x < 10; x++) {
    timesV1 += findGreatestDiffV1Time(runTimeDiffs)[0];
    timesV2 += findGreatestDiffV2Time(runTimeDiffs)[0];
  }
  console.log(`V1 times for numOfDiffs = ${numOfDiffs} and maxDiff = ${maxDiff} was: ${timesV1 / 10} seconds.`)
  console.log(`V2 times for numOfDiffs = ${numOfDiffs} and maxDiff = ${maxDiff} was: ${timesV2 / 10} seconds.`)
}

至于@gcampbell 关于使用性能的建议。现在,我会研究一下;我不熟悉该功能。很高兴知道这些事情:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多