Ticket #140 (closed 不具合)

Opened 5 years ago

Last modified 5 years ago

Dual CPU環境等でキーの反応が鈍くなる件について

Reported by: gotoh Assigned to:
Priority: major Milestone:
Component: その他/一般 Version: 3.00 (開発中)
Keywords: Cc:

Description

いしくらです。

# すでに2chに投げているネタです。

自宅PCをAthlon64X2 4600+にいれかえたら、Meadow 3.00-devのキーへの 反応が、以前より悪くなったので、ちょっと調べてみました。

結論から言うとメッセージスレッドの処理がまずそうです。

メッセージスレッドは、キー入力は以下のように処理するようです。 1-1)WaitMessage?()する。 1-2)PeekMessage?()で何かメッセージがが取れたら、

SetEvent?(keyboard_handle)を実行する。
・それがWM_KEYDOWNであれば、input_eventにキー情報を入れる。
・それ以外のメッセージについてはそれなりの処理をする。
メッセージが取れる限り1-2)の処理をくりかえす。

1-3)input_eventをkbd_buffer_store_event()でkbd_bufferに入れる。 1-4)1-1)に戻る。

一方、メイン側のキー入力の待ち方は以下のような感じです。 2-1)ResetEvent?(keyboard_handle)する 2-2)WaitForSingleObject?(keyboard_handle, ...) 2-3)kbd_bufferを読み、処理する。

つまり、待ってる方はeventをトリガにkbd_bufferを見に行くのに、待た せてる方は、eventを出した後にkbd_bufferにセットしてるわけです。 これではHyperThreading環境やDUAL CPU環境など、2スレッド同時実行が 可能な環境では2-3)で空振り(=空のkbd_bufferを読む)するでしょう。 メッセージスレッドは、本来入れるべき情報を kdb_bufferに入れた後に はじめてSetEvent?(keyboard_handle);するよう作るべきでしょう。

しかし、そう修正するのは面倒なので :-) 試しに下記のような修正を入 れて試してみたら、うちの環境ではキーの反応がよくなりました。

  • mw32term.c

    old new  
    47164716            break; 
    47174717          } 
    47184718      } 
     4719      SetEvent (keyboard_handle); 
    47194720     WaitForSingleObject (next_message_block_event, INFINITE); 
    47204721   } 
    47214722 

This ticket was imported from scarab issue MW128

Attachments

Change History

08/26/05 02:29:29 changed by gotoh

[by 三好 雅則]

[meadow-users-jp : No.6511] にて
いしくらさんは書きました:

自宅PCをAthlon64X2 4600+にいれかえたら、Meadow 3.00-devのキーへの
反応が、以前より悪くなったので、ちょっと調べてみました。

結論から言うとメッセージスレッドの処理がまずそうです。

詳しく調査していただき、ありがとうございます。 大変参考になります。もう少し考えてから変更を取り込ませてもらいま す。

つまり、待ってる方はeventをトリガにkbd_bufferを見に行くのに、待た
せてる方は、eventを出した後にkbd_bufferにセットしてるわけです。
これではHyperThreading環境やDUAL CPU環境など、2スレッド同時実行が
可能な環境では2-3)で空振り(=空のkbd_bufferを読む)するでしょう。

この“2スレッド同時実行”というのがさっぱり分からないのですよ。す べてのスレッドが2つ起動されてしまうのかしら?

参考までに、以下の変更で状況が改善するか調べてもらえませんか。

next_message_block_event ってシグナル状態にならないようなので、こ こで WaitForSingleObject?() を呼ぶのはまずいような気がします。

  • mw32term.c

    old new  

08/26/05 02:30:40 changed by gotoh

[by pooh]

参考までに、以下の変更で状況が改善するか調べてもらえませんか。

next_message_block_event ってシグナル状態にならないようなので、こ
こで WaitForSingleObject?() を呼ぶのはまずいような気がします。

