はじめに
コードを書いていてjavascript
の処理が重く、どうにか改善できないかと模索していたところ高速化できたのでその共有
要件
ボタンを押したらテーブルの末尾に行を追加する
コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<button id='append_button'>テーブル行追加ボタン</button>
<table border='1' id='my_table'>
<thead>
<tr>
<th>header_A</th>
<th>header_B</th>
</tr>
</thead>
<tbody>
<?php for($i=0; $i<10; $i++){ ?>
<tr>
<td>body_A_<?php echo($i); ?></td>
<td>body_B_<?php echo($i); ?></td>
</tr>
<?php } ?>
</tbody>
</table>
<script type="text/javascript" src="sample.js"></script>
</body>
</html>
$('#append_button').on('click', function(){
console.time('timer');
let tr = "<tr><td>a</td><td>b</td></tr>";
$('#my_table').append(tr);
console.timeEnd('timer');
});
スクリーンショット
計測結果
テーブル行数 | 実行時間 |
---|---|
1行 | 2.9ms |
10行 | 3ms |
100行 | 3.3ms |
1000行 | 3.5ms |
10000行 | 5ms |
100000行 | 14ms |
元のテーブルの行数を変えて計測しました
行数が多いほど処理に時間がかかることが分かります
原因
$('#my_table').append(tr);
テーブルを見つけそれの末尾にtrを足すだけですが、この末尾を探す処理に時間がかかっているようです
今回の例では1行の時に比べて100000行になると約5倍の差が出ました。
14msであれば改善しなくても良いかもしれませんが、実際に直面した事例では他の要因もあり改善しなければなりませんでした。
改善案
末尾を探すのに時間がかかっていたので末尾に目印をつけておき、そこに対して要素を追加してあげる
やりたいのは「末尾を探して要素を追加」ではなく「末尾に要素を追加」ということ
改善コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<button id='append_button'>テーブル行追加ボタン</button>
<table border='1' id='my_table'>
<thead>
<tr>
<th>header_A</th>
<th>header_B</th>
</tr>
</thead>
<tbody>
<?php for($i=0; $i<10; $i++){ ?>
<tr>
<td>body_A_<?php echo($i); ?></td>
<td>body_B_<?php echo($i); ?></td>
</tr>
<?php } ?>
<tr id='last_tr' style='display: none;'>
<td>dummy_A</td>
<td>dummy_B</td>
</tr>
</tbody>
</table>
<script type="text/javascript" src="sample2.js"></script>
</body>
</html>
$('#append_button').on('click', function(){
console.time('timer');
let tr = "<tr><td>a</td><td>b</td></tr>";
$('#last_tr').before(tr);
console.timeEnd('timer');
});
改善後の計測結果
テーブル行数 | 実行時間 |
---|---|
1行 | 1.5ms |
10行 | 1.6ms |
100行 | 1.6ms |
1000行 | 1.5ms |
10000行 | 1.8ms |
100000行 | 1.6ms |
平均をとっていてバラつきはありますが、行数に依存しない処理速度が確保できました。
改善前の100000行と比べると10倍の改善になりました
おわりに
些細なことですがうっかり大きいテーブルにappendすると処理時間がかかるので、こういうテクニックを覚えておくと良いかもしれません。
また、dummyの要素を末尾においているので場合によっては副作用をもたらすこともありそうですね。
注意して参考にしてみてください。