HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0117
csowaitの待ち時間について10解決


cso

リンク

2014/1/17(Fri) 21:48:16|NO.59353

下記のスクリプトを実行すると実行したパソコンによってカウントの早さが違うことがあります。

dell製PC windows7では waitは10ms×100の待ち時間でカウントしますが、
asus製PC windowsXPでは waitは1ms×100の待ち時間でカウントすることがありました。

asus製PCは常時稼動しており、
PC起動から2,3週間くらいは、waitは10ms×100で動作しているのですが、
1ヶ月たった状態で、スクリプト実行すると1ms×100になってしまいます。
PC再起動すると 10ms×100に戻ります。

count = 0
*main

count = count + 1
pos 0,0:color 255,255,255:boxf 0,0,30,30
pos 0,0:color 0,0,0:mes count

wait 100

goto *main

【質問】
・スクリプトがよくないでしょうか?
・wait命令はPCの種類、稼働時間、状態によって待ち時間が変わるのでしょうか?



この記事に返信する


暇人

リンク

2014/1/18(Sat) 03:28:38|NO.59357

最小の待ち時間は環境依存だけど
wait 100の待ち時間が環境で変るのはおかしいな・・・
自分のXPは現在29日電源切って無い状態だけど今の所問題ない
現在wait自体がバグ持ちなのは確実だけど、これも同じ原因なのか分からない

wait 1 が不安定
http://hsp.tv/play/pforum.php?mode=pastwch&num=54114



cso

リンク

2014/1/18(Sat) 11:08:24|NO.59359

返信ありがとうございます!

OSや、稼働時間は関係なさそうですね。
waitは不安定な要素があるということですね、
この状況は自分だけなのかな・・・と思って検索してたら下の知恵袋の質問と同じ状態のように思います。

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1055179015

運が悪いとたまにある。ということなのかなぁ?



check

リンク

2014/1/18(Sat) 11:26:49|NO.59360

HSPのwaitが中で何を使って時間を計測しているのかは分からないが、
タイマーの精度を1秒と1ミリ秒に変えてもほとんど差がなかったので、
もしかしたらtimeGetTimeの戻り値が大きすぎるとバグが起きるのかもしれない。
(timeGetTimeはOSが起動してからの時間を返す)

検証に使ったコード

#include "winmm.as" #module #deffunc getwait timeGetTime ts = stat wait 100 timeGetTime te = stat mes "" + double(te-ts) + " ellapsed." return #global // 精度を1秒に変える timeBeginPeriod 1000 getwait timeEndPeriod 1000 // 精度を1ミリ秒に変える timeBeginPeriod 1 getwait timeEndPeriod 1



暇人

リンク

2014/1/18(Sat) 12:05:18|NO.59361

>自分のXPは現在29日電源切って無い状態だけど今の所問題ない
これは勘違いだった・・・
計算したら一週間前に再起動してました・・・

一ヶ月ぐらいでおかしくなるなら
25日で稼働時間が$7fffffffmsを超えて
マイナスになるからバグが起こってるのかも・・・



cso

リンク

2014/1/18(Sat) 20:50:01|NO.59367

checkさん、暇人さんありがとうございます。

現在のtimeGetTimeの値は8d8363d0でした。
現象が発生しだしたのが、2〜3日前ぐらいだったように記憶しています。

timeGetTimeの値が原因でしょうか?



暇人

リンク

2014/1/18(Sat) 22:02:18|NO.59370


mes $8d8363d0 mes ($8d8363d0-1000*60*60*24*3) //3日前
上が負数
下の方は正数になるのでバグが起こる条件は
起動時間が$7fffffff(2147483647)を超えて負数になる事なのは確定だろう



setton

リンク

2014/1/19(Sun) 03:56:55|NO.59379

wait関係のソースは
http://dev.onionsoft.net/trac/browser/trunk/hsp3/win32gui/hsp3win.cpp 192行
http://dev.onionsoft.net/trac/browser/trunk/hsp3/hsp3code.cpp 1801行 2437行
あたりにありますがざっとソースをざっと見た感じ
http://dev.onionsoft.net/trac/browser/trunk/hsp3/hsp3code.cppの2446行目で
hspctx->waittick = tick + ( hspctx->waitcount * 10 );

となっているが、PCを長期間稼働し続けてGetTickCountが負数になるとこの値が負数になるので2457行目で
hspctx->waittick = hspctx->lasttick + hspctx->waitcount;
と値がセットし直されるのが原因みたいですね。
このときwaitcountが10倍されないので1msしか待機しないと。

http://hsp.tv/play/pforum.php?mode=pastwch&num=54114
この原因は
http://dev.onionsoft.net/trac/browser/trunk/hsp3/win32gui/hsp3win.cpp 192行目で
精度の悪いGetTickCountを使ってるのが原因のような気がする。
あんまり自信ないですけど。



