Delphiとは直接関係のない内容ですが Delphiでのプログラミングということで
ご容赦いただければ幸いです
以下のようなテストプログラムで sleep関数の引数を1msecとした時の実行時間
をマルチメディアタイマで計測しEditに表示したところ あるPCでは1~2msecと
いう値になり あるPCでは15~16msecという値になります
Windows2000/XPのPCで試しましたが 2000/XPには関係なく1~2msecとなるPCと
15~16msecとなるPCがありました
==========
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, MMSystem;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
t: Integer;
begin
Edit1.Text := '';
t := timeGetTime;
sleep(1);
t := timeGetTime - t;
Edit1.Text := IntToStr(t);
end;
end.
==========
実際のアプリケーションでは 複数のスレッドを同時に起動して それぞれのス
レッド内でループを廻しています その中でsleep関数を使用しています
sleep関数の実行時間がPCによって 1~2msecの場合と15~16msecの場合があり
何故こういうことが起こるのかを調べてみましたが 検索の仕方が悪いのか
「これだ」というものを見つけることができませんでした
検索に引っ掛かったページの記述から sleep関数の引数を1とすることが そも
そも間違いであるような気はしていますが PCによってsleep関数の実行時間が
大きく違うことが理解できずにおります
可能であれば どのPCでもsleep(1)の実行時間が1~2msecとなるようにしたので
すが 何か方法があればご教授いただけませんでしょうか?
よろしくお願いいたします
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
白坂 勝治
e-mail:sira...@hi-ho.ne.jp
Nifty:QFG0...@Nifty.com
「timeBeginPeriod sleep」のキーワードで検索してみてください.
以上です.
timeBeginPeriod(1);
t := timeGetTime;
sleep(1);
t := timeGetTime - t;
timeEndPeriod(1);
と してみましたが 結果は変わらずでした
timeGetDeviceCapsでwPeriodMinを取得してみたところ sleep関数の実行時間に
拘らず どのPCでも最小値は1でした
Win2k上のD7 Proで開発を行っております
1~2msecと表示されるPCの中の1台は Win2K SP4/P3 1.0GHz Dual/Mem 1280MByte
15~16msecと表示されるPCの中の1台は Win2K SP4/P4 1.8GHz/Mem 1024MByte
PCのスペックとしては それほど差があるとは思えないのですけれども・・・
CPUのDual/Singleの違いによるものかも?ってことで PentiumD/XPのPCで試し
たりもしましたが 15~16msecの時間になりました 片やCeleron2.4GHz/XPのPC
で1~2msecとなるPCもあります
アプリケーションは ループを廻して1ループ毎にsleepで止めながらポーリング
するようなものでしたが 三日間ほど悩んでまして時間も無くなってきましたの
で TEventを使用して同期するような形に書き換えることで とりあえず対処し
ましたけれども PCによってsleepの実行時間に差が出るのが何故なのか判らな
いままで悶々としてます^^; たまたまそうなってるだけってことなんでしょう
か?
何を期待されているのかが良くわからないのですが、MSDNの
Sleepの解説にあるとおりで、
| The Sleep function suspends the execution of the current
| thread for at least the specified interval.
(超訳)
| Sleep関数は少なくとも指定された間、カレントスレッドの実行を
| サスペンドします。
Sleep関数はカレントスレッドの実行を最低でも(at least)指定
された時間の間だけ停止します。ですから1を指定したからと
いって1msecでSleepから帰ってくるというものではありません。
OSからみて優先度の高い作業があればもっと待たされるという
ことも十分にありえますし、Sleepで停止する時間の解像度も
1msec単位とは限りません。
> アプリケーションはループを廻して1ループ毎にsleepで止め
> ながらポーリングするようなものでしたが三日間ほど悩んで
> まして時間も無くなってきましたのでTEventを使用して同期
> するような形に書き換えることでとりあえず対処しましたけれども
というわけでこれが正解です。メインスレッド上でビジー
ループを使用してポーリングするのはWindowsのお作法に
反しています。
+=========+=========+=========+=========+=========+=========+=========+
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp
+=========+=========+=========+=========+=========+=========+=========+
白坂さん:
> 可能であれば どのPCでもsleep(1)の実行時間が1~2msecとなるように
> した(い)のですが 何か方法があればご教授いただけませんでしょうか?
これ、すごく難しいです。 Windows のタスク切り替え(コンテキスト
スイッチング)の方法に立ち入る内容だからです。 それを実現しようと
すると、(1)スレッドの優先度を tpRealTime 近くに高めた上、timeBegin-
Period APIを呼び出すか、(2)外付けのハードウェアを使うしかない
ように思います。 いずれにしても、他のアプリケーションには副作用が
及びます。
> PentiumD/XPのPCで試したりもしましたが 15~16msecの時間になりました
> 片やCeleron2.4GHz/XPのPCで1~2msecとなるPCもあります
> PCによってsleepの実行時間に差が出るのが何故なのか判らないままで
> 悶々としてます^^; たまたまそうなってるだけってことなんでしょうか?
コンテキストスイッチングのアルゴリズムでは、他に動作している
アプリケーション(スレッド)の数、スレッド優先度、スレッドが作成した
ウィンドウがフォーカスを持っているか、スレッドが過去に実行されずに
いた経過時間、他のアプリケーションがマルチメディアタイマをどのように
使っているかなど、いろいろな要素が検討されて次に実行されるスレッドが
決まります。 Sleep の実行時間が長いというのは、何らかの理由でその
スレッドに実行順番が回りにくくなっているものと思われます。 スレッドの
優先度を上げてみたり(タスクマネージャでできます)、ウィンドウに
フォーカスを当ててみたりすると、待ち時間は短くなりませんか?
――――――――――――――――――――――――――――――――――――
株式会社イマジオム 代表取締役 高木太郎
〒316-0024 茨城県 日立市 水木町 1-11-10
電話:0294-28-0147
ファクシミリ:0294-28-0148
電子メール:tarou_...@imageom.co.jp
ホームページ:http://www.imageom.co.jp/
高木さん 福士さん ご教授ありがとうございました
sleep(1)とすることが そもそもの間違いであることは理解できましたが PCに
よってこれほど差が出るとは思えずに悩んでおりました
どのPCでもある程度一律の時間であれば「そんなもの」で済ませられたと思うの
ですが Win2kのセットアップのみで他のアプリケーションは一切走っていない
PCで15~16msecなのに 複数のアプリケーションを起動して1~2msecのPCがあっ
たりするものですから タスクの切替のバラツキにしては差が大きいなぁという
印象でした・・・でも「そんなもの」ってことなんですね
色々勉強になりました ありがとうございました
白坂さん:
> どのPCでもある程度一律の時間であれば「そんなもの」で済ませられたと
> 思うのですが Win2kのセットアップのみで他のアプリケーションは一切
> 走っていないPCで15~16msecなのに 複数のアプリケーションを起動して
> 1~2msecのPCがあったりするものですから タスクの切替のバラツキに
> しては差が大きいなぁという印象でした・・・でも「そんなもの」って
> ことなんですね
はい。 約15[ms]が Windows のデフォルト状態での自然な Sleep
時間分解能です。 1~2[ms]になっているのは、マルチメディアや
ゲーム、CDライタといった「タイムクリティカル」なアプリケーションが、
Windows の状態を( timeBeginPeriod で)変えた結果だと思われます。
正確なタイマとして Sleep(1) を使うのはまずいですが、単なる待ちには
Sleep(1) を Application.ProcessMessages と合わせてよく使います。
On Wed, 19 Dec 2007 17:35:11 +0900
aaa1...@pop06.odn.ne.jp (高木太郎) wrote:
> はい。 約15[ms]が Windows のデフォルト状態での自然な Sleep
> 時間分解能です。 1~2[ms]になっているのは、マルチメディアや
> ゲーム、CDライタといった「タイムクリティカル」なアプリケーションが、
> Windows の状態を( timeBeginPeriod で)変えた結果だと思われます。
なるほど・・・インストール済みまたは実行中のアプリケーションの中の「誰か」
がtimeBeginPeriodで時間分解能を変更しているということなんですね
時間があれば「犯人^^;」を突き止めてみたいと思います
> 正確なタイマとして Sleep(1) を使うのはまずいですが、単なる待ちには
> Sleep(1) を Application.ProcessMessages と合わせてよく使います。
はい 正確でなくて全然構わないのですが せめて5msecくらいにできるのなら
sleep使用のままでいけるかなぁと思っておりました
15msecとなるとちょっと待ち時間が長くて それが積み重なると「我慢できない」
くらいの時間になっておりました 5msec程度にすることができれば「我慢でき
る」時間だったのですけれども・・・
----- Original Message -----
From: "Katsuji Shirasaka" <sira...@hi-ho.ne.jp>
To: <Del...@ml.users.gr.jp>
Sent: Wednesday, December 19, 2007 5:56 PM
Subject: [Delphi:90151] Re: sleep関数
>> はい。 約15[ms]が Windows のデフォルト状態での自然な Sleep
>> 時間分解能です。 1~2[ms]になっているのは、マルチメディアや
>> ゲーム、CDライタといった「タイムクリティカル」なアプリケーションが、
>> Windows の状態を( timeBeginPeriod で)変えた結果だと思われます。
> なるほど・・・インストール済みまたは実行中のアプリケーションの中の「誰か」
> がtimeBeginPeriodで時間分解能を変更しているということなんですね
> 時間があれば「犯人^^;」を突き止めてみたいと思います
タイマ分解能については、何度か話題がありましたが
最後に Halbow さんが
# [Delphi:71547] Re: 計測時間間隔が重要
で取りまとめておられます。
内容は About Delphi で探せます。
http://www2.big.or.jp/~osamu/Delphi/
CPU も数桁高速化してますので timeBeginPeriod とtimeEndPeriod でインターバルを
変えてみるのもよいことだと思います。 VB ですが、こちらに話題がありました。
http://www.mb.ccnw.ne.jp/garger-studio/vbgame/131.html
参考になるかも知れません。
---- (-_-)(-_-)(-_-) THE REAL PROGRAMMER (-_-)(-_-)(-_-) ----
At the beach, The Real Programmer is the one drawing flowcharts in the sand.
戸田 英夫 mailto: hideo...@ntt-neo.co.jp
On Thu, 20 Dec 2007 16:54:57 +0900
戸田 英夫 <hideo...@ntt-neo.co.jp> wrote:
> CPU も数桁高速化してますので timeBeginPeriod とtimeEndPeriod でインターバルを
> 変えてみるのもよいことだと思います。 VB ですが、こちらに話題がありました。
> http://www.mb.ccnw.ne.jp/garger-studio/vbgame/131.html
本日午前中にこちらのペィジを見つけて タイマ分解能を1msecとしてsleep(1)
の実行時間を1~2msecとすることができました
ポーリングの部分は既にTEventで書き換えてしまっていますが スレッドの実行
過程で ハードウェアアクセスのためにsleepでウェイトを入れている部分が多
数ありまして PCによってウェイトの具合がまちまちだったものが どのPCでも
同じsleep時間でウェイトできるようになりました
昨日timeBeginPeriod~timeEndPeriodで上手くいかなかったのは このペィジに
書いてある「timeBeginPeriodを呼び出してもすぐには精度が変わりません。」
によるものでした 昨日はtimeBeginPeriodの直後にsleepを実行していましたの
で 分解能の変更が反映されていない状態だったものと思います 先ほどまでそ
のあたりの確認作業を行っておりました
過去ログも検索はしていたのですが sleepばかりに気を取られてHalbowさんの
投稿を見つけることができませんでした
sleepを使うかどうかは別にして 頭の中でもやもやしてたものがすっきりとし
ました
少し興味があったので試してみました。
環境 WindowsXP Home SP2, Delphi7 Professional
(1)
procedure TForm1.Button1Click(Sender: TObject);
var
t: Integer;
begin
Edit1.Text := '';
t := timeGetTime;
sleep(1);
t := timeGetTime - t;
Edit1.Text := IntToStr(t);
end;
の場合。
必ず15 or 16 ミリ秒となります。
(2)timeGetTimeの精度にも問題があるかもしれないので、
現在一番高性能(と私が思っている)PerformaceCounter APIを使ってみました。
小数点以下はマイクロ秒(1000分の1ミリ秒)です。
procedure TForm1.Button2Click(Sender: TObject);
var
StartTime, StopTime, Frequency: Int64;
Interval: Extended;
begin
Edit1.Text := '';
QueryPerformanceFrequency(Frequency); // PCの周波数を取得
QueryPerformanceCounter(StartTime); // 起動時よりのクロック数を取得
sleep(1);
QueryPerformanceCounter(StopTime); // 起動時よりのクロック数を取得
Interval := (StopTime - StartTime) / Frequency * 1000; // ミリ秒単位に変換
Edit1.Text := Format('%.3f', [Interval]);
end;
の場合。
14ミリ秒台から0.2ミリ秒の間で様々な値が得られました。
15ミリ秒以上の結果は得られませんでしたが、根気よくボタンをクリックし続ければ出るかもしれません。
ただし、Sleep1ミリ秒に問題があるのではなく、Sleep値を大きくしても結果は同様です。
ただし、Sleep値が大きくなるほど誤差は縮まり、100ミリ秒くらいにするとかなり安定します。
----- Original Message -----
From: "Katsuji Shirasaka" <sira...@hi-ho.ne.jp>
To: <Del...@ml.users.gr.jp>
Sent: Thursday, December 20, 2007 6:37 PM
Subject: [Delphi:90155] Re: sleep関数
> 本日午前中にこちらのペィジを見つけて タイマ分解能を1msecとしてsleep(1)
> の実行時間を1~2msecとすることができました
> ポーリングの部分は既にTEventで書き換えてしまっていますが スレッドの実行
> 過程で ハードウェアアクセスのためにsleepでウェイトを入れている部分が多
> 数ありまして PCによってウェイトの具合がまちまちだったものが どのPCでも
> 同じsleep時間でウェイトできるようになりました
ただし TimeBeginPeriod は実行中の全プロセスに影響します、つまり他のプロセスで
TimeEndPeriod されると、影響があると思いますので注意が必要と思います。
> sleepを使うかどうかは別にして 頭の中でもやもやしてたものがすっきりとし
> ました
自前で Hires Timer が必要ならコンポーネントの利用を考慮するのも如何でしょう。
Torry は
http://www.swissdelphicenter.ch/torry/
に変わってます。
DSP は
http://delphi.icm.edu.pl/
で、益々発展拡大しています。
On Fri, 21 Dec 2007 14:45:11 +0900
戸田 英夫 <hideo...@ntt-neo.co.jp> wrote:
> ただし TimeBeginPeriod は実行中の全プロセスに影響します、つまり他のプロセスで
>
> TimeEndPeriod されると、影響があると思いますので注意が必要と思います。
実際のアプリケーションはFA設備に組み込まれるデータ収集システムで 基本的
には他のアプリケーションを同時に起動することはありませんので Windowsそ
のものと実装するハードウェアのドライバさえちゃんと動いていてくれれば
timeBeginPeriod~timeEndPeriodでも成り立つ話なのかなぁと思ってます
> 自前で Hires Timer が必要ならコンポーネントの利用を考慮するのも如何でしょう。
今回はsleepで十分なのですが 機会があればコンポーネントの利用も考慮した
いと思います
最近過去ログすら読んでいなかったのですが、、、
On Fri, 21 Dec 2007 16:23:52 +0900
Katsuji Shirasaka <sira...@hi-ho.ne.jp> wrote:
> 実際のアプリケーションはFA設備に組み込まれるデータ収集システムで 基本的
> には他のアプリケーションを同時に起動することはありませんので Windowsそ
> のものと実装するハードウェアのドライバさえちゃんと動いていてくれれば
ロギングというと監視設備か計測か何かでしょうか?
新規だと、いろいろいけますが改造で既設のものがあると
それはそれできついんですよね。
fa-developer-ML というMLをご存じでしょうか?
Becky! ユーザとお見受けしましたので、
過去ログを見るのにも楽ではないのかなと、思います。
http://www.kogasw.com/fa-developer/index.html
過去ログに眼を通すと、おもしろい発見があるかと思いますよ。
;
; sn...@i-ml.com
;