mazinlabsのブログ

RubyとかCloudとかその辺の記事を書いたり書かなかったり

YCSBを改造してみた

YCSB*1でMongoDBを触っている際にスレッド数を増やすとよくinsertに失敗*2してYCSBが止まる事がしばしば。。。
update, read, scanに関しては止まらないのになぜかinsertだけ止まるのでソースコードを覗いてみた。

  • src/com/yahoo/ycsb/Client.java
                while (((_opcount == 0) || (_opsdone < _opcount)) && !_workload.isStopRequested())
                {   

                    if (!_workload.doInsert(_db,_workloadstate))
                    {   
                        break;
                    } 
  • src/com/yahoo/ycsb/workloads/CoreWorkload.java
    /** 
     * Do one insert operation. Because it will be called concurrently from multiple client threads, this 
     * function must be thread safe. However, avoid synchronized, or the threads will block waiting for each 
     * other, and it will be difficult to reach the target throughput. Ideally, this function would have no side
     * effects other than DB operations.
     */
    public boolean doInsert(DB db, Object threadstate)
    {   
        int keynum=keysequence.nextInt();
        String dbkey = buildKeyName(keynum);
        HashMap<String, ByteIterator> values = buildValues();
        if (db.insert(table,dbkey,values) == 0)
            return true;
        else
            return false;
    } 

どうやらinsertの実行結果が成功(0)以外はすべてfalseと扱われ、insertが失敗した時点でOperationが残っていても強制的に処理が終わってしまうらしい。


そんなわけで"src/com/yahoo/ycsb/workloads/CoreWorkload.java"のifの部分を弄る。

  • src/com/yahoo/ycsb/workloads/CoreWorkload.java
    /** 
     * Do one insert operation. Because it will be called concurrently from multiple client threads, this 
     * function must be thread safe. However, avoid synchronized, or the threads will block waiting for each 
     * other, and it will be difficult to reach the target throughput. Ideally, this function would have no side
     * effects other than DB operations.
     */
    public boolean doInsert(DB db, Object threadstate)
    {   
        int keynum=keysequence.nextInt();
        String dbkey = buildKeyName(keynum);
        HashMap<String, ByteIterator> values = buildValues();
        db.insert(table,dbkey,values);

        return true;
    } 

とりあえずこれでinsertに失敗しても止まらなくなった。
が、それでいいのかと言われるとどうなんだろ・・・


が、MongoDBのinsertはなんであんなに失敗するんだろ。。。

*1:Yahoo!が提供しているNoSQL用のベンチマークツール

*2:序盤の失敗はスレッドのいくつかが重複するKeyに対してのinsertを行った結果duplicateのErrorが出てる。中盤は不明。