System.DateTime.Ticksの精度と高精度タイマ(訂正)

昨日のエントリでは、System.DateTime#TicksとSystem.Diagnostics.Stopwatchクラスでは精度が出ないので使い物にならないというエントリを書いたが、少なくともStopwatchクラスに関しては私の計測方法、又はコードが悪かったために0msが戻っていただけであり、実際にはStopwatchクラスは充分な精度を持つことが判明したので訂正させて頂く。まったくもって面目ない。

昨日、NyaRuRuさんにコメントを頂いた際にシンプルな検証用のコードを頂いたのでこれを用いて単純なループの中でStopwatchの割込みが入っているかどうかを確認した。

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();
    while (true)
    {
        sw.Start();
        sw.Stop();
        Console.WriteLine(sw.Elapsed.TotalMilliseconds);
        sw.Reset();
    }
}

このコードではStopwath#Elapsedに0が戻ることは無かった。ならばと思い、このコードのままStopwatch#Startと#Stopの間に昨日使ったDbDataReaderでデータベースのレコードを列挙するコードを挿入してみた。

OleDbConnection con = new OleDbConnection(); 
try
{
    con.Open();
    DbCommand cmd = con.CreateCommand();
    cmd.CommandText = "SELECT * FROM HOGETABLE";
    Stopwatch sw = new Stopwatch();
    sw.Start();
    DbDataReader reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        for(int i = 0; i < reader.FieldCount; i++)
        {
            Console.Write(reader[i].ToString() + ", ");

        }
        Console.WriteLine("");
    }
}
finally
{
    sw.Stop();
    Console.WriteLine(sw.Elapsed.TotalMilliseconds);

    cmd.Dispose();
    con.Close();
    con.Dispose();
}

データベースのテーブル"HOGETABLE"には、カラムが5つあるレコードが約3000件格納されている。昨日はこの状態で最後のsw.Elapsed.TotalMilliseconds(昨日試していたコードではsw.ElapsedMillisecondsだったが)が0で戻ることがあったのだが、今日試してみると何故か0が戻らない。これはおかしいと思ってADO.NETプロパイダを変えたり使うテーブルを変えたり、繰り返してテストもしたのだが、結局一度も経過時間に0msが戻ることは無かった。

昨日使用したソースコードを保存しておけば簡単に再現できたのだが、既にマルチメデイアタイマを使用した版に変えてしまったので0msが戻るコードを再現する手立てが無いのが非常に気持ちが悪いが(少なくとも、何故0msが戻ったのかも検証しなくてはならなかったが、昨日書いたコードはもう忘れてしまったのだ)、少なくとも検証ではStopwatchクラスの精度は充分に高いことが検証できた。

ということで昨日のエントリで書いたことは全くの誤りであることが解りました。エントリを見て頂いた方とコメントをつけて頂いたNyaRuRuさんには謹んでお詫びいたします。どうもお騒がせいたしました。