C, C++(他も?)の話
インクリメント、デクリメント
一般的な書き方
int i = 1;
i++;
このようなインクリメントを後置くインクリメントと言います。
for文を使う場合
for(int i = 0;i < 10000;i++){
}
ちょっとだけ速くなる書き方
int i = 1;
++i
このようなインクリメントを前置インクリメントと言います。
for文を使う場合
for(int i = 0;i < 10000;++i){
}
ちょこっと解説
後置インクリメントだと内部でインスタンスの生成が発生するので、ちょっと処理に時間がかかるようです。ただ現在ではコンパイラの発達により、どちらでもほとんどが出ないことが多いです
参考
C, C++他多数の言語での話
2倍の書き方
一般的な書き方
int num = 100;
int twice = num * 2;
ちょっとだけ速くなる書き方
int num = 100;
int twice = num << 1;
ちょこっと解説
「ビット演算した方が速い」と一般的によく言われるが、実際どのような場合にビット演算を使うのかピンとこない場合が多いと思います。そんなとき最もよく使いやすいケースが上記の2倍のケースではないだろうか?
ただし、初見では???となることが多い(可読性が下がる)ので使い所は考えた方がいいかもしれません。
※ 右シフト(num >> 1
, 半分, 1/2)は符号付き(負の値)での計算において、 num / 2
と num >> 1
で実行結果が変わることがあります。
参考
Listの話
一般的な書き方
List<int> numList = new List<int>();
for(int i = 0;i < 10000;++i){
numList.Add(i);
}
if(numList.Contain(9999)){
}
ちょっとだけ速くなる書き方
HashSet<int> numList = new HashSet<int>();
for(int i = 0;i < 10000;++i){
numList.Add(i);
}
if(numList.Contain(9999)){
}
ちょこっと解説
C#やJavaなどのList(C++だとVector)にあたるような可変長配列を用いる場合、その配列の中に値が存在するかどうか判定する処理を書くと以下のような処理と同等の処理が行われます。
public bool Contain(int value){
for(int i = 0;i < this.Count;i++){
if(this[i] == value){
return true;
}
}
return false;
}
例えば、このListの中にデータが10000件ある場合、最大10000回のチェックをすることになります。(このような処理を線形探索といいます)
HashSetやDictionary(JavaではHashMapなど)を用いた場合、1回の処理で、該当の値を取得することができます。そのため判定も1回だけになるので速度が速くなります。(このような処理をハッシュ探索といいます。詳しくは参考などをご覧下さい。
参考
MySQLの話
last
一般的な書き方
SELECT id FROM テーブル名 ORDER BY DESC LIMIT 1;
よく使われるRailsで行う場合
ActiveRecord.last.id
超速くなる書き方
SELECT (information_schema.tables.AUTO_INCREMENT - 1) FROM information_schema.tables WHERE information_schema.tables.TABLE_NAME = 'テーブル名';
注意点
- テーブルの件数(TABLE_ROWS)も取得できるがこちらは結構ずれる → InnoDBのINFORMATION_SCHEMA TABLES Tableと実データのレコード数比率を出してみた
- AUTO_INCREMENTはたまに間が抜ける。そのため多少抜けてもことを許容して → 例: INSERT ... ON DUPLICATE KEY UPDATE 構文 を使った時などに間が抜けることがあります。そのため、上記SQLの結果は多少間が抜けていても問題がないようなケースで使うときに有効です。(最低でもこの値より大きい値のデータは存在しないので)
ちょこっと解説
SQLでORDER BY
文を発行するとたとえLIMIT 1
であっても、件数が増えれば処理が遅くなります。(基本的にソート処理は重たい)
MySQLにはINFORMATION_SCHEMAというテーブル情報など、MySQL内において各種定義値などのメタ情報を記録しているテーブルがデフォルトで存在します。このINFORMATION_SCHEMAテーブルからは読み込みのみ可能で、SELECT文を用いることで値を取得することができます。INFORMATION_SCHEMAのテーブルの情報にはそのテーブルの件数(TABLE_ROWS)や末尾の情報(AUTO_INCREMENT)の情報も記録されています。そこで、このテーブルから情報を取得することで高速に実行することができます。
※ ただし注意点もあることも忘れずに。
その他
他にもちょっと書き方を変えるだけで速度が改善できるようんケースがあれば追記していきたいと思います。