としおの読書生活

田舎に住む社会人の読書記録を綴ります。 主に小説や新書の内容紹介と感想を書きます。 読書の他にもワイン、紅茶、パソコン関係などの趣味を詰め込んだブログにしたいです。

タグ:Windows

先日、Windowsで初めてrobocopyコマンドを使ってファイルをコピーする機会がありました。

その際にファイルを速くコピーする方法を調べたので忘備録として記録します。



robocopyの基礎


robocopyコマンドはファイルサーバ同士の同期を目的に作られたコマンドです。

robocoyは「Roubust File Copy」の略で確実なファイルコピーという意味を持ちます。

FastCopyなどと違いWindowsに標準装備としてインストールされています。


ファイルをコピーす方法


robocopyでは以下のコマンドでファイルをコピーすることができます。

robocopy コピー元 コピー先



robocopyのオプション


robocopyのオプションはコマンドプロンプトで以下のコマンドを入力することで確認することができます。

robocopy /?

今回は、その中でも代表的なオプションをいくつか紹介します。

オプション説明
/MT[:n]n個のスレッドのマルチスレッドでコピーする。スレッドの数は1~128までの値
/MIR前回から更新のあったファイルだけコピーする。
/R:n失敗したコマンドに対してn回再試行する。
/W:n再試行と再試行の間にn秒待機時間を持たせる。
/NP進行状況を表示しない。

個人的に使ってみた感じ上記のオプションさえしっていれば基本的には困りませんでした。





ファイルを高速でコピーする


まずはオプションを変更してできる限りファイルを高速でコピーする方法を紹介します。

個人的に色々調べてみたところ以下のコマンドを使えばデフォルトでrobocopyコマンドを使うより、ファイルを速くコピーすることができました。

robocopy コピー元 コピー先 /MT:8 /MIR /R:1 /W:1 /NP

/Rや/Wオプションはデフォルト値が大きいのでかなり短くしています。

/MTオプションは環境によってチューニングが必要ですね。


今回、以下のようなディレクトリ構成で各フォルダに2KBのファイルを10000個ずつ入れて、コピーの毒度をrobocopyコマンドで計測してみました・

C:\TEST
├─1
├─10
├─2
├─3
├─4
├─5
├─6
├─7
├─8
└─9


計測結果は、24.0555624秒でした。


ちなみに上記でコピーしたフォルダにもう一度同じフォルダをコピーしてみようとしたところ、0.3133898秒で終わりました。

/MIRのオプションが有効に働いていますね。



startコマンドを使ってより早くしてみる


先ほどの計測結果よりも早くしようと思い調べてみたところ、startコマンドを使ったら早くなると書かれていたので試してみました。

一つのフォルダに対して一つのアプリケーションを起動してみます。

batファイルは以下になっています。

start robocopy C:\test\1 C:\test2\1 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\2 C:\test2\2 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\3 C:\test2\3 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\4 C:\test2\4 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\5 C:\test2\5 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\6 C:\test2\6 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\7 C:\test2\7 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\8 C:\test2\8 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\9 C:\test2\9 /MT:1 /MIR /R:1 /W:1 /NP
start robocopy C:\test\10 C\test2\10 /MT:1 /MIR /R:1 /W:1 /NP

計測結果は、24.476545でした。

あれ早くない!?スレッドの数とか調整したら早くなるのかな…。



まとめ


robocopyコマンドを使えばバックアップを速くできることが分かりました。

毎日や毎週のように短い頻度でバックアップをとっている場合、robocopyコマンドの/MIRオプションが有効に働くことも分かりました。

コピーコマンドで困った際は、ぜひrobocopyコマンドを使ってみてください。






バッチファイルを使って、試験に使用する大容量ファイルを作成してみました。



やりたいこと


今回は自分で作成したソフトの試験で10万行のファイルを読み込むという試験を行いたかったので、以下のようなファイルをバッチファイルで作成したかった。

abc
def
0123456789
0123456789
0123456789
0123456789
以下10万回『0123456789』が続く

ちなみにファイルの内容は、サンプル用の適当なものです。



ファイルに書き込む



上書き


以下のようにechoコマンドを使用して、出力したい内容とファイル名を指定することができます。

echo 出力したい内容> ファイル名

以下に上書きの場合のバッチファイルのサンプルを記しておきます。

バッチファイル
echo 123> ./test.txt 
echo 456> ./test.txt 

