Bug #3890

ビジースレッドがあるとコンテキストスイッチが起きづらくなる

Added by Usaku NAKAMURA almost 5 years ago. Updated over 4 years ago.

[ruby-dev:42315]
Status:Closed
Priority:Normal
Assignee:Koichi Sasada
ruby -v:ruby 1.9.3dev (2010-09-29 trunk 29361) [x64-mswin64_90] Backport:

Description

=begin
こんにちは、なかむら(う)です。
とりあえずチケット化するために全文引用します。
遅いのはfeatureかbugか... bugでいいか。

ちなみに
ruby 1.9.3dev (2010-09-30 trunk 29375) [i386-mswin32]
では再現していません。
x64版固有とかCPUコア数とかと関係するとかですかね。

In message " ビジースレッドがあるとコンテキストスイッチが起きづらくなる"
on Sep.29,2010 21:16:52, beuniv@gmail.com wrote:

こんにちは。
ビジー状態のスレッドがあると中々他のスレッドに処理が戻らず実行速度が遅くなることがあります。
環境はruby 1.9.3dev (2010-09-29 trunk 29361) [x64-mswin64_90]です。

以下のスクリプトを実行すると終了するまでに時間がかかります。

t = Time.now
n = 0
Thread.new{loop {n+=1} }
Thread.new{}.join
p [n, Time.now - t]

.\ruby.exe a.rb
[82741230, 10.6304]

追ってみたところnative_sleepのGVL_UNLOCK_ENDで、mainスレッドが
GVLを取得できずに止まっている時間が長いようです。
ためしにCriticalSectionではなく、USE_WIN32_MUTEXで、Mutexを使うように変更するとすぐ終わるようになりました。

MutexLock版
.\ruby.exe a.rb
[65482, 0.017]

ruby/test_threads.rb:test_listが結構な割合で失敗するので気がつきました。

kuwamoto

それでは。
--
U.Nakamura usa@garbagecollect.jp
=end


Related issues

Related to Ruby trunk - Bug #2359: test_threads.rb:test_list Closed 11/12/2009

Associated revisions

Revision 29956
Added by Koichi Sasada over 4 years ago

  • thread.c, vm_core.h: make gvl_acquire/release/init/destruct APIs to modularize GVL implementation.
  • thread_pthread.c, thread_pthread.h: Two GVL implementations. (1) Simple locking GVL which is same as existing GVL. (2) Wake-up queued threads. The wake-up order is simple FIFO. (We can make several queues to support exact priorities, however this causes some issues such as priority inversion and so on.) This impl. prevents spin-loop (*1) caused on SMP environemnts. *1: Only one Ruby thread acqures GVL again and again. Bug #2359
  • thread_win32.c, thread_win32.h: Using simple lock not by CRITICAL_SECTION but by Mutex. Bug #3890
  • vm.c (ruby_vm_destruct): ditto.

Revision 29956
Added by Koichi Sasada over 4 years ago

  • thread.c, vm_core.h: make gvl_acquire/release/init/destruct APIs to modularize GVL implementation.
  • thread_pthread.c, thread_pthread.h: Two GVL implementations. (1) Simple locking GVL which is same as existing GVL. (2) Wake-up queued threads. The wake-up order is simple FIFO. (We can make several queues to support exact priorities, however this causes some issues such as priority inversion and so on.) This impl. prevents spin-loop (*1) caused on SMP environemnts. *1: Only one Ruby thread acqures GVL again and again. Bug #2359
  • thread_win32.c, thread_win32.h: Using simple lock not by CRITICAL_SECTION but by Mutex. Bug #3890
  • vm.c (ruby_vm_destruct): ditto.

History

#1 Updated by Usaku NAKAMURA almost 5 years ago

  • Category set to core
  • Status changed from Open to Assigned
  • Assignee set to Usaku NAKAMURA
  • Target version set to 2.0.0
  • ruby -v set to ruby 1.9.3dev (2010-09-29 trunk 29361) [x64-mswin64_90]

=begin

=end

#2 Updated by shintaro kuwamoto almost 5 years ago

=begin
こんにちは。

コア数のようですね。Corei7 940 HT有りで見かけ上8コアで動かしてます。
affinity maskを設定して動かすと3コアぐらいから競合が増えているように見えます。
時間は結構ぶれがあるので参考程度です。

start /affinity 0x1 .\ruby.exe a.rb
start /affinity 0x3 .\ruby.exe a.rb
start /affinity 0x7 .\ruby.exe a.rb
start /affinity 0xF .\ruby.exe a.rb
start /affinity 0x1F .\ruby.exe a.rb
start /affinity 0x3F .\ruby.exe a.rb
start /affinity 0x7F .\ruby.exe a.rb
start /affinity 0xFF .\ruby.exe a.rb

CPU COUNT TIME
1 [491032, 0.11]
2 [92323, 0.013]
3 [6901444, 0.8736]
4 [8894934, 1.56]
5 [6975323, 0.9984]
6 [124533026, 15.7444]
7 [48895362, 5.981]
8 [9636525, 1.2842]

今のところ複数コアでもあまりうれしくないので、常に1コアでもいいのかなあ。
native_thread_yieldをSleep(1)にすると8コアでもすぐ終わるようになるんですが。

--
kuwamoto

=end

#3 Updated by Koichi Sasada almost 5 years ago

=begin
 ささだです。

(2010/09/30 12:48), kuwamoto shintaro wrote:

コア数のようですね。Corei7 940 HT有りで見かけ上8コアで動かしてます。
affinity maskを設定して動かすと3コアぐらいから競合が増えているように見えます。
時間は結構ぶれがあるので参考程度です。
...
今のところ複数コアでもあまりうれしくないので、常に1コアでもいいのかなあ。
native_thread_yieldをSleep(1)にすると8コアでもすぐ終わるようになるんですが。

 この問題に関しては、まさに native_thread_yield() の実装というか、その
辺の実装(GVLの受け渡しの実装)の問題として、既知のものです(Linux 8
core で(多分)同様の問題が出ています。というか、もっとひどくてコンテキ
ストスイッチしないという)。

 もう少ししたら、実装を直そうと思いますので、その時に、またお試し頂けれ
ばと思います。

--
// SASADA Koichi at atdot dot net

=end

#4 Updated by Usaku NAKAMURA almost 5 years ago

  • Assignee changed from Usaku NAKAMURA to Koichi Sasada

=begin
笹田さんが把握してて直す気もあるということなのでアサインしておきますね。
=end

#5 Updated by shintaro kuwamoto almost 5 years ago

=begin
こんにちは

 この問題に関しては、まさに native_thread_yield() の実装というか、その
辺の実装(GVLの受け渡しの実装)の問題として、既知のものです

なるほど了解です。

ついでですが、
http://redmine.ruby-lang.org/issues/show/2359
も同じ原因のような気がします

--
kuwamoto

=end

#6 Updated by Koichi Sasada over 4 years ago

=begin
(2010/09/30 9:42), U.Nakamura wrote:

ためしにCriticalSectionではなく、USE_WIN32_MUTEXで、Mutexを使うように変更するとすぐ終わるようになりました。

 安易ですが、mutex を使うようにしてみました。どうでしょうか。

--
// SASADA Koichi at atdot dot net

=end

#7 Updated by Koichi Sasada over 4 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r29956.
Usaku, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

#8 Updated by shintaro kuwamoto over 4 years ago

=begin
ruby 1.9.3dev (2010-11-28 trunk 29965) [x64-mswin64_90]
ですぐに終了すること確認しました。
対応ありがとうございます。

=end

Also available in: Atom PDF