groonga / grnxx

groonga++
Other
7 stars 0 forks source link

Goroonga と Grnxx Go wrapper のロード時間を比べる #152

Closed s-yata closed 9 years ago

s-yata commented 9 years ago

概要

Goroonga を使って Groonga にデータを投入するのと, Go wrapper を使って Grnxx にデータを投入するのにかかる時間を比較します.

s-yata commented 9 years ago

データ

実験には, Wikipedia を Pandoc でテキスト化したものを Body として,整数を二つ追加した上で Json 化したものを使います. LengthBody の長さ, Random は擬似乱数により生成された値 [0, 100) を入れてあります.

基本的に, Wikipedia の段落が一つのレコードに対応しています.

{"Body":"地理学(ちりがく、、、)は...と称される[1]。","Length":471,"Random":81}
{"Body":"元来は農耕や戦争、...求められるようになった。","Length":324,"Random":87}
{"Body":"地理学の歴史","Length":18,"Random":47}
{"Body":"...「近代地理学の父」...","Length":96,"Random":59}
{"Body":"地理学誕生の地は、...重要性を説いた。","Length":925,"Random":81}
s-yata commented 9 years ago

実行環境

CPU は Core i7 4558U 2.8GHz (up to 3.3GHz) です. VMWare 上の Ubuntu 14.04 にて実行します.

Groonga への入力方法

以下のようにします.

count := 0
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    // Store data into Groonga DB.
    values := scanner.Text()
    values = strings.Replace(values, "'", "\\'", -1)
    command := "load --table Table --values '[" + values + "]'"
    if err := ctx.Send(command); err != nil {
        log.Fatalln("goroonga error:", err)
    }
    _, err := ctx.Receive()
    if err != nil {
        log.Fatalln("goroonga error:", err)
    }
    count++
}

Grnxx への入力方法

以下のようにします.

count := 0
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    // Store data into Grnxx DB.
    var row Row
    if err := json.Unmarshal(scanner.Bytes(), &row); err != nil {
        log.Fatalln("json error:", err)
    }
    rowID, err := table.InsertRow(nil)
    if err != nil {
        log.Fatalln("grnxx error:", err)
    }
    if err := bodyColumn.Set(rowID, grnxx.Text(row.Body)); err != nil {
        log.Fatalln("grnxx error:", err)
    }
    if err := lengthColumn.Set(rowID, grnxx.Int(row.Length)); err != nil {
        log.Fatalln("grnxx error:", err)
    }
    if err := randomColumn.Set(rowID, grnxx.Int(row.Random)); err != nil {
        log.Fatalln("grnxx error:", err)
    }
    count++
}
s-yata commented 9 years ago

結果

プログラムにバグがあったので,以下の結果は無効です.

time にて計測した実行結果を以下に示します. Groonga only は Groonga のみへの入力をおこなった結果, Parse only は Json のパースのみをおこなった結果(参考程度), Grnxx only は Grnxx への入力のみをおこなった結果, Groonga + Grnxx は両方への入力をおこなった結果です.

Groonga only Parse only Grnxx only Groonga + Grnxx
real 25.995s 4.184s 4.803s 34.723s
user 18.913s 4.088s 4.816s 26.794s
sys 6.739s 0.174s 0.193s 7.747s

Groonga, Grnxx ともに索引なしでの結果です. Groonga 側に全文検索を担当させるのであれば,転置索引の構築が加わるため, Grnxx への入力にかかる時間は影響が小さくなるものと予想されます.

s-yata commented 9 years ago

調査項目

現状の結果でも,想定している用途からすると特に問題なさそうですが,ほかに何か調べておくべきことはないか検討してみました.

取り急ぎは思い付きませんが,何か思い付いたときか,ほかのテストに関連して調査できるときなどにおこないます.

s-yata commented 9 years ago

結果(修正版)

Groonga only は Groonga のみへの入力をおこなった結果, Grnxx only は Grnxx への入力のみをおこなった結果, Groonga + Grnxx は両方への入力をおこなった結果です.

Groonga only Grnxx only Groonga + Grnxx
real 12.931s 6.005s 21.201s
user 12.634s 6.005s 20.738s
sys 0.278s 0.219s 0.419s

Groonga, Grnxx ともに索引なしでの結果です. 修正前の結果と比べて差はかなり縮まっていますが, Grnxx の方が速いようです.

s-yata commented 9 years ago

つづき

s-yata commented 9 years ago

今後の方針

一行ずつ入れるのであれば,形式による違いはほとんどなさそうに思えます. 念のために試しますが,複数行をまとめて入力しないと効果はあまり期待できません.

ドキュメントを見る限り,もっとも速そうなのは, --columns でカラムを指定し,値を配列で渡すというものです.

複数行に分ける形式(標準入力形式)については,個別に Send(), Receive() が必要らしいので,微妙な気がします. ただし,エスケープは省略できるので,二行目にデータを連結して渡すのはアリかもしれません.

s-yata commented 9 years ago

Goroonga で複数行をまとめて入力するケースについては, #155 で調査します.

s-yata commented 9 years ago

複数行入力について

155 の結果を見ると,一度の load で複数行をまとめて入力すれば,ロード時間(変換込み)を 1/3 程度に短縮できるようです.

そのため,複数行をまとめて入力できる状況であれば, Goroonga の方が Grnxx より速くなる可能性があります.

とはいえ, Grnxx のロードで時間がかかっているのは JSON から Grnxx 形式に変換するところなので,入力のフォーマット次第なところがあります.

s-yata commented 9 years ago

Goroonga と Groonga の比較

同じクエリを Goroonga と Groonga コマンドで試してみたところ,同じくらいの時間で終了しました. Goroonga の方が少し不利かと思っていたのですが, Groonga コマンドは各クエリの実行時間を表示するのが影響しているかもしれません. とはいえ,深追いするほどのことではないと思います.