出力
456



追記


上書きから「>」の部分を「>>」に変更すると追記になります。

echo 出力したい内容>> ファイル名 

以下に追記の場合のバッチファイルのサンプルを記しておきます。

バッチファイル
echo 123>> ./test.txt 
echo 456>> ./test.txt

出力
123
456



for文


バッチファイルではfor文は以下のようにして書くことができます。

for /l %%変数 in (開始値,増減値,終了値) do (
    処理
)

これを先ほどのファイル出力のコマンドと組み合わせると以下のようになります。

バッチファイル
for /l %%i in (1,1,5) do (
    echo abc>> ./test.txt
)




試験用ファイルを作成する


先ほど説明したコマンドを組み合わせて、最初にやりたいことで示したファイルを作成してみます。

バッチファイル
rem 試験用ファイルを作成する
@echo off

echo abc>> ./test.txt
echo def>> ./test.txt
for /l %%i in (1,1,100000) do (
    echo 0123456789>> ./test.txt
)




まとめ


バッチファイルで試験用のファイルを作成してみましたが、コンパイルなどがいらないので単純なファイルを作るのには便利だなと思いました。



3753817_s

C++の実行時間を計測するときにWindowsだとどうしたらいいのか迷うことが多かったので、精度別の実行時間の計測方法をまとめていきます。



clock(10ミリ秒程度)


clockはC言語でも使用できる標準形の関数で、プログラム実行開始からの経過時間をミリ秒単位で返します。

精度は処理系に依存しますが、Windowsでは10ミリ秒程度です。

C言語の標準ライブラリに含まれる関数なのでWindows以外でも使える点が嬉しいです。

以下は、実行時間計測のサンプルプログラムです。

#include <iostream>
#include <vector>
#include <time.h>

using namespace std;

int main(void){    
    clock_t start = clock();

    // 計測対象(今回はvectorに1000000個要素を追加する)
    vector<inttestVec;
    for (int i=0i<1000000; ++i){
        testVec.push_back(i);
    }
    clock_t end = clock();

    cout << end-start << endl;


    return 0;
}



timeGetTime(1ミリ秒)


timeGetTimeはWin32 APIで用意されている関数で、システム起動開始からの経過時間をミリ秒単位で返します。

精度は1ミリ秒程度です。

timeGetTimeを使用するためには、windows.hのインクルードと、winmm.libのリンクが必要です。

以下は、実行時間計測のサンプルプログラムです。

#include <iostream>
#include <vector>
#include <windows.h>

using namespace std;

int main(void){    
    DWORD start = timeGetTime();

    // 計測対象(今回はvectorに1000000個要素を追加する)
    vector<inttestVec;
    for (int i=0i<1000000; ++i){
        testVec.push_back(i);
    }
    DWORD end = timeGetTime();

    cout << end-start << endl;


    return 0;
}






QueryPerformanceCounter(マイクロ秒)


こちらもtimeGetTimeと同様にWin32 APIで用意されている関数です。

精度は環境に依存しますが、マイクロ秒~10ナノ秒程度で、Windowsで使える時間計測の方法で最も精度が高いです。

しかし、実行時間の計測開始前にQueryPerformanceFrequency関数でカウントアップする周波数を取得するなど少し他のAPIに比べて手間がかかるという欠点もあります。

以下は、実行時間計測のサンプルプログラムです。

#include <iostream>
#include <vector>
#include <windows.h>

using namespace std;

int main(void){    
    LARGE_INTEGER frequency;
    QueryPerformanceFrequency(&frequency);

    LARGE_INTEGER start;
    QueryPerformanceCounter(&start);

    // 計測対象(今回はvectorに1000000個要素を追加する)
    vector<inttestVec;
    for (int i=0i<1000000; ++i){
        testVec.push_back(i);
    }
    
    LARGE_INTEGER end;
    QueryPerformanceCounter(&end);

    cout << (double)(end.QuadPart - start.QuadPart) / frequency.QuadPart << endl

    return 0;
}



まとめ


今回はWindows環境でC++の実行時間を計測する方法をまとめました。

Linuxと違ってナノ秒単位で正確に計測することはできませんが、QueryPerformanceCounterを使えばかなり正確に実行時間が計測できることが分かりました。

他にも良い計測方法があればコメントで教えていただけますと幸いです。



↑このページのトップヘ