VB.NETのタイマー精度を測る
VB.NETにはタイマーコントロールが付いている。
誰もが一度は次の事柄を疑問に思うであるう。
1、このタイマーの最小の設定値はどの位で有ろうか?
2、タイマーの間隔の精度は?
3、ほかの仕事が忙しい場合はタイマーのイベントはどうなるの?
そこでこれらを測定するコードを書いてみた。
構造的には2つのタイマーを使用して、1つは最小のインターバルを設定し、
もう一つはトータルの測定時間をセットする。
つまり2つ目のタイマーの間に、最小のインターバル値を設定した、
1つめのタイマーが幾つカウントするか測定することで、実際の最小インターバル
を測定しようとするものである。
仕様
こんな感じである。
インターバルの最大、最小、平均も測れる。
コードの説明
先ずフォーム内の宣言である。
フォーム内でグローバルで使用する変数を構造体にしてある。
これは構造体にしなくても、普通に宣言しても良い。
私の癖なのであるが、構造体にするとインテリセンスで候補が出るので、
多少プログラムが楽な気がする。
宣言とメイン関数 ソースコード
VB.NETコード
Public Class Form1
'データー保持用の構造体
Private Structure sTime
Dim intCount As Integer 'タイマーでのカウント数
Dim intTime() As Integer 'タイマーでの割り込み時の経過時間
Dim intBackSec As Integer 'm秒のオーバーフローの制御用
Dim intSec As Integer '秒単位の経過時間
Dim timeStart As Date 'スタート時刻の保持
End Structure
Dim myTime As sTime
開始ボタン押下の処理
開始ボタン押下の処理である。
開始ボタンを再度押された場合の為に変数の初期化は必要である。
タイマー1のインターバルの設定は1/1000秒固定である。
VB.NET 測定開始ボタンのコード
'-------------------
'開始ボタン
'-------------------
Private Sub Button1_Click( ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Timer2.Interval = CInt ((TextSpan.Text)) * 1000
ReDim myTime.intTime( CInt (TextSpan.Text) * 1000)
Timer1.Enabled = True
Timer2.Enabled = True
'以下初期化
myTime.intCount = 0
myTime.intBackSec = 0
myTime.intSec = 0
myTime.timeStart = Now
TextNo.Text = vbNullString
TextAve.Text = vbNullString
TextMax.Text = vbNullString
TextMini.Text = vbNullString
End Sub
精密タイマーの処理
精密タイマーの処理である、このタイマーのインターバルは1につまり1/1000秒にセット
してある。
当然この時間ではタイマーイベントは発生しないが、設定値を最小にして、どの位で
イベントが発生するか測定するのが、このプログラムの目的の一つでも有る。
イベントの時間はNow関数を使用している、この関数は1/1000秒までの正確な時間を
得ることが出来る。
面倒なのは1/1000秒がオーバーフローした時の処理であるが、ここではオーバーフローの回数を
カウントして、それを1000倍し1/1000秒に加えそれを配列に入れている。
この配列の前後の時間差が、タイマーイベントのインターバルとなる。
精密タイマーのコード
'-----------------
'精密タイマー
'-----------------
Private Sub Timer1_Tick( ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Timer1.Tick
Dim tsTime As TimeSpan '経過時間
Dim intNowSec As Integer
'発生した割り込みのカウンター
myTime.intCount += 1
'1/1000秒を取得
intNowSec = Now.Millisecond
'1/1000秒のオーバーフロー発生
If myTime.intBackSec> intNowSec Then
'オーバーフローの回数
myTime.intSec += 1
End If
'前の/1000秒を記憶
myTime.intBackSec = intNowSec
'現在の/1000秒の時刻 + オーバーフロー補正
myTime.intTime(myTime.intCount) = myTime.intSec * 1000 + Now.Millisecond
'現在の時刻からスタート時刻を引く
tsTime = DateTime.Now.Subtract(myTime.timeStart)
'現在の時刻の表示
TextTime.Text = Format(tsTime.Seconds, "00" ) & ":" _
& Format(tsTime.Milliseconds, "000" )
End Sub
計測時間用タイマーのコード
こちらはもう一つのタイマーのコードである。
測定を終了した時に、イベントの間隔の平均値と最大値、最小値をそれぞれ表示している。
特に難しいところは無いであろう。
VB.NET 計測時間用タイマーのコード
'------------------
'計測時間用のタイマー
'------------------
Private Sub Timer2_Tick( ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Timer2.Tick
Dim tsTime As TimeSpan '経過時間
Dim lngSum As Long 'トータルの経過時間
Dim intMax As Integer = 0
Dim IntMini As Integer = 0
Dim intSpan As Integer
Timer2.Enabled = False
Timer1.Enabled = False
'スタート時間からの経過時間
tsTime = DateTime.Now.Subtract(myTime.timeStart)
'経過時間の表示
TextTime.Text = Format(tsTime.Seconds, "00" ) & ":" _
& Format(tsTime.Milliseconds, "000" )
'精密タイマーの各割り込みスパンの計算
For i As Integer = 1 To myTime.intCount - 1
'各スパンを全て足す
intSpan = (myTime.intTime(i + 1) - myTime.intTime(i))
lngSum = lngSum + CLng (intSpan)
If intMax = 0 And IntMini = 0 Then
'初回の処理
intMax = intSpan
IntMini = intSpan
ElseIf IntMini> intSpan Then
'MAXの更新
IntMini = intSpan
ElseIf intMax < intSpan Then
'Miniの更新
intMax = intSpan
End If
Next
TextNo.Text = myTime.intCount.ToString
'平均を出す
TextAve.Text = (lngSum \ myTime.intCount).ToString
TextMax.Text = intMax.ToString
TextMini.Text = IntMini.ToString
End Sub
タイマーの設定値の確認コード
このコードは計測時間をセットした時にその値が適切か否かチェックするコードである。
タイマーの時間は1秒から10秒までの値しか入力出来ないようにしてある。
タイマーの設定値の確認コード
'---------------------------
'タイマーの設定値の確認
'---------------------------
Private Sub TextSpan_Validating( ByVal sender As Object , _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles TextSpan.Validating
If Val(TextSpan.Text)> 10 Then
'設定値が大きすぎる
TextSpan.Text = "10"
TextSpan.Focus()
ElseIf Val(TextSpan.Text) <1 Then
'設定値が小さすぎる
TextSpan.Text = "1"
TextSpan.Focus()
End If
End Sub
End Class
測定結果
測定結果は一秒間に約63回、平均時間は15mSec、最大時間は16mSec、最小時間は15mSecで有った。
何回か測って見たが結果は同じであった。
ただし測定時間を10秒に設定して、測定し、測定中にインターネットエクスプローラーを掴んで、
画面上で激しく上下左右に振ってみたところ、測定値は大きく乱れ、最大値が200mSecを超え、最小値が
0となった、つまるところほかの仕事が忙しい場合はインターバルは不定をなる。
私の経験上、このテストが尤も過酷な方法である、タイマーの精度を気にされる方は、
この辺を考慮に入れて使われたい。
自分の環境で試したい方の為に、コードのサンプルをリンクしておく。
|