cso

リンク

2014/1/19(Sun) 13:15:16|NO.59383

暇人さん、settonさんありがとうございます。

settonさんの示してくれた箇所周辺を見ると
確かにhspctx->waittickは*10していない値にセットし直されそうですね!

現状ではGetTickCountが負数になる稼働時間のPCで
waitを使用するときには注意が必要ですね。

みなさまの調査とても勉強になりました。見習っていきたいです。
checkさん、暇人さん、settonさんありがとうございました!!



setton

リンク

2014/1/26(Sun) 01:01:27|NO.59506

一応HSPwikiのバグトラックに書いとこうと思ったらエラーになるのでここに書き込みます。
>開発者の方へ
PCを25日弱連続で使うと質問者の問題がおきます
以下の2点を修正することで解決できると思います。
http://dev.onionsoft.net/trac/browser/trunk/hsp3/hsp3code.cppの2455行目
if ( hspctx->waittick < 0 ) {
if ( hspctx->waittick == -1 ) {
に変更。
同2459行目の
if ( tick >= hspctx->waittick ) {
if ( tick - hspctx->waittick >= 0 ) {
2点目は修正しないと滅多にないがwaitで延々と待機し続けることがあります。
以上でも問題は残りますが実用上ほぼ問題ないと思います。

wait 1 が不安定(http://hsp.tv/play/pforum.php?mode=pastwch&num=54114)
ついでにこの問題ですがhttp://dev.onionsoft.net/trac/browser/trunk/hsp3/win32gui/hsp3win.cppの193行目で
GetTickCountを使いその他でtimeGetTimeを使って混在させてるのが原因みたいです。
二つの関数の精度の違いで起こります。

以下は検証用スクリプト
入力ボックスの値がwaitのパラメータ
上のバーはループ一回の時間
下のバーはGetTickCountとtimeGetTimeの差で緑のとき+で赤のときが-。
この差の分だけ待機時間の理論値とずれが生じるはずです。
起動時のタイミングにより-10ms以上の差が出ると待機時間が0(wait 0と同等)になりCPUが100%になるみたいです。


#include "winmm.as" #include "kernel32.as" #include "comctl32.as" sx=600:sy=110 screen 0,sx,sy,1 //なるべく描画の負荷の影響を減らすためにパレットモードにして更新も最小限にする wt=1 input wt,50,25 ic=8,16 InitCommonControlsEx varptr(ic) CreateUpDownControl 0x50800086,0,0,0,0,hwnd,0x10000,hinstance,objinfo_hwnd(0),1000,0,wt palette 1,255,0,0,0 palette 2,0,255,0,0 palette 3,0,0,255,1 //目盛り描画 repeat sx/5 line cnt*5,sy-20,cnt*5,sy-30 if cnt\5==0:line cnt*5,sy-20,cnt*5,sy-35 if cnt\10==0:line cnt*5,sy-20,cnt*5,sy-40 : pos cnt*5-10,sy-20:mes cnt loop repeat crtime=timeGetTime() diftime=GetTickCount()-crtime looptime=crtime-pretime pretime=crtime wait wt redraw 0 color 255,255,255 boxf 0,30,sx,70 color 0,0,255 boxf 0,30,looptime*5,50 if diftime>=0:color 0,255,0:else:color 255,0,0:diftime=-diftime boxf 0,50,diftime*5,70 redraw 1,0,30,sx,40 if crtime-pretime2>=1000{ //fps表示 redraw 0 color 255,255,255 boxf 50,0,150,25 color pos 50,0 mes "fps="+fps redraw 1,50,0,100,25 fps=0 pretime2=crtime } fps++ loop



setton

リンク

2014/1/26(Sun) 01:09:59|NO.59507

さっきの検証用スクリプトはそのままじゃ動かなかったです。
以下の部分をさっきのスクリプトの一番上に足してください。
userdef.asに登録してるので忘れてた。


//WIN32APIを関数でも使えるようにするモジュール #module #deffunc kansuninare #define STRUCTDAT_OT_STATEMENT 2 #define STRUCTDAT_OT_FUNCTION 4 #define STRUCTPRM_SUBID_DLL (-3) #define STRUCTPRM_SUBID_DLLINIT (-4) mref hspctx,68 dupptr hsphed,hspctx,96 if hsphed.15>0{ dupptr structdat,hspctx.210,hsphed.15 repeat hsphed.15/28 subid=structdat(7*cnt)>>16 if (subid==STRUCTPRM_SUBID_DLL | subid==STRUCTPRM_SUBID_DLLINIT) & (structdat(7*cnt+5)==STRUCTDAT_OT_STATEMENT){ structdat(7*cnt+5)|=STRUCTDAT_OT_FUNCTION } loop } return #global kansuninare



ONION software Copyright 1997-2021(c) All rights reserved.