3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DelphiのTStopwatchで時間を計測する

Posted at

以下のこのコードはDelphi 13で検証しています。

はじめに

Delphiのコードの処理時間の測定する機会がありましたので,TStopwatchを使ってみました。
Vcl(つまりWindows環境)だと,GetTickCountをこれまで使っていたのですが,取得するのはシステムが開始してからの経過時間でCardinal(UInt32)が返されるため,コードの特定の部分を複数回実行してかかる時間の合計を出すには少しコードを描く必要がありました。
そこで,TStopwatchでどのくらい簡単に時間を計測できるか調べるため,簡単なストップウォッチのサンプルプログラムを書きたいと思います。

今回のサンプルプログラムはVclで書きましたが,TStopwatchはSystem.Diagnosticsで定義されていますので,VclとFMXのどちらでも利用可能です。

TStopwatchの初期化

まずは,TStopwatchについて調べます。
TStopwatchはレコード型で定義されているのですが,初期化が必要です。
2つの方法が提供されています。

  • 初期化だけをしたい場合:
StopWatch := TStopWatch.Create;
  • 初期化してすぐに計測をスタートする場合:
StopWatch := TStopWatch.StartNow;

StopWatch.Start;というよく似た名前のメソッドがあるのですが,Stopwatch.StartNow;は TStopWatchを初期化して返しますので注意が必要です。

計測の開始と終了

  • 初期化されたStopwatchの計測をスタートする。※計測値は初期化されません。
StopWatch.Start;
  • 計測中のStopwatchの計測をストップする。※計測値は初期化されません。
StopWatch.Stop;
  • Stopwatchの計測値をリセットする。
StopWatch.Reset;

計測結果の取得方法

主に3つのプロパティで計測値を取得できます。

プロパティ 説明
Elapsed 計測値を,System.TimeSpanユニットで定義されているTTimeSpanで返します。
ElapsedMilliseconds 計測値のミリ秒を,Int64で返します。
ElapsedTicks 計測値のカウント数を,Int64で返します。

これらのプロパティは計測中に計測値を読み出せるだけでなく,一旦Stopメソッドで計測を停止させてから,後で計測値を読み出すこともできます。

高解像度タイマを利用できているかの確認方法

IsHighResolutionプロパティで高精度タイマが使用されているかを確認できます。

サンプルコード

これを踏まえて,簡単なストップウォッチのサンプルを作ることにしました。

  • 以下のようにVclフォームForm1に,Label1: TLabelButton1: TButton,Button2: TButton,Button3: TButtonそしてTimer1: TTimerを配置します。(Label1のフォントサイズを少し大きくしています。)
    Snap20260111_0000.png

  • インターフェースのuses節にSystem.Diagnosticsを追加します。

uses
  ・・・()・・・,
  System.Diagnostics;
  • Form1のPrivate宣言にFStpwatchを以下のように追加します。
  private
    { Private 宣言 }
    FStopwatch: TStopwatch;
  • フォームForm1のOnCreateイベントを追加し,以下のように書きます。
    Timer1IntervalLabel1のフレームレートを40fpsになるように25を設定しています。この値はの更新の頻度になりますので,適当に値を変更していただいて構いません。
    高解像度タイマを使っているときにはラベルの文字を赤色にしています。
procedure TForm1.FormCreate(Sender: TObject);
begin
  FStopWatch := TStopWatch.Create;
  Timer1.Interval := 25; // 40fps
  if FStopWatch.IsHighResolution then begin
    Label1.Font.Color := clRed;
  end;
end;
  • Button1: TButtonのOnClickイベントで計測をスタートします。
procedure TForm1.Button1Click(Sender: TObject);
begin
  FStopwatch.Start;
end;
  • Button2: TButtonのOnClickイベントで計測をストップします。
procedure TForm1.Button2Click(Sender: TObject);
begin
  FStopwatch.Stop;
end;
  • Button3: TButtonのOnClickイベントで計測値をリセットします。
procedure TForm1.Button3Click(Sender: TObject);
begin
  FStopwatch.Reset;
end;
  • Timer1: TTimerのOnTimerイベントで計測値を表示します。
    今回は,ElapsedMillisecondsプロパティを使いましたが,紹介した別のプロパティを使っていただいてもかまいません。
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := FStopwatch.ElapsedMilliseconds.ToString;
end;

全て記述すると以下のようになります。Unit1.pasで保存します。

Unit1.pas
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  System.Diagnostics;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private 宣言 }
    FStopwatch: TStopwatch;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  FStopwatch.Start;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FStopwatch.Stop;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  FStopwatch.Reset;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FStopwatch := TStopwatch.Create;
  if FStopwatch.IsHighResolution then begin
    Label1.Font.Color := clRed;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := FStopwatch.ElapsedMilliseconds.ToString;
end;

end.

実行すると,StopWatchがどのような計測値を保持しているかが理解できると思います。

まとめ

TStopwatchを使うと簡単に繰り返し処理の中の特定の処理にかかる時間を測定できそうです。
処理を見通せる場所にTStopwatchを配置し,初期化してから計測を行い,任意のタイミングで計測結果が表示できます。
利用時には初期化が必要です。測定が一度きりで済むならStartNewで,計測を断続的に累積して行うならCreateでやるとよいのではないかと思います。

参考URL

謝辞

dekoさんの Delphi Programming -経過時間を得るには?
を参考にさせていただきました。この場を借りてお礼申し上げます。

誤って理解していることがあればご指摘いただけるとありがたいです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?