2

多くのタプル (約 18 GB のキーと値のペア) を含む berkeley db でハッシュを構築しようとしていますが、すべてのテストで、挿入操作のパフォーマンスが時間の経過とともに大幅に低下します。パフォーマンスをテストするために、次のスクリプトを作成しました。

#include<iostream>
#include<db_cxx.h>
#include<ctime>

#define MILLION 1000000

int main () {
    long long a = 0;
    long long b = 0;

    int passes = 0;
    int i = 0;
    u_int32_t flags = DB_CREATE;

    Db* dbp = new Db(NULL,0);
    dbp->set_cachesize( 0, 1024 * 1024 * 1024, 1 );

    int ret = dbp->open(
            NULL,
            "test.db",
            NULL,
            DB_HASH,
            flags,
            0);
    time_t time1 = time(NULL);

    while ( passes < 100 ) {
        while( i < MILLION ) {

            Dbt key( &a, sizeof(long long) );
            Dbt data( &b, sizeof(long long) );

            dbp->put( NULL, &key, &data, 0);
            a++; b++; i++;  
        }

        DbEnv* dbep = dbp->get_env();
        int tmp;
        dbep->memp_trickle( 50, &tmp );

        i=0;
        passes++;
        std::cout << "Inserted one million --> pass: " << passes << " took: " << time(NULL) - time1 << "sec" << std::endl;
        time1 = time(NULL);
    }

}

おそらく、しばらくすると「put」操作に時間がかかる理由と、これを修正する方法を教えてください。

助けてくれてありがとう、アンドレアス

4

4 に答える 4

3

db_statユーティリティーによって提供される情報と、使用可能なHASH固有のチューニング機能を確認することをお勧めします。HASHデータベースの構成については、BDBリファレンスガイドのセクションを参照してください。

コモディティハードウェアでは、毎秒数万のインサートを入手できると思います。あなたは何を経験していて、あなたのパフォーマンス目標は何ですか?

よろしく、

デイブ

于 2010-06-02T02:48:51.063 に答える
3

一括挿入APIを試すことをお勧めします。これについては、次のドキュメントを参照してください: http ://www.oracle.com/technology/documentation/berkeley-db/db/api_reference/CXX/dbput.html#put_DB_MULTIPLE_KEY

また、memp_trickleの呼び出しが、速度低下の大部分の原因であると思います。キャッシュが汚れるにつれて、細流化するページを見つけるのに費用がかかります。実際、あなたは書いているだけなので、大きなキャッシュを持っていることは痛いだけです(一度データを書いたら、それを再び使用することはないので、キャッシュにぶら下がってほしくないです)。さまざまな(小さい)キャッシュサイズをテストします。

最後に、挿入のパフォーマンスが唯一の懸念事項である場合は、より大きなページサイズを使用すると役立ちます。各ページにより多くのデータを収めることができ、その結果、ディスクへの書き込みが少なくなります。

-ベン

于 2010-06-02T20:33:53.930 に答える
1

memp_trickle はほぼ確実に速度を落としています。トリクルを使用することはしばしば良いことですが、それは独自のスレッドに属しており、効果的です。BDB (より高いレベルのレプリケーション API を使用する場合を除く) はスレッドを作成しません。バックグラウンドで (スレッドに関して) 何も起こりません。トリクルは、ダーティ ページがキャッシュから強制的に削除された場合に効果的です (統計出力を見て、それが起こっているかどうかを確認してください)。

HASH の代わりに BTREE の使用を検討することもできます。ええ、私はあなたが具体的にハッシュと言ったことを知っていますが、なぜですか? パフォーマンスを最大化したいのであれば、なぜその制限を追加するのでしょうか? 参照の局所性を利用して、キャッシュのフットプリントを削減できる場合があります。たとえば、日付を前に付けるなど、ランダムな数字であるキーを生成する場合、信じているよりもはるかに多くの局所性があるか、おそらく作成できる局所性があります。そして時間。これは通常、認識された「ランダム」システムに局所性を導入します。btree を使用する場合は、システムのキーのバイト順序に注意を払う必要があります (ウィキペディアでエンディアンを調べてください)。リトル エンディアン システムを使用している場合は、バイトを交換する必要があります。BTREE を正しい順序で使用し、ローカリティを導入すると、キーと値のペアが ' したがって、最近のキーで最も多くのアクションが見られる場合は、同じページを何度もヒットする傾向があります (統計でキャッシュ ヒット率を確認してください)。したがって、必要なキャッシュが少なくなります。別の考え方として、キャッシュ量が同じ場合、ソリューションはより大きな倍数でスケーリングされます。

あなたの実際のアプリは実際に整数キーを順番に挿入しないと思います(そうであれば、幸運です)。したがって、少なくともキーのサイズ、データのサイズ、アクセス パターン、データベース内の項目数、読み取り/書き込みの組み合わせに関して、アクセス パターンを厳密にシミュレートするベンチマークを作成する必要があります。それができたら、統計を見てください。IO や競合を意味するものには細心の注意を払ってください。

ところで、私は最近http://libdb.wordpress.comでブログを開始し、 BDB のパフォーマンス チューニング (および BDB に関連するその他の問題) について説明しています。そこでいいアイデアが浮かぶかもしれません。実行するチューニングの種類によっては、レイテンシーとスループットに大きな違いが生じる可能性があります。特に、http://libdb.wordpress.com/2011/01/31/revving-up-a-benchmark-from-626-to-74000-operations-per-second/を参照してください。

于 2010-10-27T16:43:02.810 に答える
0

パフォーマンスの低下にはいくつかの理由が考えられますが、実際にはコードとは関係ありません。私は間違っているかもしれませんが、これはすべて内部データベース構造 (および使用されるデータ構造) に関するものだと思います。

データベースがRB ツリーなど、ハッシュ テーブル以外のアプローチを使用している状況を考えてみてください。そのツリーへの挿入はBig-O の意味を持ち、要素が挿入されるたびに次の挿入に必要な時間が増加します。O(logN)

残念ながら、単純なhash-tableでも同じことが起こる可能性があるため、最初のO(1)挿入操作時間はさらに悪化します。これにはいくつかの理由が考えられますが、それはすべてハッシュの衝突に関するものです。これは、間違ったハッシュ関数、間違ったデータ (現在使用されているハッシュ関数にとっては悪いことです)、または月の満ち欠けが原因で発生する可能性があります。

私があなただったら、あなたのデータベースの内部構造を掘り下げようとします。また、キーをデータベース以外のもの (例: boost::unordered_map) でテストすることも、テストとプロファイリングに役立つと思います。

cache_size編集:また、サンプルでそのようなものを変更しようとしましたか? それとも、変更できる他のパフォーマンス関連のパラメーターがいくつかあるのでしょうか?

于 2010-05-27T10:15:47.633 に答える