遠藤です。

2011年3月7日9:47 Masaki Matsushita <redmine / ruby-lang.org>:
> sora_hさんが書いたパッチと異なる点は、トランザクションに入っているスレッドがあるかどうかを格納しているインスタンス変数@transactionを廃して、
> Mutexがロックされているかどうかでトランザクションに入っているスレッドがあるかどうかを判定している点です。
> また、第2引数thread_safeの真偽に関わらずトランザクション内の処理をMutexで同期しますが、互換性の為、thread_safeが偽である場合にトランザクションを入ろうとすると例外nested transactionが発生するようにしてあります。


ちょっとだけ考古学してみました。Hongli Lai の元記事がこちら。

http://izumi.plan99.net/blog/index.php/2008/03/26/making-pstore-reaaaally-fast/

とにかく高速化したかったみたいですね。最後に "I’ll send a patch to
ruby-core so that this can be merged back upstream" とあるけれど、
そのメールは見つかりませんでした。matz が勝手に (または ruby-core
以外で話をして) 取り込んだんですかね。


r26673 で thread_safe が全然動いてなかったお粗末なバグが修正されて
いることから、Hongli Lai は thread_safe のテストを全くやらなかった
と思われます。なので、thread_safe のときにも nested transation 例外
が投げられるのは特に意図はしていなさそうな気がします。


PStore#initialize の rdoc を見ると、

# PStore objects are always reentrant. But if _thread_safe_ is set to true,
# then it will become thread-safe at the cost of a minor performance hit.

とあり、元の目的が超高速化なだけあって、Mutex のロックのコストを気に
しているようです。ケチな話ですね。そういう意味で、

> インスタンス変数@transactionを廃して、
> Mutexがロックされているかどうか

の変更は、少なくとも Hongli Lai の望むところではなさそうです。
少なくとも、上の rdoc は嘘になっているので修正する必要があります。


一応、Mutex#synchronize は DummyMutex より 2 倍以上遅いみたいです。
1 回あたりを考えるともともと無視できそうなコストですが、PStore のよ
うな用途だと問題になりうるんですかね。

  $ time ./ruby -e '
    class DummyMutex
      def synchronize
        yield
      end
    end
    m = DummyMutex.new
    1000000.times { m.synchronize { } }
  '

  real    0m0.219s
  user    0m0.200s
  sys     0m0.012s


  $ time ./ruby -e '
    m = Mutex.new
    1000000.times { m.synchronize { } }
  '

  real    0m0.527s
  user    0m0.492s
  sys     0m0.004s


Hongli Lai は ruby-core でちょくちょく見かける人なので、聞けば返事を
してくれるんじゃないでしょうか。この話は ruby-core で議論した方がいい
のでは。

-- 
Yusuke Endoh <mame / tsg.ne.jp>