kou6839の日記

c++ 競プロ(特にcsacademy) linuxについて書きます。普段は自動車屋さんでナビ開発してます。転職先を探しています!!。

chmod遅すぎ問題

chmodが遅すぎる問題が発生したので、chmodに関して色々実験
(virtual boxからクリップボード共有ができなかったので、virtual boxで書いてます。すでに重い・・・)

<環境>

アーキテクチャ:                      x86_64
CPU 操作モード:                      32-bit, 64-bit
バイト順序:                          Little Endian
CPU:                                 2
オンラインになっている CPU のリスト: 0,1
コアあたりのスレッド数:              1
ソケットあたりのコア数:              2
ソケット数:                          1
NUMA ノード数:                       1
ベンダー ID:                         GenuineIntel
CPU ファミリー:                      6
モデル:                              69
モデル名:                            Intel(R) Core(TM) i7-4510U CPU @ 2.00GHz
ステッピング:                        1
CPU MHz:                             2593.998
BogoMIPS:                            5187.99
ハイパーバイザのベンダー:            KVM
仮想化タイプ:                        完全仮想化
L1d キャッシュ:                      32K
L1i キャッシュ:                      32K
L2 キャッシュ:                       256K
L3 キャッシュ:                       4096K
NUMA ノード 0 CPU:                   0,1

シェルスクリプトの名前が変わらないのは許してください。
まずは普通にfor文書いてみます。

kou6839@kou6839-VirtualBox:~$ cat for.sh 

for i in `seq 10000`
do
	:
done

・計測

kou6839@kou6839-VirtualBox:~$ time ./for.sh 

real	0m0.050s
user	0m0.031s
sys	0m0.016s

普通に早い

・次にtouch 10000回

kou6839@kou6839-VirtualBox:~$ cat for.sh 

for i in `seq 10000`
do
  touch a 
done

計測

kou6839@kou6839-VirtualBox:~$ time ./for.sh 

real	0m10.846s
user	0m6.315s
sys	0m2.582s

まぁまぁ遅い

次にchmod 10000回

kou6839@kou6839-VirtualBox:~$ cat for.sh 
touch a
for i in `seq 10000`
do
  chmod 777 a
done

計測

kou6839@kou6839-VirtualBox:~$ time ./for.sh 

real	0m10.470s
user	0m6.161s
sys	0m2.473s

touchとほぼ同じくらい

次にchmodでモードを変えてるのと変えてないのでは時間がかわるのか実験
ループ回数を半分にして中の処理を2つにしています

kou6839@kou6839-VirtualBox:~$ cat for.sh 
touch a
for i in `seq 5000`
do
  chmod 777 a
  chmod 444 a
done

計測

kou6839@kou6839-VirtualBox:~$ time ./for.sh 

real	0m10.332s
user	0m7.440s
sys	0m3.075s

別に変えても変えてなくても時間は同じっぽい

・次にchmodの引数を複数にするとはやいらしいので、その準備
ファイルa, bのモードを変えます

kou6839@kou6839-VirtualBox:~$ cat for.sh 
touch a
touch b
for i in `seq 5000`
do
  chmod 777 a
  chmod 777 b
done

計測

kou6839@kou6839-VirtualBox:~$ time ./for.sh 

real	0m10.408s
user	0m7.395s
sys	0m3.209s

1個1万回と2個5000回ずつなのであまりかわりません。

引数を2つにします

kou6839@kou6839-VirtualBox:~$ cat for.sh 
touch a
touch b
for i in `seq 5000`
do
  chmod 777 a b
done

計測

kou6839@kou6839-VirtualBox:~$ time ./for.sh 

real	0m5.311s
user	0m3.700s
sys	0m1.595s

はやい!

最初の2つ(touchや1ファイルのchmod)と比較すると2つのファイルのchmodだと引数に関わりなく、timeコマンドの結果からIO待ちが少ないことがわかります。
さらに、引数を増やすと並列なのかforkが少なくなるのかわからんが、とにかく早い!

5000回chmodすることはないかと思いますが、再帰的に(-R)chmodするときには、使えるかもしれません。
そもそもchmod以外でも使える技なので、使ってみてください!

[参考]
シェルスクリプト高速化のツボ - 新・日々録 by TRASH BOX@Eel