継続条件
毎回size()
関数を召喚。とてもよく見掛ける
for(int a=0;a<A.size();a++);
書き替え
for(int a=0,b=A.size();a<b;a++);
逆方向からで良いなら以下のように
for(int a=A.size();a;)--a;
分岐頻度の最適化
いわゆるif else
構文においてelse
方面へ分岐する処理は低頻度である方が良い。以下は最悪の一例。
for(int a=0;a<9;a++)
if(a==0);
else;
上記の反復処理においてif
(真)方面へは1回ぽっきり、残り全てelse
(偽)方面へ分岐する。分岐し過ぎである。以下のように逆の方が高速になりやすい。
書き替え
for(int a=0;a<9;a++)
if(a);
else;
三項演算の場合も同様
for(int a=0;a<9;a++)a==0?1:0;
書き替え
for(int a=0;a<9;a++)a?0:1;
不要分岐排除
if
(真)へ進んだら、それより後の処理をしない事が確定している場合、else
は不要
int f(int a,int b){
if(a<b)return a;
else if(a>b)return b;
else return 0;
}
書き替え
int f(int a,int b){
if(a<b)return a;
if(a>b)return b;
return 0;
}
深い所は近道
深い階層の値をそのまま読み書きするのは重労働
let a={a:{a:{a:9,b;[]}}}, b=0;
while(a.a.a.a>b)a.a.a.b[b]=b++;
書き替え
let a={a:{a:{a:9,b;[]}}}, b=0, c=a.a.a.a, d=a.a.a.b;
while(c>b)d[b]=b++;
浅くても値を写した別変数を読み書きするのが良い
近道2
closureにおいても外側のscopeの変数はlocal変数に写して更新
let f=function(){
var a=0;
return function(b){for(;b;)a+=b--;return a}
}()
書き替え
let f=function(){
var a=0;
return function(b){for(var c=a;b;)c+=b--;return a=c}
}()
近道3
class
のmember変数に対して過剰読み書きするのも考えものである。
class C{
private:
int *mA, mP, mEnd;
public:
C(int n){mA=new int[mEnd=n];}
~C(){delete[]mA;}
//手抜き
void set(int n){
for(mP=0;mP<mEnd;)mA[mP++]=n;
}
//改善
void Set(int n){
int P=0, *A=mA, E=mEnd;
for(;P<E;)A[P++]=n;mP=P;
}
};
if(変数!=0)
これは加減算の例だが、他にも応用できる例は多い。
let a=Math.random()*2, b=[a, a+a|0, a*a|0], c=0;
if(b[0]!=0)c++;
if(b[1]!=0)c++;
if(b[2]!=0)c++;
書き替え
let a=Math.random()*2, b=[a, a+a|0, a*a|0], c=3-!b[0]-!b[1]-!b[2];
蛇足
compilerの性能や実行環境が良ければ気にするほどの差は出ません。