ソースを眺めた限りでは、next_message_block_eventはTRUEで初期化されてそ のままなので、あってもなくても結果は変わらないと思います。
#すぐにde-blockされる

08/26/05 02:31:35 changed by gotoh

[by MIYOSHI Masanori]

おっしゃるとおりです。確かに next_message_block_event は、生成時か らシグナル状態のままでした。

でも、手元で試したところ、従来ぎこちなかったキャレットカーソルの移 動が断然スムーズになりました。どうしてでしょうかね。

08/26/05 02:32:21 changed by gotoh

[by ISHIKURA Hiroyuki]

この“2スレッド同時実行”というのがさっぱり分からないのですよ。す
べてのスレッドが2つ起動されてしまうのかしら?

いえいえ違います。

スレッドが以下の3状態を持つとしましょう。

READY: スレッドはCPUを割り当てられるのを待っている状態。
RUN: CPUを割り当てられて実行している状態。 与えらえたCPU時間を使い尽くすとREADYに戻る。
BLOCKED: イベント・その他資源待ち状態。 待っているものが与えられるとREADY状態に戻る。

で、シングルCPU環境だと、RUN状態になっているスレッドの数は1ですが、 Dual/HT環境だと、RUN状態になっているスレッドの数は2つなのです。

つまり、Dual/HT環境だと、メッセージスレッドのイベント発行でBLOCKED からREADYに戻ったキー待ち側は、他のプロセスががしがしCPUを使ってな い限りはすぐにRUNに移行し、kbd_bufferを見に行くことになります。

そしてこの時、やはりRUN状態にあるメッセージスレッドは、kbd_bufferに 何もセットしていない可能性があるのです。kbd_bufferにキー情報を入れ るのはイベント発行より後ですからね。

なので、そんな可能性を残してしまうメッセージスレッドの作りそのもの がまずい、という話になるのです。

next_message_block_event ってシグナル状態にならないようなので、こ
こで WaitForSingleObject?() を呼ぶのはまずいような気がします。

poohさんも書いてますが、next_message_block_eventは初期値がシグナル 状態なので、WaitForSingleObject?()は即時に抜けます。 なので、WaitForSingleObject?()を削除しても変わらないはずですし、実際 削除して試してみても、やっぱり変わりません。

以上です。

08/26/05 02:32:50 changed by gotoh

考えてみました。いしくらさんご指摘の通りだと思います。

mw32_message_loop() のSetEvent (keyboard_handle) を mw32_async_handle_message() に移動しました。

この“2スレッド同時実行”というのがさっぱり分からないのですよ。す
べてのスレッドが2つ起動されてしまうのかしら?

これは、メインスレッドとメッセージスレッドが同時に実行されるという ことでした。スレッドの実行のタイミングが変わるので、HTT やマルチ CPU 環境で問題が露呈したのでした。

  • mw32term.c

    old new  

同時に、こちらの WaitForSingleObject?() も冗長なので削除しました。

08/26/05 02:36:36 changed by gotoh

  • status changed from new to closed.

r3820およびr3821にて対処(by miyoshi)。

08/29/05 18:15:05 changed by gotoh

[by pooh]

まだ処理に抜けがあるようです。 mw32_message_loop を exit_message_loop = 1 で終了してきた場合、 mw32_async_handle_message で WaitMessage を呼ぶのではなく、mw32_message_loop を呼び直す必要があります。

あと別件ですが、show_or_hide_mouse_cursor をたまに呼んであげないと mw32_hide_mouse_timeout が機能しないと思います。

09/02/05 17:36:29 changed by gotoh

[by miyoshi]

mw32_message_loop() の終了状態を引数で受け取るように変更しました。

そして、mw32_message_loop() に未処理のメッセージが残っている場合に は、WaitMessage?() を呼ばないようにしました。

いずれも r3837 にて。


Add/Change #140 (Dual CPU環境等でキーの反応が鈍くなる件について)




Change Properties
Action