@ -29,6 +29,7 @@
# include "rocksdb/memtablerep.h"
# include "rocksdb/memtablerep.h"
# include "table/block.h"
# include "table/block.h"
# include "table/meta_blocks.h"
# include "table/meta_blocks.h"
# include "table/block_based_table_reader.h"
# include "table/block_based_table_builder.h"
# include "table/block_based_table_builder.h"
# include "table/block_based_table_factory.h"
# include "table/block_based_table_factory.h"
# include "table/block_based_table_reader.h"
# include "table/block_based_table_reader.h"
@ -960,6 +961,7 @@ class BlockBasedTableTest : public TableTest {};
class PlainTableTest : public TableTest { } ;
class PlainTableTest : public TableTest { } ;
class TablePropertyTest { } ;
class TablePropertyTest { } ;
/*
// This test serves as the living tutorial for the prefix scan of user collected
// This test serves as the living tutorial for the prefix scan of user collected
// properties.
// properties.
TEST ( TablePropertyTest , PrefixScanTest ) {
TEST ( TablePropertyTest , PrefixScanTest ) {
@ -1121,19 +1123,37 @@ TEST(BlockBasedTableTest, NumBlockStat) {
ASSERT_EQ ( kvmap . size ( ) ,
ASSERT_EQ ( kvmap . size ( ) ,
c . table_reader ( ) - > GetTableProperties ( ) - > num_data_blocks ) ;
c . table_reader ( ) - > GetTableProperties ( ) - > num_data_blocks ) ;
}
}
*/
class BlockCacheProperties {
// A simple tool that takes the snapshot of block cache statistics.
class BlockCachePropertiesSnapshot {
public :
public :
explicit BlockCacheProperties ( Statistics * statistics ) {
explicit BlockCachePropertiesSnapshot ( Statistics * statistics ) {
block_cache_miss = statistics - > getTickerCount ( BLOCK_CACHE_MISS ) ;
block_cache_miss = statistics - > getTickerCount ( BLOCK_CACHE_MISS ) ;
block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_HIT ) ;
block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_HIT ) ;
index_block_cache_miss = statistics - > getTickerCount ( BLOCK_CACHE_INDEX_MISS ) ;
index_block_cache_miss = statistics - > getTickerCount ( BLOCK_CACHE_INDEX_MISS ) ;
index_block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_INDEX_HIT ) ;
index_block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_INDEX_HIT ) ;
data_block_cache_miss = statistics - > getTickerCount ( BLOCK_CACHE_DATA_MISS ) ;
data_block_cache_miss = statistics - > getTickerCount ( BLOCK_CACHE_DATA_MISS ) ;
data_block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_DATA_HIT ) ;
data_block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_DATA_HIT ) ;
filter_block_cache_miss =
statistics - > getTickerCount ( BLOCK_CACHE_FILTER_MISS ) ;
filter_block_cache_hit = statistics - > getTickerCount ( BLOCK_CACHE_FILTER_HIT ) ;
}
void AssertIndexBlockStat ( int64_t index_block_cache_miss ,
int64_t index_block_cache_hit ) {
ASSERT_EQ ( index_block_cache_miss , this - > index_block_cache_miss ) ;
ASSERT_EQ ( index_block_cache_hit , this - > index_block_cache_hit ) ;
}
void AssertFilterBlockStat ( int64_t filter_block_cache_miss ,
int64_t filter_block_cache_hit ) {
ASSERT_EQ ( filter_block_cache_miss , this - > filter_block_cache_miss ) ;
ASSERT_EQ ( filter_block_cache_hit , this - > filter_block_cache_hit ) ;
}
}
// Check if the fetched props matches the expected ones.
// Check if the fetched props matches the expected ones.
// TODO(kailiu) Use this only when you disabled filter policy!
void AssertEqual ( int64_t index_block_cache_miss ,
void AssertEqual ( int64_t index_block_cache_miss ,
int64_t index_block_cache_hit , int64_t data_block_cache_miss ,
int64_t index_block_cache_hit , int64_t data_block_cache_miss ,
int64_t data_block_cache_hit ) const {
int64_t data_block_cache_hit ) const {
@ -1154,9 +1174,55 @@ class BlockCacheProperties {
int64_t index_block_cache_hit = 0 ;
int64_t index_block_cache_hit = 0 ;
int64_t data_block_cache_miss = 0 ;
int64_t data_block_cache_miss = 0 ;
int64_t data_block_cache_hit = 0 ;
int64_t data_block_cache_hit = 0 ;
int64_t filter_block_cache_miss = 0 ;
int64_t filter_block_cache_hit = 0 ;
} ;
} ;
TEST ( BlockBasedTableTest , BlockCacheTest ) {
// Make sure, by default, index/filter blocks were pre-loaded (meaning we won't
// use block cache to store them).
TEST ( BlockBasedTableTest , BlockCacheDisabledTest ) {
Options options ;
options . create_if_missing = true ;
options . statistics = CreateDBStatistics ( ) ;
options . block_cache = NewLRUCache ( 1024 ) ;
std : : unique_ptr < const FilterPolicy > filter_policy ( NewBloomFilterPolicy ( 10 ) ) ;
options . filter_policy = filter_policy . get ( ) ;
BlockBasedTableOptions table_options ;
// Intentionally commented out: table_options.cache_index_and_filter_blocks =
// true;
options . table_factory . reset ( new BlockBasedTableFactory ( table_options ) ) ;
std : : vector < std : : string > keys ;
KVMap kvmap ;
TableConstructor c ( BytewiseComparator ( ) ) ;
c . Add ( " key " , " value " ) ;
c . Finish ( options , GetPlainInternalComparator ( options . comparator ) , & keys ,
& kvmap ) ;
// preloading filter/index blocks is enabled.
auto reader = dynamic_cast < BlockBasedTable * > ( c . table_reader ( ) ) ;
ASSERT_TRUE ( reader - > TEST_filter_block_preloaded ( ) ) ;
ASSERT_TRUE ( reader - > TEST_index_block_preloaded ( ) ) ;
{
// nothing happens in the beginning
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertIndexBlockStat ( 0 , 0 ) ;
props . AssertFilterBlockStat ( 0 , 0 ) ;
}
{
// a hack that just to trigger BlockBasedTable::GetFilter.
reader - > Get ( ReadOptions ( ) , " non-exist-key " , nullptr , nullptr , nullptr ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertIndexBlockStat ( 0 , 0 ) ;
props . AssertFilterBlockStat ( 0 , 0 ) ;
}
}
// Due to the difficulities of the intersaction between statistics, this test
// only tests the case when "index block is put to block cache"
TEST ( BlockBasedTableTest , FilterBlockInBlockCache ) {
// -- Table construction
// -- Table construction
Options options ;
Options options ;
options . create_if_missing = true ;
options . create_if_missing = true ;
@ -1174,6 +1240,10 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
c . Add ( " key " , " value " ) ;
c . Add ( " key " , " value " ) ;
c . Finish ( options , GetPlainInternalComparator ( options . comparator ) , & keys ,
c . Finish ( options , GetPlainInternalComparator ( options . comparator ) , & keys ,
& kvmap ) ;
& kvmap ) ;
// preloading filter/index blocks is prohibited.
auto reader = dynamic_cast < BlockBasedTable * > ( c . table_reader ( ) ) ;
ASSERT_TRUE ( ! reader - > TEST_filter_block_preloaded ( ) ) ;
ASSERT_TRUE ( ! reader - > TEST_index_block_preloaded ( ) ) ;
// -- PART 1: Open with regular block cache.
// -- PART 1: Open with regular block cache.
// Since block_cache is disabled, no cache activities will be involved.
// Since block_cache is disabled, no cache activities will be involved.
@ -1181,7 +1251,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
// At first, no block will be accessed.
// At first, no block will be accessed.
{
{
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
// index will be added to block cache.
// index will be added to block cache.
props . AssertEqual ( 1 , // index block miss
props . AssertEqual ( 1 , // index block miss
0 , 0 , 0 ) ;
0 , 0 , 0 ) ;
@ -1190,7 +1260,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
// Only index block will be accessed
// Only index block will be accessed
{
{
iter . reset ( c . NewIterator ( ) ) ;
iter . reset ( c . NewIterator ( ) ) ;
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
// NOTE: to help better highlight the "detla" of each ticker, I use
// NOTE: to help better highlight the "detla" of each ticker, I use
// <last_value> + <added_value> to indicate the increment of changed
// <last_value> + <added_value> to indicate the increment of changed
// value; other numbers remain the same.
// value; other numbers remain the same.
@ -1201,7 +1271,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
// Only data block will be accessed
// Only data block will be accessed
{
{
iter - > SeekToFirst ( ) ;
iter - > SeekToFirst ( ) ;
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertEqual ( 1 , 1 , 0 + 1 , // data block miss
props . AssertEqual ( 1 , 1 , 0 + 1 , // data block miss
0 ) ;
0 ) ;
}
}
@ -1210,7 +1280,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
{
{
iter . reset ( c . NewIterator ( ) ) ;
iter . reset ( c . NewIterator ( ) ) ;
iter - > SeekToFirst ( ) ;
iter - > SeekToFirst ( ) ;
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertEqual ( 1 , 1 + 1 , /* index block hit */
props . AssertEqual ( 1 , 1 + 1 , /* index block hit */
1 , 0 + 1 /* data block hit */ ) ;
1 , 0 + 1 /* data block hit */ ) ;
}
}
@ -1226,7 +1296,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
iter . reset ( c . NewIterator ( ) ) ;
iter . reset ( c . NewIterator ( ) ) ;
iter - > SeekToFirst ( ) ;
iter - > SeekToFirst ( ) ;
ASSERT_EQ ( " key " , iter - > key ( ) . ToString ( ) ) ;
ASSERT_EQ ( " key " , iter - > key ( ) . ToString ( ) ) ;
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
// Nothing is affected at all
// Nothing is affected at all
props . AssertEqual ( 0 , 0 , 0 , 0 ) ;
props . AssertEqual ( 0 , 0 , 0 , 0 ) ;
}
}
@ -1237,7 +1307,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
options . block_cache = NewLRUCache ( 1 ) ;
options . block_cache = NewLRUCache ( 1 ) ;
c . Reopen ( options ) ;
c . Reopen ( options ) ;
{
{
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertEqual ( 1 , // index block miss
props . AssertEqual ( 1 , // index block miss
0 , 0 , 0 ) ;
0 , 0 , 0 ) ;
}
}
@ -1248,7 +1318,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
// It first cache index block then data block. But since the cache size
// It first cache index block then data block. But since the cache size
// is only 1, index block will be purged after data block is inserted.
// is only 1, index block will be purged after data block is inserted.
iter . reset ( c . NewIterator ( ) ) ;
iter . reset ( c . NewIterator ( ) ) ;
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertEqual ( 1 + 1 , // index block miss
props . AssertEqual ( 1 + 1 , // index block miss
0 , 0 , // data block miss
0 , 0 , // data block miss
0 ) ;
0 ) ;
@ -1258,7 +1328,7 @@ TEST(BlockBasedTableTest, BlockCacheTest) {
// SeekToFirst() accesses data block. With similar reason, we expect data
// SeekToFirst() accesses data block. With similar reason, we expect data
// block's cache miss.
// block's cache miss.
iter - > SeekToFirst ( ) ;
iter - > SeekToFirst ( ) ;
BlockCacheProperties props ( options . statistics . get ( ) ) ;
BlockCachePropertiesSnapshot props ( options . statistics . get ( ) ) ;
props . AssertEqual ( 2 , 0 , 0 + 1 , // data block miss
props . AssertEqual ( 2 , 0 , 0 + 1 , // data block miss
0 ) ;
0 ) ;
}
}