8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

全文検索エンジンGroongaAdvent Calendar 2013

Day 4

Rroongaとスレッドプログラミング

Last updated at Posted at 2013-12-05

コメントで重要な指摘を貰っているので、そちらも参照のこと

遅くなってしまって、済みません。

以前自分の日記に書いた内容の焼き直しですが、Groongaアドベントカレンダーの四日目です。四日目です!(エントリーの作成日時は見ないでくださいね)

複数のスレッドからRroonga(を通したGroongaデータベース)を触る時には、同時にDBを開かないように気を付けなくてはなりません(とは言え、そもそもそういう状況になるのがよくないので、見直したほうがいいです)。

例えばこんなユーティリティ関数を作って

def open
  Groonga::Database.open @db_file do |db|
    yield db
  end
end

複数のスレッドから触ると……

$stderr.sync = true
threads = []
1000.times do |i|
  $stderr.print "#{i}: start\n"
  threads << Thread.new(i) {
    $stderr.print "#{i}: open\n"
    open do |db|
      $stderr.print "#{i}: before\n"
      Groonga['Items'].add i.to_s
      $stderr.print "#{i}: after\n"
    end
  }
end

threads.each &:join

ほとんどの場合、最後まで実行されず途中で例外でストップすると思います。

これは、データベースを触る時にちゃんとロックすることで回避することができます。

  require 'monitor'
  # :
  # monitorのセットアップ
  # :
  threads = []
  1000.times do |i|
    $stderr.print "#{i}: start\n"
    threads << Thread.new(i) {
      $stderr.print "#{i}: open\n"
      synchronize do
        open do |db|
          $stderr.print "#{i}: before\n"
          Groonga['Items'].add i.to_s
          $stderr.print "#{i}: after\n"
        end
      end
    }
  end

  threads.each &:join

ということを自分の日記に書いたら、須藤さんからこんな突っ込みを頂きました。
https://twitter.com/ktou/statuses/339355624703930368

@KitaitiMakoto Groonga["..."]は普段使いの時に便利になるためのショートカットで、共通のGroonga::Contextを使うんです。普通に使う分には便利にするけど、複雑なことをしたいならそこは自分でカバーしてね!という方針です!

というわけで、Groonga::Contextを調べてみました。

ドキュメントを読んでも、使い方がはっきりとは分からないのですが、open_databaseというのが怪しいのでこれを使ってopenを書き換えてみます。

def open
  Groonga::Context.new.open_database @db_file do |db|
    yield db
  end
end

すると、おお、ちゃんと完走する。

$ ruby groonga-context.rb
  :
994: after
995: before
995: after

しかも、monitorを使った場合の40%くらい速い!

$ time ruby groonga-monitor.rb
  :
real	0m5.404s
user	0m4.512s
sys	0m0.768s
$ time ruby groonga-context.rb
  :
real	0m3.134s
user	0m2.420s
sys	0m0.620s

というわけで、(なるべくそんなことしないほうがいいと思うけど)マルチスレッド環境でRroongaを使う場合はGroonga::Contextを使うようにしましょう。

8
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?