Skip to content

Commit

Permalink
Fix ArenaTest.UnmappedAllocation for transparent huge pages
Browse files Browse the repository at this point in the history
Summary: ... by allocating in increments (1MiB) smaller than the
typical smallest huge page size of 2MiB.

Fixes facebook#12351

Test Plan:
```
sudo bash -c 'echo "always" > /sys/kernel/mm/transparent_hugepage/enabled'
```
And see unit test fails before this change, passes after this change
  • Loading branch information
pdillinger committed Feb 23, 2024
1 parent d1386de commit 35b450e
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 79 deletions.
196 changes: 118 additions & 78 deletions db/db_test2.cc
Expand Up @@ -6904,88 +6904,128 @@ TEST_F(DBTest2, LastLevelTemperatureUniversal) {
}

TEST_F(DBTest2, LastLevelStatistics) {
Options options = CurrentOptions();
options.bottommost_temperature = Temperature::kWarm;
options.default_temperature = Temperature::kHot;
options.level0_file_num_compaction_trigger = 2;
options.level_compaction_dynamic_level_bytes = true;
options.statistics = CreateDBStatistics();
Reopen(options);

// generate 1 sst on level 0
ASSERT_OK(Put("foo", "bar"));
ASSERT_OK(Put("bar", "bar"));
ASSERT_OK(Flush());
ASSERT_EQ("bar", Get("bar"));
for (bool write_time_default : {false, true}) {
SCOPED_TRACE("write time default? " + std::to_string(write_time_default));

ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES), 0);
ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT), 0);
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES), 0);
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT), 0);

// 2nd flush to trigger compaction
ASSERT_OK(Put("foo", "bar"));
ASSERT_OK(Put("bar", "bar"));
ASSERT_OK(Flush());
ASSERT_OK(dbfull()->TEST_WaitForCompact());
ASSERT_EQ("bar", Get("bar"));

ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(WARM_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));

auto pre_bytes =
options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES);
auto pre_count =
options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);

// 3rd flush to generate 1 sst on level 0
ASSERT_OK(Put("foo", "bar"));
ASSERT_OK(Put("bar", "bar"));
ASSERT_OK(Flush());
ASSERT_EQ("bar", Get("bar"));
Options options = CurrentOptions();
options.bottommost_temperature = Temperature::kWarm;
if (write_time_default) {
options.default_write_temperature = Temperature::kHot;
ASSERT_EQ(options.default_temperature, Temperature::kUnknown);
} else {
options.default_temperature = Temperature::kHot;
ASSERT_EQ(options.default_write_temperature, Temperature::kUnknown);
}
options.level0_file_num_compaction_trigger = 2;
options.level_compaction_dynamic_level_bytes = true;
options.statistics = CreateDBStatistics();
BlockBasedTableOptions bbto;
bbto.no_block_cache = true;
options.table_factory.reset(NewBlockBasedTableFactory(bbto));

ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
pre_bytes);
ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
pre_count);
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(WARM_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));

// Not a realistic setting to make last level kWarm and default temp kCold.
// This is just for testing default temp can be reset on reopen while the
// last level temp is consistent across DB reopen because those file's temp
// are persisted in manifest.
options.default_temperature = Temperature::kCold;
ASSERT_OK(options.statistics->Reset());
Reopen(options);
ASSERT_EQ("bar", Get("bar"));
Reopen(options);

ASSERT_EQ(0, options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
// generate 1 sst on level 0
ASSERT_OK(Put("foo1", "bar"));
ASSERT_OK(Put("bar", "bar"));
ASSERT_OK(Flush());
ASSERT_EQ("bar", Get("bar"));

ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES), 0);
ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT), 0);
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES), 0);
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT), 0);

// 2nd flush to trigger compaction
ASSERT_OK(Put("foo2", "bar"));
ASSERT_OK(Put("bar", "bar"));
ASSERT_OK(Flush());
ASSERT_OK(dbfull()->TEST_WaitForCompact());
ASSERT_EQ("bar", Get("bar"));

ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(WARM_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));

auto pre_bytes =
options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES);
auto pre_count =
options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);

// 3rd flush to generate 1 sst on level 0
ASSERT_OK(Put("foo3", "bar"));
ASSERT_OK(Put("bar", "bar"));
ASSERT_OK(Flush());
ASSERT_EQ("bar", Get("foo1"));
ASSERT_EQ("bar", Get("foo2"));
ASSERT_EQ("bar", Get("foo3"));
ASSERT_EQ("bar", Get("bar"));

ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
pre_bytes);
ASSERT_GT(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
pre_count);
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(WARM_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));
// Control
ASSERT_NE(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT));

