Products
GG网络技术分享 2025-03-18 16:10 3
本文邀请jinbiao来回答,与你分享逻辑代码优化的方法~
在不考虑面向对象的情况下,先让我们先回忆下c语言中的3大结构。
1、顺序结构
2、分支(条件)结构
3、循环结构
这三个结构任意组合构成了我们书写的逻辑代码(算法)。下面我们就根据这常用的三种结构进行调优。注意,下文中的使用的语言为JavaScript,但考虑大的是大部分语言的情况。
代码在计算机中实际都是一条条语句执行的,分支和循环结构在使用了jump语句实现了语句跳转之后,实际上也变成了一个顺序结构。如果代码以顺序结构执行,则可以通过程序计数器自增让代码顺序执行。如果是jump跳转语句则会发生寻址,计算等额外步骤。
[ 汇编 ]
这里c语言代码中写了一个普通的循环。但是在计算机中实际执行时类似右边goto版本的。每一个goto会加重计算机的计算,所以在考虑性能的情况下尽量使用顺序结构。
常见的循环有
1、while
2、for
3、do…while
注意的是循环中while与for是先判断在开始循环,do…while是先运行一次后判断在开始循环
循环中两种方案调优
1、减少每次循环处理的事务
2、减少循环的次数
在循环判断条件中,通常我们将某个对象的属性进行判断比如
实际上在计算机的语句为
初始化(一次)
一次i初始化(var i)
一次i赋值(i = 0)
判断(n次)
i值查找(i)
array值查找(array)
通过array找到length(array.length)
i 与 length 比较(i < array.length)
后处理,自增(n - 1次)
i取值(i)
计算i + 1(i + 1)
将结果赋值给(i = i + 1)
这次判断实际上有四个语句组成,在看看下面的代码
在这个判断中实际上在计算机的语句为:
一次i值查找。
一次len值查找
通过array找到length
i 与 length 比较
这里在单次循环中语句减少了一条。在多次循环下,将减少了n条计算机语句。
如果是简单的数值比较我们还可以使用倒序循环方式
这次实际上在计算机的语句为
初始化(一次)
i初始化(var i)
array值查找(array)
通过array找到length(array.length)
i赋值(i = array.length)
判断(n次)
i取值(i)
计算i - 1(i - 1)
将结果赋值给(i = i - 1)
后处理,自增(n-1次)
实际上这样的语句确实少了挺多,但是必须是在顺序无关和数值比较的前提下。因为部分语言会提供数值与布尔值的自动转换(像java这么写就会报错)
减少使用递归
谈到循环,自然也会谈到递归。递归最简单说就是某个函数继续调用某个函数,一般是自己调用自己。
一个进程。有数据区,堆栈,PCB等内容。堆栈的大小在进程开启的时候基本确定,栈能存储运行时的局部变量,和函数调用信息。如果发生递归,则会在栈中持续添加内容。若执行函数需要用到局部变量,或者调用函数不是最后一句时。将会发生中断。中断后,本次运行的上下文环境也会被保存进栈内,形成一个调用栈。
[ 递归 ]
发生一次中断,会触发CPU的中断处理,保存中断信息现场,指令跳转。恢复时又会跳转指令,恢复中断现场信息。如果非必要,请不要使用递归。
栈的大小是固定的,如果超过栈的大小,就会有爆栈的可能(著名的stack overflow)。部分语言有尾调用优化,可以让递归不保存中断信息。
优化选择
常见的选择有:
if…else 更适合范围匹配
switch…case 更适合单值匹配
不管使用的是if…else还是switch…case,判断都是按书写的顺序开始执行的。所以我们应该把最可能出现的情况放在第一位。
由于选择结构也会触发指令跳转,我们应该使用嵌套的if…else,使用树的形式,让到达每一个结果的情况尽可能的少。
Demand feedback