ちょっとしたテクリで速度改善Tips

# C, C++(他も?)の話
## インクリメント、デクリメント

### 一般的な書き方

```C++
int i = 1;
i++;
```

このようなインクリメントを<b>後置くインクリメント</b>と言います。
for文を使う場合

```C++
for(int i = 0;i < 10000;i++){
}
```

### ちょっとだけ速くなる書き方

```C++
int i = 1;
++i
```

このようなインクリメントを<b>前置インクリメント</b>と言います。

for文を使う場合

```C++
for(int i = 0;i < 10000;++i){
}
```

#### ちょこっと解説
<b>後置インクリメント</b>だと内部でインスタンスの生成が発生するので、ちょっと処理に時間がかかるようです。<font color="#FF8800">ただ現在ではコンパイラの発達により、どちらでもほとんどが出ないことが多いです</font>


##### 参考
 * [前置きと後置き](https://www.javadrive.jp/cstart/ope/index4.html)
 * [C++では、必要でない限り、後置インクリメント演算子は使わず、前置インクリメント演算子を使ったほうがよい](https://qiita.com/tommy6073/items/bc5bb97e27c6ee7d633f)

# C, C++他多数の言語での話
## 2倍の書き方

### 一般的な書き方

```C++
int num = 100;
int twice = num * 2;
```

### ちょっとだけ速くなる書き方

```C++
int num = 100;
int twice = num << 1;
```

#### ちょこっと解説
「[ビット演算](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97)した方が速い」と一般的によく言われるが、実際どのような場合にビット演算を使うのかピンとこない場合が多いと思います。そんなとき最もよく使いやすいケースが上記の2倍のケースではないだろうか?
ただし、初見では???となることが多い(可読性が下がる)ので使い所は考えた方がいいかもしれません。

※ 右シフト(```num >> 1```, 半分, 1/2)は符号付き(負の値)での計算において、 ```num / 2``` と ```num >> 1``` で実行結果が変わることがあります。

##### 参考
 * [ビット演算入門](https://qiita.com/Ingward/items/43acda931c8a62c70d2f)

## Listの話

### 一般的な書き方

```C#
List<int> numList = new List<int>();
for(int i = 0;i < 10000;++i){
  numList.Add(i);
}
if(numList.Contain(9999)){
}
```

### ちょっとだけ速くなる書き方

```C#
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)にあたるような可変長配列を用いる場合、その配列の中に値が存在するかどうか判定する処理を書くと以下のような処理と同等の処理が行われます。

```C#
public bool Contain(int value){
  for(int i = 0;i < this.Count;i++){
    if(this[i] == value){
      return true;
    }
  }
  return false;
}
```

例えば、このListの中にデータが10000件ある場合、最大10000回のチェックをすることになります。(このような処理を[線形探索](https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%9E%8B%E6%8E%A2%E7%B4%A2)といいます)
HashSetやDictionary(JavaではHashMapなど)を用いた場合、１回の処理で、該当の値を取得することができます。そのため判定も1回だけになるので速度が速くなります。(このような処理を[ハッシュ探索](https://programming-place.net/ProgrammingPlacePlus/algorithm/search/006.html)といいます。詳しくは参考などをご覧下さい。

##### 参考
 * [JavaでよくつかうCollection実装クラスの仕組みと特性](https://qiita.com/frost_star/items/8a5d711f9090f0e24f51)


# MySQLの話

## last
### 一般的な書き方


```SQL
SELECT id FROM テーブル名 ORDER BY DESC LIMIT 1;
```

よく使われるRailsで行う場合

```ruby
ActiveRecord.last.id
```

### 超速くなる書き方

```SQL
SELECT (information_schema.tables.AUTO_INCREMENT - 1) FROM information_schema.tables WHERE information_schema.tables.TABLE_NAME = 'テーブル名';
```

### <font color="#FF0000">注意点</font> ###
 * テーブルの件数(TABLE_ROWS)も取得できるがこちらは結構ずれる → [InnoDBのINFORMATION_SCHEMA TABLES Tableと実データのレコード数比率を出してみた](http://blog.masudak.net/entry/20120816/1345125886)
 * AUTO_INCREMENTはたまに間が抜ける。そのため多少抜けてもことを許容して → 例: [INSERT ... ON DUPLICATE KEY UPDATE 構文 ](https://dev.mysql.com/doc/refman/5.6/ja/insert-on-duplicate.html)を使った時などに間が抜けることがあります。そのため、上記SQLの結果は多少間が抜けていても問題がないようなケースで使うときに有効です。(最低でもこの値より大きい値のデータは存在しないので)

### ちょこっと解説
SQLで```ORDER BY```文を発行するとたとえ```LIMIT 1```であっても、件数が増えれば処理が遅くなります。(基本的にソート処理は重たい)
MySQLにはINFORMATION_SCHEMAというテーブル情報など、MySQL内において各種定義値などのメタ情報を記録しているテーブルがデフォルトで存在します。このINFORMATION_SCHEMAテーブルからは読み込みのみ可能で、SELECT文を用いることで値を取得することができます。INFORMATION_SCHEMAのテーブルの情報にはそのテーブルの件数(TABLE_ROWS)や末尾の情報(AUTO_INCREMENT)の情報も記録されています。そこで、このテーブルから情報を取得することで高速に実行することができます。
※ ただし注意点もあることも忘れずに。

# その他
他にもちょっと書き方を変えるだけで速度が改善できるようんケースがあれば追記していきたいと思います。