このエントリーをはてなブックマークに追加

 

手を動かしてさくさく理解する
C# 処理時間計測 Stopwatch 入門
Copyright (C) 2015 by Nobuhide Tsuda

 

※ イラスト提供:かわいいフリー素材集「いらすとや」様

概要

プログラム開発当初から過度のパフォーマンス最適化を行うのは良くないと言われている。 プログラムソースの柔軟性が失われる可能性があるし、必要無いかもしれない最適化に時間を費やすのは開発工数管理的に好ましくないからだ。

プログラムがある程度動作するようになり、パフォーマンスが悪い(実行速度が遅すぎる)場合は、 処理時間計測を行い処理時間を要している箇所を探しだし、アルゴリズムやデータ構造の変更などのパフォーマンス・チューニングを行う必要がある。
予備調査として、色々なアルゴリズム・データ構造を採用した場合の処理時間計測を行い、 どれが最適か、どのような性質があるかを知ることも重要である。

本稿では、上記のような目的のためにプログラムの処理時間を計測する方法について説明する。

場合によっては、ストップウォッチを片手にプログラムを実行し、処理時間を計測することもあるかもしれないが、 精度が1秒程度なので、場合によっては不適切である。
処理時間計測関数を使えば、ミリ秒の精度で計測することが出来るぞ。

準備

Stopwatch クラスを使用するには、コードの最初の方に「using System;」「using System.Diagnostics;」を記述する必要がある。

Unity の場合は、これらは自動的には生成されないので、下記のように、ちゃんと忘れずに記述しよう。

using UnityEngine;
using System;                                //  ← 追加するのを忘れずに
using System.Diagnostics;             //  ← 追加するのを忘れずに
using System.Collections;

public class TestStopwatch : MonoBehaviour {
    .....
}

C# コンソールアプリであれば、「using System;」は自動的に生成されるので、「using System.Diagnostics;」だけを追加する。

using System;
using System.Collections.Generic;
using System.Diagnostics;             //  ← 追加するのを忘れずに
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace testList
{
    class Program
    {
        static void Main(string[] args)
        .....
    }
}

なお、本稿で示すコードは Unity 用ではなく、C# コンソールアプリ用なので注意すること。

処理時間計測

C# で処理時間計測を行なうには、Stopwatch クラスと TimeSpan クラスを使用する。

具体的な計測方法は以下のようになる。

    var sw = new Stopwatch();     // ストップウォッチオブジェクト生成
    sw.Start();  //  時間計測スタート
    Sleep(1);     //  時間計測を行なう処理
    sw.Stop();   // 時間計測終了
    TimeSpan span = sw.Elapsed;    //  計測した時間を span に代入
    Console.WriteLine(span.TotalMilliseconds);    // トータルミリ秒をコンソールに表示

※ このコードは C#コンソールアプリ用なので注意。Unity で使用する場合は、「using System;」を書き、出力を Debug.Log() に変える必要がある。

Stopwatch が実際に時間計測するためのクラスだ。
new で Stopwatch オブジェクトを生成し、計測したい処理を Start() と Stop() で囲む。
かかった時間は TimeSpan 型の Elapsed で取得することができる。

TimeSpan はメンバ関数で時間間隔を秒数やミリ秒数に変換することができるので、それらを使って表示する。
上記の例では TotalMilliseconds でトータルのミリ秒を取り出し、表示している。

TimeSpan には Milliseconds や Seconds というプロパティもあるが、これらは時間間隔を 時・分・秒・ミリ秒に分解した値なので、 間違わないようにしよう。
例えば、トータルミリ秒が 1230 の場合、1秒 230ミリ秒なので、TotalMilliseconds は 1230 を返すが、Milliseconds は 230 を返す。

演習問題:

  1. 上記コードをビルド実行し、Sleep(1) にかかった時間を計測してみなさい。
  2. Sleep(10), Sleep(100), Sleep(1000) にかかる時間を計測してみなさい。
  3. List<int> lst; に対して Add(0), Add(1) ... Add(999999) を実行するのに要する時間と、 C++ で同様なことを行なうのに要する時間を計測し、比較しなさい。
  4.             var sw = new Stopwatch();
                List<int> lst = new List<int>();
                sw.Start();
                for (int i = 0; i < 1000*1000; ++i) {
                    lst.Add(i);
                }
                sw.Stop();
                TimeSpan span = sw.Elapsed;
                Console.WriteLine(span.TotalMilliseconds);
    
  5. List<int> lst; に対して Add(0) の実行に要する時間が lst の要素数に比例しないことを確かめなさい。
  6.             const int N = 10;
                List<int> lst = new List<int>();
                for (int i = 0; i < N; ++i) {
                    var sw = new Stopwatch();
                    sw.Start();
                    for (int k = 0; k < 100000; ++k) {
                        lst.Add(0);
                    }
                    sw.Stop();
                    TimeSpan span = sw.Elapsed;
                    Console.WriteLine(span.TotalMilliseconds);
                }
    

まとめ

Stopwatch、TimeSpan クラスを使って、ミリ秒単位の時間計測ができるぞ。