// Not a realistic setting to make last level kWarm and default temp kCold.
// This is just for testing default temp can be reset on reopen while the
// last level temp is consistent across DB reopen because those file's temp
// are persisted in manifest.
options.default_temperature = Temperature::kCold;
ASSERT_OK(options.statistics->Reset());
Reopen(options);
ASSERT_EQ("bar", Get("foo1"));
ASSERT_EQ("bar", Get("foo2"));
ASSERT_EQ("bar", Get("foo3"));
ASSERT_EQ("bar", Get("bar"));

if (write_time_default) {
// Unchanged
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(HOT_FILE_READ_COUNT));

ASSERT_LT(0, options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_EQ(0, options.statistics->getTickerCount(COLD_FILE_READ_BYTES));
} else {
// Changed (in how we map kUnknown)
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(COLD_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(COLD_FILE_READ_COUNT));

ASSERT_EQ(0, options.statistics->getTickerCount(HOT_FILE_READ_BYTES));
ASSERT_LT(0, options.statistics->getTickerCount(COLD_FILE_READ_BYTES));
}

ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(COLD_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(COLD_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(WARM_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_BYTES),
options.statistics->getTickerCount(WARM_FILE_READ_BYTES));
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));
// Control
ASSERT_NE(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT));
}
}

TEST_F(DBTest2, CheckpointFileTemperature) {
Expand Down
10 changes: 9 additions & 1 deletion include/rocksdb/advanced_options.h
Expand Up @@ -818,12 +818,20 @@ struct AdvancedColumnFamilyOptions {
Temperature bottommost_temperature = Temperature::kUnknown;
Temperature last_level_temperature = Temperature::kUnknown;

// EXPERIMENTAL
// When no other option such as last_level_temperature determines the
// temperature of a new SST file, it will be written with this temperature,
// which can vary by ColumnFamily.
//
// Dynamically changeable through the SetOptions() API
Temperature default_write_temperature = Temperature::kUnknown;

// EXPERIMENTAL
// When this field is set, all SST files without an explicitly set temperature
// will be treated as if they have this temperature for file reading
// accounting purpose, such as io statistics, io perf context.
//
// Not dynamically changeable, change it requires db restart.
// Not dynamically changeable; change requires DB restart.
Temperature default_temperature = Temperature::kUnknown;

// EXPERIMENTAL
Expand Down
4 changes: 4 additions & 0 deletions options/cf_options.cc
Expand Up @@ -449,6 +449,10 @@ static std::unordered_map<std::string, OptionTypeInfo>
{offsetof(struct MutableCFOptions, last_level_temperature),
OptionType::kTemperature, OptionVerificationType::kNormal,
OptionTypeFlags::kMutable}},
{"default_write_temperature",
{offsetof(struct MutableCFOptions, default_write_temperature),
OptionType::kTemperature, OptionVerificationType::kNormal,
OptionTypeFlags::kMutable}},
{"enable_blob_files",
{offsetof(struct MutableCFOptions, enable_blob_files),
OptionType::kBoolean, OptionVerificationType::kNormal,
Expand Down
3 changes: 3 additions & 0 deletions options/cf_options.h
Expand Up @@ -167,6 +167,7 @@ struct MutableCFOptions {
Temperature::kUnknown
? options.bottommost_temperature
: options.last_level_temperature),
default_write_temperature(options.default_write_temperature),
memtable_protection_bytes_per_key(
options.memtable_protection_bytes_per_key),
block_protection_bytes_per_key(options.block_protection_bytes_per_key),
Expand Down Expand Up @@ -221,6 +222,7 @@ struct MutableCFOptions {
compression(Snappy_Supported() ? kSnappyCompression : kNoCompression),
bottommost_compression(kDisableCompressionOption),
last_level_temperature(Temperature::kUnknown),
default_write_temperature(Temperature::kUnknown),
memtable_protection_bytes_per_key(0),
block_protection_bytes_per_key(0),
sample_for_compression(0),
Expand Down Expand Up @@ -312,6 +314,7 @@ struct MutableCFOptions {
CompressionOptions compression_opts;
CompressionOptions bottommost_compression_opts;
Temperature last_level_temperature;
Temperature default_write_temperature;
uint32_t memtable_protection_bytes_per_key;
uint8_t block_protection_bytes_per_key;

Expand Down
3 changes: 3 additions & 0 deletions options/options.cc
Expand Up @@ -93,6 +93,9 @@ AdvancedColumnFamilyOptions::AdvancedColumnFamilyOptions(const Options& options)
ttl(options.ttl),
periodic_compaction_seconds(options.periodic_compaction_seconds),
sample_for_compression(options.sample_for_compression),
bottommost_temperature(options.bottommost_temperature),
last_level_temperature(options.last_level_temperature),
default_write_temperature(options.default_write_temperature),
default_temperature(options.default_temperature),
preclude_last_level_data_seconds(
options.preclude_last_level_data_seconds),
Expand Down
1 change: 1 addition & 0 deletions options/options_helper.cc
Expand Up @@ -273,6 +273,7 @@ void UpdateColumnFamilyOptions(const MutableCFOptions& moptions,
cf_opts->compression_per_level = moptions.compression_per_level;
cf_opts->last_level_temperature = moptions.last_level_temperature;
cf_opts->bottommost_temperature = moptions.last_level_temperature;
cf_opts->default_write_temperature = moptions.default_write_temperature;
cf_opts->memtable_max_range_deletions = moptions.memtable_max_range_deletions;
}

Expand Down
1 change: 1 addition & 0 deletions options/options_settable_test.cc
Expand Up @@ -554,6 +554,7 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) {
"prepopulate_blob_cache=kDisable;"
"bottommost_temperature=kWarm;"
"last_level_temperature=kWarm;"
"default_write_temperature=kCold;"
"default_temperature=kHot;"
"preclude_last_level_data_seconds=86400;"
"preserve_internal_time_seconds=86400;"
Expand Down
4 changes: 4 additions & 0 deletions options/options_test.cc
Expand Up @@ -131,6 +131,7 @@ TEST_F(OptionsTest, GetOptionsFromMapTest) {
{"blob_file_starting_level", "1"},
{"prepopulate_blob_cache", "kDisable"},
{"last_level_temperature", "kWarm"},
{"default_write_temperature", "kCold"},
{"default_temperature", "kHot"},
{"persist_user_defined_timestamps", "true"},
{"memtable_max_range_deletions", "0"},
Expand Down Expand Up @@ -288,6 +289,7 @@ TEST_F(OptionsTest, GetOptionsFromMapTest) {
ASSERT_EQ(new_cf_opt.prepopulate_blob_cache, PrepopulateBlobCache::kDisable);
ASSERT_EQ(new_cf_opt.last_level_temperature, Temperature::kWarm);
ASSERT_EQ(new_cf_opt.bottommost_temperature, Temperature::kWarm);
ASSERT_EQ(new_cf_opt.default_write_temperature, Temperature::kCold);
ASSERT_EQ(new_cf_opt.default_temperature, Temperature::kHot);
ASSERT_EQ(new_cf_opt.persist_user_defined_timestamps, true);
ASSERT_EQ(new_cf_opt.memtable_max_range_deletions, 0);
Expand Down Expand Up @@ -2351,6 +2353,7 @@ TEST_F(OptionsOldApiTest, GetOptionsFromMapTest) {
{"blob_file_starting_level", "1"},
{"prepopulate_blob_cache", "kDisable"},
{"last_level_temperature", "kWarm"},
{"default_write_temperature", "kCold"},
{"default_temperature", "kHot"},
{"persist_user_defined_timestamps", "true"},
{"memtable_max_range_deletions", "0"},
Expand Down Expand Up @@ -2504,6 +2507,7 @@ TEST_F(OptionsOldApiTest, GetOptionsFromMapTest) {
ASSERT_EQ(new_cf_opt.prepopulate_blob_cache, PrepopulateBlobCache::kDisable);
ASSERT_EQ(new_cf_opt.last_level_temperature, Temperature::kWarm);
ASSERT_EQ(new_cf_opt.bottommost_temperature, Temperature::kWarm);
ASSERT_EQ(new_cf_opt.default_write_temperature, Temperature::kCold);
ASSERT_EQ(new_cf_opt.default_temperature, Temperature::kHot);
ASSERT_EQ(new_cf_opt.persist_user_defined_timestamps, true);
ASSERT_EQ(new_cf_opt.memtable_max_range_deletions, 0);
Expand Down

0 comments on commit 35b450e

Please sign in to comment.