first version of fast lruk

This commit is contained in:
2024-04-25 10:10:49 +00:00
parent 0c0d4684bb
commit 36a615aaad
10 changed files with 498 additions and 3 deletions

103
bpt/src/disk_manager.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "bpt/disk_manager.h"
#include <cstring>
#include <exception>
#include <stdexcept>
DiskManager::DiskManager(const std::string &file_path_)
: file_path(file_path_),
first_empty_page_id(0),
current_total_page_count(0),
current_none_empty_page_count(0),
raw_data_memory(nullptr),
fp(nullptr) {
fp = fopen(file_path.c_str(), "r+b");
if (fp == nullptr) {
// File doesn't exist, create a new one
fp = fopen(file_path.c_str(), "w+b");
// Initialize internal page
first_empty_page_id = 0;
current_total_page_count = 0;
current_none_empty_page_count = 0;
raw_data_memory = new char[kPageSize - meta_data_size];
memset(raw_data_memory, 0, kPageSize - meta_data_size);
FlushInternalPage();
is_new = true;
} else {
// File exists, read metadata from internal page
fseek(fp, 0, SEEK_SET);
fread(&first_empty_page_id, sizeof(page_id_t), 1, fp);
fread(&current_total_page_count, sizeof(size_t), 1, fp);
fread(&current_none_empty_page_count, sizeof(size_t), 1, fp);
raw_data_memory = new char[kPageSize - meta_data_size];
fread(raw_data_memory, kPageSize - meta_data_size, 1, fp);
is_new = false;
}
page_buf = new char[kPageSize];
}
DiskManager::~DiskManager() {
Close();
delete[] raw_data_memory;
delete[] page_buf;
}
char *DiskManager::RawDataMemory() { return raw_data_memory; }
size_t DiskManager::RawDatMemorySize() { return kPageSize - meta_data_size; }
void DiskManager::FlushInternalPage() {
fseek(fp, 0, SEEK_SET);
fwrite(&first_empty_page_id, sizeof(page_id_t), 1, fp);
fwrite(&current_total_page_count, sizeof(size_t), 1, fp);
fwrite(&current_none_empty_page_count, sizeof(size_t), 1, fp);
fwrite(raw_data_memory, kPageSize - meta_data_size, 1, fp);
fflush(fp);
}
void DiskManager::Close() {
if (fp != nullptr) {
FlushInternalPage();
fclose(fp);
fp = nullptr;
}
}
void DiskManager::ReadPage(page_id_t page_id, char *page_data_ptr) {
fseek(fp, page_id * kPageSize, SEEK_SET);
fread(page_data_ptr, kPageSize, 1, fp);
}
void DiskManager::WritePage(page_id_t page_id, const char *page_data_ptr) {
fseek(fp, page_id * kPageSize, SEEK_SET);
fwrite(page_data_ptr, kPageSize, 1, fp);
}
bool DiskManager::CurrentFileIsNew() { return is_new; }
page_id_t DiskManager::AllocNewEmptyPageId() {
page_id_t new_page_id;
if (first_empty_page_id == 0) {
// No empty page available, append a new page
current_total_page_count++;
new_page_id = current_total_page_count;
fseek(fp, 0, SEEK_END);
fwrite(page_buf, kPageSize, 1, fp);
} else {
new_page_id = first_empty_page_id;
ReadPage(new_page_id, page_buf);
memcpy(&first_empty_page_id, page_buf, sizeof(page_id_t));
}
current_none_empty_page_count++;
return new_page_id;
}
void DiskManager::DeallocatePage(page_id_t page_id) {
// Add the deallocated page to the head of the empty list
memcpy(page_buf, &first_empty_page_id, sizeof(page_id_t));
WritePage(page_id, page_buf);
first_empty_page_id = page_id;
current_none_empty_page_count--;
}
size_t DiskManager::CurrentTotalPageCount() { return current_total_page_count; }
size_t DiskManager::CurrentNoneEmptyPageCount() { return current_none_empty_page_count; }

157
bpt/src/replacer.cpp Normal file
View File

