@ -13,6 +13,7 @@
# include "rocksdb/slice_transform.h"
# include "rocksdb/slice_transform.h"
# include "port/port.h"
# include "port/port.h"
# include "port/atomic_pointer.h"
# include "port/atomic_pointer.h"
# include "util/histogram.h"
# include "util/murmurhash.h"
# include "util/murmurhash.h"
# include "db/memtable.h"
# include "db/memtable.h"
# include "db/skiplist.h"
# include "db/skiplist.h"
@ -54,7 +55,9 @@ class HashLinkListRep : public MemTableRep {
public :
public :
HashLinkListRep ( const MemTableRep : : KeyComparator & compare , Arena * arena ,
HashLinkListRep ( const MemTableRep : : KeyComparator & compare , Arena * arena ,
const SliceTransform * transform , size_t bucket_size ,
const SliceTransform * transform , size_t bucket_size ,
size_t huge_page_tlb_size , Logger * logger ) ;
size_t huge_page_tlb_size , Logger * logger ,
int bucket_entries_logging_threshold ,
bool if_log_bucket_dist_when_flash ) ;
virtual KeyHandle Allocate ( const size_t len , char * * buf ) override ;
virtual KeyHandle Allocate ( const size_t len , char * * buf ) override ;
@ -92,6 +95,10 @@ class HashLinkListRep : public MemTableRep {
const MemTableRep : : KeyComparator & compare_ ;
const MemTableRep : : KeyComparator & compare_ ;
Logger * logger_ ;
int bucket_entries_logging_threshold_ ;
bool if_log_bucket_dist_when_flash_ ;
bool BucketContains ( Node * head , const Slice & key ) const ;
bool BucketContains ( Node * head , const Slice & key ) const ;
Slice GetPrefix ( const Slice & internal_key ) const {
Slice GetPrefix ( const Slice & internal_key ) const {
@ -308,11 +315,16 @@ class HashLinkListRep : public MemTableRep {
HashLinkListRep : : HashLinkListRep ( const MemTableRep : : KeyComparator & compare ,
HashLinkListRep : : HashLinkListRep ( const MemTableRep : : KeyComparator & compare ,
Arena * arena , const SliceTransform * transform ,
Arena * arena , const SliceTransform * transform ,
size_t bucket_size , size_t huge_page_tlb_size ,
size_t bucket_size , size_t huge_page_tlb_size ,
Logger * logger )
Logger * logger ,
int bucket_entries_logging_threshold ,
bool if_log_bucket_dist_when_flash )
: MemTableRep ( arena ) ,
: MemTableRep ( arena ) ,
bucket_size_ ( bucket_size ) ,
bucket_size_ ( bucket_size ) ,
transform_ ( transform ) ,
transform_ ( transform ) ,
compare_ ( compare ) {
compare_ ( compare ) ,
logger_ ( logger ) ,
bucket_entries_logging_threshold_ ( bucket_entries_logging_threshold ) ,
if_log_bucket_dist_when_flash_ ( if_log_bucket_dist_when_flash ) {
char * mem = arena_ - > AllocateAligned ( sizeof ( port : : AtomicPointer ) * bucket_size ,
char * mem = arena_ - > AllocateAligned ( sizeof ( port : : AtomicPointer ) * bucket_size ,
huge_page_tlb_size , logger ) ;
huge_page_tlb_size , logger ) ;
@ -416,15 +428,36 @@ MemTableRep::Iterator* HashLinkListRep::GetIterator(Arena* alloc_arena) {
// allocate a new arena of similar size to the one currently in use
// allocate a new arena of similar size to the one currently in use
Arena * new_arena = new Arena ( arena_ - > BlockSize ( ) ) ;
Arena * new_arena = new Arena ( arena_ - > BlockSize ( ) ) ;
auto list = new FullList ( compare_ , new_arena ) ;
auto list = new FullList ( compare_ , new_arena ) ;
HistogramImpl keys_per_bucket_hist ;
for ( size_t i = 0 ; i < bucket_size_ ; + + i ) {
for ( size_t i = 0 ; i < bucket_size_ ; + + i ) {
int count = 0 ;
bool num_entries_printed = false ;
auto bucket = GetBucket ( i ) ;
auto bucket = GetBucket ( i ) ;
if ( bucket ! = nullptr ) {
if ( bucket ! = nullptr ) {
Iterator itr ( this , bucket ) ;
Iterator itr ( this , bucket ) ;
for ( itr . SeekToHead ( ) ; itr . Valid ( ) ; itr . Next ( ) ) {
for ( itr . SeekToHead ( ) ; itr . Valid ( ) ; itr . Next ( ) ) {
list - > Insert ( itr . key ( ) ) ;
list - > Insert ( itr . key ( ) ) ;
if ( logger_ ! = nullptr & &
+ + count > = bucket_entries_logging_threshold_ & &
! num_entries_printed ) {
num_entries_printed = true ;
Info ( logger_ , " HashLinkedList bucket %zu has more than %d "
" entries. %dth key: %s " ,
i , count , count ,
GetLengthPrefixedSlice ( itr . key ( ) ) . ToString ( true ) . c_str ( ) ) ;
}
}
}
}
}
if ( if_log_bucket_dist_when_flash_ ) {
keys_per_bucket_hist . Add ( count ) ;
}
}
}
if ( if_log_bucket_dist_when_flash_ & & logger_ ! = nullptr ) {
Info ( logger_ , " hashLinkedList Entry distribution among buckets: %s " ,
keys_per_bucket_hist . ToString ( ) . c_str ( ) ) ;
}
if ( alloc_arena = = nullptr ) {
if ( alloc_arena = = nullptr ) {
return new FullListIterator ( list , new_arena ) ;
return new FullListIterator ( list , new_arena ) ;
} else {
} else {
@ -482,13 +515,17 @@ Node* HashLinkListRep::FindGreaterOrEqualInBucket(Node* head,
MemTableRep * HashLinkListRepFactory : : CreateMemTableRep (
MemTableRep * HashLinkListRepFactory : : CreateMemTableRep (
const MemTableRep : : KeyComparator & compare , Arena * arena ,
const MemTableRep : : KeyComparator & compare , Arena * arena ,
const SliceTransform * transform , Logger * logger ) {
const SliceTransform * transform , Logger * logger ) {
return new HashLinkListRep ( compare , arena , transform , bucket_count_ ,
return new HashLinkListRep (
huge_page_tlb_size_ , logger ) ;
compare , arena , transform , bucket_count_ , huge_page_tlb_size_ , logger ,
bucket_entries_logging_threshold_ , if_log_bucket_dist_when_flash_ ) ;
}
}
MemTableRepFactory * NewHashLinkListRepFactory ( size_t bucket_count ,
MemTableRepFactory * NewHashLinkListRepFactory (
size_t huge_page_tlb_size ) {
size_t bucket_count , size_t huge_page_tlb_size ,
return new HashLinkListRepFactory ( bucket_count , huge_page_tlb_size ) ;
int bucket_entries_logging_threshold , bool if_log_bucket_dist_when_flash ) {
return new HashLinkListRepFactory ( bucket_count , huge_page_tlb_size ,
bucket_entries_logging_threshold ,
if_log_bucket_dist_when_flash ) ;
}
}
} // namespace rocksdb
} // namespace rocksdb