头图
javascript 是单线程、动态类型语言,那么我们在编码时候如何编写性能最优代码呢?下面将讲解V8引擎的内联优化。利用内联缓存这个特性我们可以编写更加优秀的代码。

什么是内联缓存

引用官方的描述:内联缓存(Inline caching)是部分编程语言的运行时系统采用的优化技术,最早为Smalltalk开发。内联缓存的目标是通过记住以前直接在调用点上方法查询的结果来加快运行时方法绑定的速度。内联缓存对动态类型语言尤为有用,其中大多数(如非全部)方法绑定发生在运行时,因此虚方法表通常无法使用。

  • 我们可以理解为javascript每一次的栈执行遇到调用外部函数、对象时候都产生地址缓存记录,下回执行到这个位置时候直接从缓存中取出对应记录,省去重新查找这一过程从加快程序执行速度。

转换成代码

模拟计算逻辑(伪代码)
为了更好提现出现内联缓存的优化,我们把对象所有方法逻辑为一致。
        let value = 0
        const Calculator = {
            add1(val) {
                value += val
            },
            add2(val) {
                value += val
            },
            add3(val) {
                value += val
            },
            add4(val) {
                value += val
            },
            add5(val) {
                value += val
            },
            add6(val) {
                value += val
            },
            add7(val) {
                value += val
            },
            add8(val) {
                value += val
            },
            add9(val) {
                value += val
            },
            add10(val) {
                value += val
            }
        }
不实用内联优化策略的代码
        function notOptimization(val, type) {
            Calculator[type](val) // 动态执行函数,当前调点无法确定地址
        }

        const CalculatorKey = Object.keys(Calculator)

        console.time('notOptimization')
        for(let i = 0; i < 1000000; i ++) {
            const key = CalculatorKey[Math.floor(Math.random() * CalculatorKey.length)]
            notOptimization(1, key)
        }
        console.timeEnd('notOptimization')

上面这段代码使用哈希快速查找对应函数,但是放弃内联缓存策略。代码5次执行结果,平均为80ms左右
在这里插入图片描述

使用内联缓存策略代码
        function optimization(val, type) {
            if (type === 'add1')
                Calculator.add1(val)
            else if (type === 'add2')
                Calculator.add2(val)
            else if (type === 'add3')
                Calculator.add3(val)
            else if (type === 'add4')
                Calculator.add4(val)
            else if (type === 'add5')
                Calculator.add5(val)
            else if (type === 'add6')
                Calculator.add6(val)
            else if (type === 'add7')
                Calculator.add7(val)
            else if (type === 'add8')
                Calculator.add8(val)
            else if (type === 'add9')
                Calculator.add9(val)
            else
                Calculator.add10(val)
        }
        const CalculatorKey = Object.keys(Calculator)

       console.time('optimization')
       for(let i = 0; i < 1000000; i ++) {
           const key = CalculatorKey[Math.floor(Math.random() * CalculatorKey.length)]
           optimization(1, key)
       }
       console.timeEnd('optimization')

这段代码用了多层if else 进行函数调用(为了提现内联缓存策略的优化,正确应该用switch或数组查找),我们看看执行5次结果,速度为55~50ms
在这里插入图片描述

总结,所以在编码过程我们尽量少使用动态调用运算,但是相对对象属性值获取哈希、数组的方式是远远快于if、switch的

杨周龙
789 声望5 粉丝

Pong!一个大BUG