【问题标题】:How does the JS engine deal with explicitly typed computations?JS 引擎如何处理显式类型的计算?
【发布时间】:2019-02-22 05:07:11
【问题描述】:

我最近对元编程很感兴趣。我们可以进行通用计算,在本例中为均值,并为其动态创建一个高效的、明确的函数。在这里,我在 mean2 中创建了一个将显式计算均值的函数(没有循环)。通常,这些显式函数运行得更快。但我正在经历一些有趣的行为。在我的时间里,对于在 4e7 循环中运行的大小为 50 的数组,显式函数如预期的那样轻松获胜:

符号:2479.273ms |字面量:60.572ms

但是将初始数组大小从 50 微调到 55,性能急剧下降。

符号:2445.357ms |字面量:3221.829ms

这可能是什么原因?

const A = new Float64Array(50).map(Math.random)

const mean1 = function (A) {
    let sum = 0

    for (let i = 0; i < A.length; i++)
        sum += A[i]

    return sum / A.length
}

const mean2 = (function (A) {
    return new Function('A', `
        return (${new Array(A.length).fill(null).map(function (_, i) {
            return `A[${i}]`
        }).join('+')}) / ${A.length}
    `)
})(A)

console.time('symbolic')
for (let i = 0; i < 4e7; i++)
    mean1(A)
console.timeEnd('symbolic')


console.time('literal')
for (let i = 0; i < 4e7; i++)
    mean2(A)
console.timeEnd('literal')

【问题讨论】:

  • @Shidersz Mean2 是一个匿名函数的结果,它只在启动时运行以创建模板 - console.log(mean2.toString()) 看看我的意思
  • @meagar 是的,我现在可以看到它(mean2 初始化时的自调用函数),谢谢,要删除我的评论...

标签: javascript node.js performance performance-testing


【解决方案1】:

结果在第二个示例中被缓存,它与“元编程”方法无关,(或者更具体地说,缺少循环)。

这不是那么容易用 JavaScript 直接证明的;在编译语言中,您通常只查看程序集并看到编译器已尝试以某种方式变得聪明并优化计时器内的循环。 JS 运行时显然更加不透明和复杂,输出不是那么容易访问。您可以改为通过代理对其进行测试,方法是观察不同但等效的表单的行为,以了解是什么触发了前期优化。

在测试时,您的“mean2”函数在 nodejs (v8) 中对缓存优化进行了以下轻微修改:

在返回之前赋值给一个作用域变量:

const mean2 = (function (A) {
    return new Function('A', `
        let sum = (${new Array(A.length).fill(null).map(function (_, i) {
            return `A[${i}]`
        }).join('+')}) / ${A.length};
        return sum;
    `)
})(A)

使用A.length 引用而不是文字:

const mean2 = (function (A) {
    return new Function('A', `
        return (${new Array(A.length).fill(null).map(function (_, i) {
            return `A[${i}]`
        }).join('+')}) / A.length
    `)
})(A)

不过,您不必担心这些字幕...而是更改您的测试方法,确保样本不会被丢弃以产生相同的结果,否则您可能会测试编译器忽略无用指令而不是实际性能的能力。

在这种情况下,在每个样本之前使用随机值重新初始化数组,并且绝对确定 - 使一些持久变量依赖于每个样本的结果。也不要在计时器中包含这些额外的步骤,否则会影响您的采样时间。

【讨论】:

    猜你喜欢
    • 2019-01-08
    • 2021-10-20
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多