@ -0,0 +1,157 @@
#include "bpt/replacer.h"
#include <cstddef>
LRUKReplacer::LRUKReplacer(size_t max_frame_count, size_t k_value)
: max_frame_count(max_frame_count), k_value(k_value) {
hash_for_record = new LRUKRecord[max_frame_count];
for (size_t i = 0; i < max_frame_count; i++) {
hash_for_record[i].active = false;
}
LRU_chain_head_guard = new LRUChainNodeType(-1, nullptr, nullptr);
LRU_chain_tail_guard = new LRUChainNodeType(-1, nullptr, nullptr);
LRU_chain_head_guard->next = LRU_chain_tail_guard;
LRU_chain_tail_guard->prev = LRU_chain_head_guard;
LRUK_chain_head_guard = new MainChainNodeType(-1, 0, nullptr, nullptr, nullptr);
LRUK_chain_tail_guard = new MainChainNodeType(-1, 0, nullptr, nullptr, nullptr);
LRUK_chain_head_guard->next = LRUK_chain_tail_guard;
LRUK_chain_tail_guard->prev = LRUK_chain_head_guard;
}
LRUKReplacer::~LRUKReplacer() {
delete[] hash_for_record;
LRUChainNodeType *ptr = LRU_chain_head_guard->next;
while (ptr != LRU_chain_tail_guard) {
LRUChainNodeType *tmp = ptr;
ptr = ptr->next;
delete tmp;
}
MainChainNodeType *ptr2 = LRUK_chain_head_guard->next;
while (ptr2 != LRUK_chain_tail_guard) {
MainChainNodeType *tmp = ptr2;
ptr2 = ptr2->next;
delete tmp;
}
delete LRU_chain_head_guard;
delete LRU_chain_tail_guard;
delete LRUK_chain_head_guard;
delete LRUK_chain_tail_guard;
}
void LRUKReplacer::SetEvictable(frame_id_t frame_id, bool evitable) {
std::lock_guard<std::mutex> guard(latch);
if (!hash_for_record[frame_id].active) {
return;
}
if (hash_for_record[frame_id].evitable == evitable) {
return;
}
hash_for_record[frame_id].evitable = evitable;
if (evitable) {
current_evitable_count_++;
} else {
current_evitable_count_--;
}
}
void LRUKReplacer::RemoveWholeFrameFromLRUKChain(MainChainNodeType *first_occurrence_ptr) {
if (first_occurrence_ptr == nullptr) return;
MainChainNodeType *tmp;
while (first_occurrence_ptr != nullptr) {
tmp = first_occurrence_ptr;
RemoveFromList(tmp);
first_occurrence_ptr = first_occurrence_ptr->next_self_record;
delete tmp;
}
}
LRUKReplacer::MainChainNodeType *LRUKReplacer::AddRecordToMainChain(frame_id_t frame_id, size_t time_stamp,
MainChainNodeType *last_node_in_main_chain) {
MainChainNodeType *new_node = new LRUKReplacer::MainChainNodeType(frame_id, time_stamp, nullptr, nullptr, nullptr);
if (last_node_in_main_chain != nullptr) last_node_in_main_chain->next_self_record = new_node;
InsertAt(new_node, LRUK_chain_tail_guard->prev, LRUK_chain_tail_guard);
return new_node;
}
bool LRUKReplacer::TryEvictExactFrame(frame_id_t frame_id) {
std::lock_guard<std::mutex> guard(latch);
if (!hash_for_record[frame_id].active) {
return false;
}
if (!hash_for_record[frame_id].evitable) {
return false;
}
LRUChainNodeType *node = hash_for_record[frame_id].node_in_LRU_chain;
if (node != nullptr) RemoveFromList(node);
delete node;
hash_for_record[frame_id].node_in_LRU_chain = nullptr;
RemoveWholeFrameFromLRUKChain(hash_for_record[frame_id].head_node_in_main_chain);
hash_for_record[frame_id].active = false;
current_evitable_count_--;
return true;
}
bool LRUKReplacer::TryEvictLeastImportant(frame_id_t &frame_id) {
latch.lock();
if (current_evitable_count_ == 0) {
latch.unlock();
return false;
}
LRUChainNodeType *node = LRU_chain_head_guard->next;
while (node != LRU_chain_tail_guard) {
frame_id = node->frame_id;
if (hash_for_record[frame_id].evitable) {
latch.unlock();
return TryEvictExactFrame(frame_id);
}
node = node->next;
}
MainChainNodeType *main_chain_node = LRUK_chain_head_guard->next;
while (main_chain_node != LRUK_chain_tail_guard) {
frame_id = main_chain_node->frame_id;
if (hash_for_record[frame_id].evitable) {
latch.unlock();
return TryEvictExactFrame(frame_id);
}
main_chain_node = main_chain_node->next;
}
latch.unlock();
return false;
}
void LRUKReplacer::RecordAccess(frame_id_t frame_id) {
std::lock_guard<std::mutex> guard(latch);
current_timestamp_++;
if (!hash_for_record[frame_id].active) {
hash_for_record[frame_id].active = true;
hash_for_record[frame_id].evitable = false;
hash_for_record[frame_id].visit_count = 1;
hash_for_record[frame_id].head_node_in_main_chain = hash_for_record[frame_id].tail_node_in_main_chain =
AddRecordToMainChain(frame_id, current_timestamp_, nullptr);
hash_for_record[frame_id].node_in_LRU_chain =
new LRUChainNodeType(frame_id, LRU_chain_tail_guard->prev, LRU_chain_tail_guard);
InsertAt(hash_for_record[frame_id].node_in_LRU_chain, LRU_chain_tail_guard->prev, LRU_chain_tail_guard);
} else {
hash_for_record[frame_id].visit_count++;
MainChainNodeType *last_occurrence_ptr = hash_for_record[frame_id].tail_node_in_main_chain;
MainChainNodeType *new_node_in_main_chain_ptr =
AddRecordToMainChain(frame_id, current_timestamp_, last_occurrence_ptr);
hash_for_record[frame_id].tail_node_in_main_chain = new_node_in_main_chain_ptr;
if (hash_for_record[frame_id].node_in_LRU_chain != nullptr) {
RemoveFromList(hash_for_record[frame_id].node_in_LRU_chain);
delete hash_for_record[frame_id].node_in_LRU_chain;
hash_for_record[frame_id].node_in_LRU_chain = nullptr;
}
if (hash_for_record[frame_id].visit_count < k_value) {
hash_for_record[frame_id].node_in_LRU_chain =
new LRUChainNodeType(frame_id, LRU_chain_tail_guard->prev, LRU_chain_tail_guard);
InsertAt(hash_for_record[frame_id].node_in_LRU_chain, LRU_chain_tail_guard->prev, LRU_chain_tail_guard);
}
if (hash_for_record[frame_id].visit_count > k_value) {
MainChainNodeType *first_occurrence_ptr = hash_for_record[frame_id].head_node_in_main_chain;
RemoveFromList(first_occurrence_ptr);
hash_for_record[frame_id].head_node_in_main_chain = first_occurrence_ptr->next_self_record;
delete first_occurrence_ptr;
}
}
}
size_t LRUKReplacer::GetCurrentEvitableCount() { return current_evitable_count_; }