モーグルとカバとパウダーの日記

モーグルやカバ(EXカービング)山スキー(BC)などがメインの日記でした。今は仕事のコンピュータ系のネタが主になっています。以前はスパム対策関連が多かったのですが最近はディープラーニング関連が多めです。

s3fs配下でchmod 0755/0644する速度

S3をs3fsでマウントしている環境で、アップロードされたファイルのパーミッションを、ディレクトリは0755、ファイルは0644にchmodするスクリプトがあり、だいぶ処理時間が掛かっているので改善できないか調べていました。
s3fs使ってS3にアクセスするのは非常に遅いため、通常のファイルシステムに対しての常識とはまた違った気遣いが必要になります。


最初のスクリプト

find ./example -type d -exec chmod 0755 {} +
find ./example -type f -exec chmod 0644 {} +

という感じだったので、これを1コマンドにまとめたら少なくとも倍速になるんでは、と思ったわけです。


こういうのってうまく書いたらchmodだけで出来ないのかなあ、とも思っていたのでtweetしたところ、@mnb0327さん、@tatsushi_dさん、@satoh_fumiyasuさんからリプいただきました。

というわけで簡単に書く方法はなくて、やはりfind使うかperlとかでごりごりやるしかない、という感じでした。


(2016/11/2 追記)

chmodだけでディレクトリに対してのみ+x出来る記述方法を教えていただきました。

chmod -R a=,u=rwX,go=rX ./example

「0755」系のビットフィールド使った指定ではなく、「x」系の指定で「X」を使うと、ディレクトリに対してのみ実行権限「x」を付けられるのですね。
知らんかった…


そこで教えていただいた方法や、対照実験用のchmod単体でやった場合など、いくつか試してtime取ってみました。
2回データ取ってよかったほうを採用しましたが、だいたい近い時間で処理されていました。
s3fs-1.74で約950ファイルに対して行っています。

time ./chmod.pl
real    2m39.680s

time chmod -R 0755 ./example
real    2m44.186s

time find ./example -exec chmod 0644 {} +
real    2m47.660s

time find ./example -type d -exec chmod 0755 {} + -o -type f -exec chmod 0644 {} +
real    2m53.486s

time find ./example -exec chmod 0755 {} +
real    2m58.552s

time find ./example -depth -type d -exec chmod 0755 {} + -o -type f -exec chmod 0644 {} +
real    3m8.701s

time (find ./example -type d -exec chmod 0755 {} +; find ./example -type f -exec chmod 0644 {} +)
real    3m38.750s

chmod.pl

sub recursive {
    my ($dir) = @_;
    my @files = glob("$dir/*");
    foreach my $file (@files) {
        if (-d $file) {
            system("chmod 0755 $file");
            recursive($file);
        } else {
            system("chmod 0644 $file");
        }
    }
}

recursive("./example");

(参考)ディレクトリの中をを再帰的にたどってすべてのファイルに対してなにかの処理をするには | 入出力・ファイル操作 | プログラミング言語の比較 | hydroculのメモ


結局、perlで書いたのが一番早く、その場合は単純にchmodで全部0755にしてしまうよりも早く処理が終わりました。
単純なchmodよりもperlのが早いというのはちょっと不思議ですが、他の処理も動いていたため揺れの範疇かもしれません。
そして、find で -o オプション使って処理を変えるものも、ほとんど遜色ない時間で処理が終わりました。
さらに意外だったのが、元々のfindを2回書くパターンが実はそれほど遅くないということで、だいたい2割増程度の時間で済んでいました。


(2016/11/2 追記)

エントリ書いた後、さらにこのようなアドバイスいただいたので

  • chmodだけでディレクトリに対してのみ+x出来る記述方法
  • perlのchmodを内部コマンド使う方法
  • xargs経由でやる方法

を追加テストしました。

今日は全体的にS3へのアクセス速度が早くなっていて昨日やったテストの時間と直接比較できないため、代表的なものを比較用に再度テストしています。

time chmod -R a=,u=rwX,go=rX ./example
real    2m19.232s

time chmod -R 0755 ./example
real    2m22.987s

time ./chmod2.pl
real    2m26.634s

time ./chmod.pl
real    2m41.052s

time find ./11434 -type d -exec chmod 0750 {} + -o -type f -exec chmod 0640 {} +
real    3m18.127s

time (find ./example -type f -print | xargs chmod 0644; find ./example -type d -print | xargs chmod 0755)
real    3m19.146s

chmod2.pl

sub recursive {
    my ($dir) = @_;
    my @files = glob("$dir/*");
    foreach my $file (@files) {
        if (-d $file) {
            chmod 0755, $file;
            recursive($file);
        } else {
            chmod 0644, $file;
        }
    }
}

recursive("./example");

というわけでchmodでラージ「X」使うのが一番良くて、記述ももっともスッキリしました。
アドバイスいただいた皆様、多謝です!!