Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用哈希访问将许多键值对快速插入berkeley db_C++_Berkeley Db - Fatal编程技术网

C++ 使用哈希访问将许多键值对快速插入berkeley db

C++ 使用哈希访问将许多键值对快速插入berkeley db,c++,berkeley-db,C++,Berkeley Db,我试图用berkeley db构建一个哈希,它将包含许多元组(大约18GB的键值对),但在我所有的测试中,插入操作的性能会随着时间的推移而急剧下降。我编写此脚本是为了测试性能: #include<iostream> #include<db_cxx.h> #include<ctime> #define MILLION 1000000 int main () { long long a = 0; long long b = 0; in

我试图用berkeley db构建一个哈希,它将包含许多元组(大约18GB的键值对),但在我所有的测试中,插入操作的性能会随着时间的推移而急剧下降。我编写此脚本是为了测试性能:

#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);
    }

}
#包括
#包括
#包括
#定义百万1000000
int main(){
长a=0;
长b=0;
int passes=0;
int i=0;
u_int32_t flags=DB_CREATE;
Db*dbp=newdb(NULL,0);
dbp->set_cachesize(0,1024*1024*1024,1);
int ret=dbp->打开(
无效的
“test.db”,
无效的
DB_散列,
旗帜,
0);
time\u t time1=时间(空);
while(通过<100次){
而(我<百万){
Dbt键(&a,sizeof(long));
Dbt数据(&b,sizeof(long));
dbp->put(NULL、键和数据,0);
a++;b++;i++;
}
DbEnv*dbep=dbp->get_env();
int tmp;
dbep->memp_涓流(50和tmp);
i=0;
通过++;

std::cout性能下降可能有几个原因,这些原因实际上与代码无关。我可能弄错了,但我认为这都是关于内部数据库结构(以及使用的数据结构)

设想一种情况,在这种情况下,数据库使用哈希表以外的方法,例如RB树。在该树中插入将需要大O意义上的
O(logN)
,并且每个插入的元素都会增加下一次插入所需的时间

不幸的是,普通哈希表也可能发生同样的情况,因此初始的
O(1)
插入操作时间会降低到更糟糕的程度。这可能有几个原因,但都与哈希冲突有关,这可能是由于错误的哈希函数、错误的数据(这对当前使用的哈希函数不好)造成的甚至是由于月亮的相位

如果我是你,我会尝试深入研究你的数据库内部结构。此外,我认为用数据库以外的东西测试你的密钥(例如
boost::unordered_map
)也会有助于你的测试和分析


编辑:同样要提到的是,您是否尝试更改示例中的
缓存大小
内容?或者可能还有其他一些与性能相关的参数可以修改?

您可能希望查看db\u stat实用程序提供的信息以及可用的哈希特定调整函数。请参阅

我希望你能在商品硬件上每秒获得10到数千次插入。你经历了什么?你的性能目标是什么

问候,


Dave

我建议您尝试批量插入API,您可以在以下文档中阅读:

此外,我猜您对memp_trickle的调用是造成大部分减速的原因。随着缓存变得更脏,查找要trickle的页面变得更昂贵。事实上,由于您只是在写,拥有大缓存只会带来伤害(一旦您写了数据,您就不会再使用它,因此您不希望它在缓存中徘徊。)我建议测试不同(较小)的缓存大小

最后,如果您唯一关心的是插入性能,那么使用更大的页面大小将有所帮助。您将能够在每个页面上容纳更多数据,从而减少磁盘写入


-Ben

memp_trickle几乎肯定会减慢速度。使用trickle通常是好的,但它属于它自己的线程才能有效。BDB(进入更高级别的复制API时除外)不会为您创建线程——幕后不会发生任何事情(线程方面).trickle将在强制从缓存中删除脏页时生效(查看统计输出以了解是否发生了这种情况)

你也可以考虑使用BTHEY代替哈希。是的,我知道你具体说的是哈希,但是为什么?如果你想最大化性能,为什么要添加这个限制?你可以利用引用的局部性来减少你的缓存占用——你相信的地方经常更多,或者你可以Cre。ate some——例如,如果生成的密钥是随机数字,则在日期和时间之前加上前缀。这通常会在感知的“随机”系统中引入局部性。如果使用btree,则需要注意系统密钥的字节顺序(在Wikipedia中查找Endianness),如果您使用的是小型Endian系统,则需要交换字节。使用具有正确顺序和引入的局部性的BTREE意味着您的键/值对将按“键生成时间”顺序存储,因此,如果您在最近的键上看到大多数操作,您将倾向于反复访问相同的页面(请在统计数据中查看缓存命中率)。因此,您将需要更少的缓存。另一种方法是,在相同的缓存量下,您的解决方案将以更大的倍数进行扩展

我希望你的实际应用程序不会按顺序插入整数键(如果是这样,你就幸运了)。因此,您应该编写一个非常模拟您的访问模式的基准测试,至少在以下方面:键的大小、数据的大小、访问模式、数据库中的项目数、读/写混合。一旦有了这些,请查看统计数据--密切关注任何暗示IO或争用的内容


顺便说一句,我最近在上开了一个博客,讨论BDB性能调优(以及与BDB相关的其他事项)。你可能会在那里得到一些好主意。根据你所做的调优类型,延迟和吞吐量可能会有很大的不同。特别是,请参见

为什么要使用Java风格?为什么不只是
Db dbp(NULL,0)
?没有特别的原因。无论如何,在这种情况下这并不重要。是的,我尝试过操纵缓存大小,但它似乎对写入的性能没有任何影响。