Commit eb8f7390 authored by John Esmet's avatar John Esmet

FT-309 Fix a bug in heat zone, pretty-up the replay's output

parent 5aec290d
...@@ -221,6 +221,8 @@ block_allocator::choose_block_to_alloc_after(size_t size, uint64_t heat) { ...@@ -221,6 +221,8 @@ block_allocator::choose_block_to_alloc_after(size_t size, uint64_t heat) {
return block_allocator_strategy::best_fit(_blocks_array, _n_blocks, size, _alignment); return block_allocator_strategy::best_fit(_blocks_array, _n_blocks, size, _alignment);
case BA_STRATEGY_HEAT_ZONE: case BA_STRATEGY_HEAT_ZONE:
return block_allocator_strategy::heat_zone(_blocks_array, _n_blocks, size, _alignment, heat); return block_allocator_strategy::heat_zone(_blocks_array, _n_blocks, size, _alignment, heat);
case BA_STRATEGY_PADDED_FIT:
return block_allocator_strategy::padded_fit(_blocks_array, _n_blocks, size, _alignment);
default: default:
abort(); abort();
} }
...@@ -260,7 +262,8 @@ void block_allocator::alloc_block(uint64_t size, uint64_t heat, uint64_t *offset ...@@ -260,7 +262,8 @@ void block_allocator::alloc_block(uint64_t size, uint64_t heat, uint64_t *offset
// our allocation strategy chose the space after `bp' to fit the new block // our allocation strategy chose the space after `bp' to fit the new block
uint64_t answer_offset = align(bp->offset + bp->size, _alignment); uint64_t answer_offset = align(bp->offset + bp->size, _alignment);
uint64_t blocknum = bp - _blocks_array; uint64_t blocknum = bp - _blocks_array;
assert(&_blocks_array[blocknum] == bp); invariant(&_blocks_array[blocknum] == bp);
invariant(blocknum < _n_blocks);
memmove(bp + 2, bp + 1, (_n_blocks - blocknum - 1) * sizeof(*bp)); memmove(bp + 2, bp + 1, (_n_blocks - blocknum - 1) * sizeof(*bp));
bp[1].offset = answer_offset; bp[1].offset = answer_offset;
bp[1].size = size; bp[1].size = size;
......
...@@ -115,16 +115,14 @@ _first_fit(struct block_allocator::blockpair *blocks_array, ...@@ -115,16 +115,14 @@ _first_fit(struct block_allocator::blockpair *blocks_array,
return nullptr; return nullptr;
} }
for (uint64_t n_spaces_to_check = n_blocks - 1, struct block_allocator::blockpair *bp = forward ? &blocks_array[0] : &blocks_array[-1];
blocknum = forward ? 0 : n_blocks - 2; for (uint64_t n_spaces_to_check = n_blocks - 1; n_spaces_to_check > 0;
n_spaces_to_check > 0; n_spaces_to_check--, forward ? bp++ : bp--) {
n_spaces_to_check--, forward ? blocknum++ : blocknum--) { // Consider the space after bp
invariant(blocknum < n_blocks);
// Consider the space after blocknum
struct block_allocator::blockpair *bp = &blocks_array[blocknum];
uint64_t padded_alignment = max_padding != 0 ? _align(max_padding, alignment) : alignment; uint64_t padded_alignment = max_padding != 0 ? _align(max_padding, alignment) : alignment;
uint64_t possible_offset = _align(bp->offset + bp->size, padded_alignment); uint64_t possible_offset = _align(bp->offset + bp->size, padded_alignment);
if (possible_offset + size <= bp[1].offset) { if (possible_offset + size <= bp[1].offset) {
invariant((forward ? bp - blocks_array : blocks_array - bp) < (int64_t) n_blocks);
return bp; return bp;
} }
} }
...@@ -178,28 +176,29 @@ block_allocator_strategy::heat_zone(struct block_allocator::blockpair *blocks_ar ...@@ -178,28 +176,29 @@ block_allocator_strategy::heat_zone(struct block_allocator::blockpair *blocks_ar
uint64_t n_blocks, uint64_t size, uint64_t alignment, uint64_t n_blocks, uint64_t size, uint64_t alignment,
uint64_t heat) { uint64_t heat) {
if (heat > 0) { if (heat > 0) {
struct block_allocator::blockpair *bp, *boundary_bp;
const double hot_zone_threshold = 0.85; const double hot_zone_threshold = 0.85;
// Hot allocation. Find the beginning of the hot zone. // Hot allocation. Find the beginning of the hot zone.
struct block_allocator::blockpair *bp = &blocks_array[n_blocks - 1]; boundary_bp = &blocks_array[n_blocks - 1];
uint64_t highest_offset = _align(bp->offset + bp->size, alignment); uint64_t highest_offset = _align(boundary_bp->offset + boundary_bp->size, alignment);
uint64_t hot_zone_offset = static_cast<uint64_t>(hot_zone_threshold * highest_offset); uint64_t hot_zone_offset = static_cast<uint64_t>(hot_zone_threshold * highest_offset);
bp = std::lower_bound(blocks_array, blocks_array + n_blocks, hot_zone_offset); boundary_bp = std::lower_bound(blocks_array, blocks_array + n_blocks, hot_zone_offset);
uint64_t blocks_in_zone = (blocks_array + n_blocks) - bp; uint64_t blocks_in_zone = (blocks_array + n_blocks) - boundary_bp;
uint64_t blocks_outside_zone = bp - blocks_array; uint64_t blocks_outside_zone = boundary_bp - blocks_array;
invariant(blocks_in_zone + blocks_outside_zone == n_blocks); invariant(blocks_in_zone + blocks_outside_zone == n_blocks);
if (blocks_in_zone > 0) { if (blocks_in_zone > 0) {
// Find the first fit in the hot zone, going forward. // Find the first fit in the hot zone, going forward.
bp = _first_fit(bp, blocks_in_zone, size, alignment, true, 0); bp = _first_fit(boundary_bp, blocks_in_zone, size, alignment, true, 0);
if (bp != nullptr) { if (bp != nullptr) {
return bp; return bp;
} }
} }
if (blocks_outside_zone > 0) { if (blocks_outside_zone > 0) {
// Find the first fit in the cold zone, going backwards. // Find the first fit in the cold zone, going backwards.
bp = _first_fit(bp, blocks_outside_zone, size, alignment, false, 0); bp = _first_fit(boundary_bp, blocks_outside_zone, size, alignment, false, 0);
if (bp != nullptr) { if (bp != nullptr) {
return bp; return bp;
} }
......
...@@ -111,6 +111,8 @@ using std::set; ...@@ -111,6 +111,8 @@ using std::set;
using std::string; using std::string;
using std::vector; using std::vector;
static bool verbose = false;
static void ba_replay_assert(bool pred, const char *msg, const char *line, int line_num) { static void ba_replay_assert(bool pred, const char *msg, const char *line, int line_num) {
if (!pred) { if (!pred) {
fprintf(stderr, "%s, line (#%d): %s\n", msg, line_num, line); fprintf(stderr, "%s, line (#%d): %s\n", msg, line_num, line);
...@@ -259,7 +261,10 @@ static void replay_canonicalized_trace(const vector<string> &canonicalized_trace ...@@ -259,7 +261,10 @@ static void replay_canonicalized_trace(const vector<string> &canonicalized_trace
char *line = toku_strdup(it->c_str()); char *line = toku_strdup(it->c_str());
printf("playing canonical trace line #%d: %s", line_num, line); if (verbose) {
printf("playing canonical trace line #%d: %s", line_num, line);
}
char *ptr = tidy_line(line); char *ptr = tidy_line(line);
// canonical allocator id is in base 10, not 16 // canonical allocator id is in base 10, not 16
...@@ -335,30 +340,43 @@ static void print_result(uint64_t allocator_id, ...@@ -335,30 +340,43 @@ static void print_result(uint64_t allocator_id,
uint64_t total_bytes = report->data_bytes + report->unused_bytes; uint64_t total_bytes = report->data_bytes + report->unused_bytes;
uint64_t total_blocks = report->data_blocks + report->unused_blocks; uint64_t total_blocks = report->data_blocks + report->unused_blocks;
if (total_bytes < 32UL * 1024 * 1024) { if (total_bytes < 32UL * 1024 * 1024) {
printf("skipping allocator_id %" PRId64 " (total bytes < 32mb)\n", allocator_id); printf(" ...skipping allocator_id %" PRId64 " (total bytes < 32mb)\n", allocator_id);
printf("\n");
return; return;
} }
printf("\n"); printf(" allocator_id: %20" PRId64 "\n", allocator_id);
printf("allocator_id: %20" PRId64 "\n", allocator_id); printf(" strategy: %20s\n", strategy_str(strategy));
printf("strategy: %20s\n", strategy_str(strategy));
// byte statistics // byte statistics
printf("total bytes: %20" PRId64 "\n", total_bytes); printf(" total bytes: %20" PRId64 "\n", total_bytes);
printf("used bytes: %20" PRId64 " (%.3lf)\n", report->data_bytes, printf(" used bytes: %20" PRId64 " (%.3lf)\n", report->data_bytes,
static_cast<double>(report->data_bytes) / total_bytes); static_cast<double>(report->data_bytes) / total_bytes);
printf("unused bytes: %20" PRId64 " (%.3lf)\n", report->unused_bytes, printf(" unused bytes: %20" PRId64 " (%.3lf)\n", report->unused_bytes,
static_cast<double>(report->unused_bytes) / total_bytes); static_cast<double>(report->unused_bytes) / total_bytes);
// block statistics // block statistics
printf("total blocks: %20" PRId64 "\n", total_blocks); printf(" total blocks: %20" PRId64 "\n", total_blocks);
printf("used blocks: %20" PRId64 " (%.3lf)\n", report->data_blocks, printf(" used blocks: %20" PRId64 " (%.3lf)\n", report->data_blocks,
static_cast<double>(report->data_blocks) / total_blocks); static_cast<double>(report->data_blocks) / total_blocks);
printf("unused blocks: %20" PRId64 " (%.3lf)\n", report->unused_blocks, printf(" unused blocks: %20" PRId64 " (%.3lf)\n", report->unused_blocks,
static_cast<double>(report->unused_blocks) / total_blocks); static_cast<double>(report->unused_blocks) / total_blocks);
// misc // misc
printf("largest unused: %20" PRId64 "\n", report->largest_unused_block); printf(" largest unused: %20" PRId64 "\n", report->largest_unused_block);
printf("\n");
}
static void merge_fragmentation_reports(TOKU_DB_FRAGMENTATION dst,
TOKU_DB_FRAGMENTATION src) {
dst->file_size_bytes += src->file_size_bytes;
dst->data_bytes += src->data_bytes;
dst->data_blocks += src->data_blocks;
dst->checkpoint_bytes_additional += src->checkpoint_bytes_additional;
dst->checkpoint_blocks_additional += src->checkpoint_blocks_additional;
dst->unused_bytes += src->unused_bytes;
dst->unused_blocks += src->unused_blocks;
dst->largest_unused_block += src->largest_unused_block;
} }
int main(void) { int main(void) {
...@@ -371,6 +389,11 @@ int main(void) { ...@@ -371,6 +389,11 @@ int main(void) {
candidate_strategies.push_back(block_allocator::allocation_strategy::BA_STRATEGY_PADDED_FIT); candidate_strategies.push_back(block_allocator::allocation_strategy::BA_STRATEGY_PADDED_FIT);
candidate_strategies.push_back(block_allocator::allocation_strategy::BA_STRATEGY_HEAT_ZONE); candidate_strategies.push_back(block_allocator::allocation_strategy::BA_STRATEGY_HEAT_ZONE);
printf("\n");
printf("Individual reports, by allocator:\n");
printf("\n");
map<block_allocator::allocation_strategy, TOKU_DB_FRAGMENTATION_S> reports_by_strategy;
for (vector<enum block_allocator::allocation_strategy>::const_iterator it = candidate_strategies.begin(); for (vector<enum block_allocator::allocation_strategy>::const_iterator it = candidate_strategies.begin();
it != candidate_strategies.end(); it++) { it != candidate_strategies.end(); it++) {
const block_allocator::allocation_strategy strategy(*it); const block_allocator::allocation_strategy strategy(*it);
...@@ -381,16 +404,31 @@ int main(void) { ...@@ -381,16 +404,31 @@ int main(void) {
map<uint64_t, block_allocator *> allocator_map; map<uint64_t, block_allocator *> allocator_map;
replay_canonicalized_trace(canonicalized_trace, strategy, &allocator_map); replay_canonicalized_trace(canonicalized_trace, strategy, &allocator_map);
TOKU_DB_FRAGMENTATION_S aggregate_report;
memset(&aggregate_report, 0, sizeof(aggregate_report));
for (map<uint64_t, block_allocator *>::iterator al = allocator_map.begin(); for (map<uint64_t, block_allocator *>::iterator al = allocator_map.begin();
al != allocator_map.end(); al++) { al != allocator_map.end(); al++) {
block_allocator *ba = al->second; block_allocator *ba = al->second;
TOKU_DB_FRAGMENTATION_S report; TOKU_DB_FRAGMENTATION_S report;
memset(&report, 0, sizeof(report));
ba->get_statistics(&report); ba->get_statistics(&report);
ba->destroy(); ba->destroy();
print_result(al->first, strategy,&report); merge_fragmentation_reports(&aggregate_report, &report);
print_result(al->first, strategy, &report);
} }
reports_by_strategy[strategy] = aggregate_report;
}
printf("\n");
printf("Aggregate reports, by strategy:\n");
printf("\n");
for (map<block_allocator::allocation_strategy, TOKU_DB_FRAGMENTATION_S>::iterator it = reports_by_strategy.begin();
it != reports_by_strategy.end(); it++) {
TOKU_DB_FRAGMENTATION report = &it->second;
print_result(0, it->first, report);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment