add cache

This commit is contained in:
YuhangQ 2021-11-07 12:57:26 +08:00
parent e8e6a73266
commit 99265240b8
6 changed files with 149 additions and 82 deletions

View File

@ -2,6 +2,9 @@
// Created by i on 2021/10/24. // Created by i on 2021/10/24.
// //
#define UNLIMITED_MEMORY true
#ifndef INVODB_NODE_H #ifndef INVODB_NODE_H
#define INVODB_NODE_H #define INVODB_NODE_H
@ -11,38 +14,30 @@
#include <map> #include <map>
#include <type_traits> #include <type_traits>
#include "file/page_manager.h" #include "file/page_manager.h"
#include "models/cache.h" #include "invodb/models/cache.h"
template<int M_SIZE, typename KT, int K_SIZE> template<int M_SIZE, typename KT, int K_SIZE>
class BTreeNode { class BTreeNode {
public: public:
BTreeNode(const int& address);
static std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> getNode(const int &index);
static BTreeNode<M_SIZE, KT, K_SIZE>* release(const int &index);
int insert(KT const &key);
int findPos(KT const &key);
void update() {
if(leaf) return;
for(int i=0; i<=size; i++) {
auto node = getNode(linkSet[i]);
node->parent = address;
node->save();
}
}
void release();
void clear();
int save();
static const int m = M_SIZE; static const int m = M_SIZE;
static const int maxCount = m - 1; static const int maxCount = m - 1;
static const int minLeafCount = m / 2; static const int minLeafCount = m / 2;
static const int minLinkCount = (m - 1) / 2; static const int minLinkCount = (m - 1) / 2;
bool enough() { static std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> getNode(const int &index);
if(leaf) return size >= minLeafCount; static BTreeNode<M_SIZE, KT, K_SIZE>* release(const int &index);
else return size >= minLinkCount;
} BTreeNode(const int& address);
bool full() {
return size == maxCount; int insert(KT const &key);
} int findPos(KT const &key);
void update();
void release();
void clear();
int save();
bool enough();
bool full();
KT keySet[m + 1]; KT keySet[m + 1];
int linkSet[m + 1]; int linkSet[m + 1];
int parent; int parent;
@ -51,8 +46,17 @@ public:
bool leaf; bool leaf;
int size; int size;
int address; int address;
private:
//static std::map<int, std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>>> cache;
static LRUCache<int, std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>>> cache;
}; };
//template<int M_SIZE, typename KT, int K_SIZE>
//std::map<int, std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>>> BTreeNode<M_SIZE, KT, K_SIZE>::cache;
template<int M_SIZE, typename KT, int K_SIZE>
LRUCache<int, std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>>> BTreeNode<M_SIZE, KT, K_SIZE>::cache(100000);
template<int M_SIZE, typename KT, int K_SIZE> template<int M_SIZE, typename KT, int K_SIZE>
BTreeNode<M_SIZE, KT, K_SIZE>::BTreeNode(const int& address): address(address) { BTreeNode<M_SIZE, KT, K_SIZE>::BTreeNode(const int& address): address(address) {
clear(); clear();
@ -94,11 +98,26 @@ std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> BTreeNode<M_SIZE, KT, K_SIZE>::ge
if(index == 0) { if(index == 0) {
throw "invalid address!"; throw "invalid address!";
} }
// if(!cache.exist(index)) {
// auto p = std::make_shared<BTreeNode<M_SIZE, KT, K_SIZE>>(index);
// cache.put(index, p);
// return p;
// } else {
// auto p = cache.get(index);
// cache.put(index, p);
// return p;
// }
return std::make_shared<BTreeNode<M_SIZE, KT, K_SIZE>>(index); return std::make_shared<BTreeNode<M_SIZE, KT, K_SIZE>>(index);
// if(cache.count(index) == 0) {
// cache[index] = std::make_shared<BTreeNode<M_SIZE, KT, K_SIZE>>(index);
// }
} }
template<int M_SIZE, typename KT, int K_SIZE> template<int M_SIZE, typename KT, int K_SIZE>
BTreeNode<M_SIZE, KT, K_SIZE> *BTreeNode<M_SIZE, KT, K_SIZE>::release(const int &index) { BTreeNode<M_SIZE, KT, K_SIZE> *BTreeNode<M_SIZE, KT, K_SIZE>::release(const int &index) {
//cache.remove(index);
PageManager::Instance().release(index); PageManager::Instance().release(index);
return nullptr; return nullptr;
} }
@ -192,4 +211,25 @@ int BTreeNode<M_SIZE, KT, K_SIZE>::save() {
return p; return p;
} }
template<int M_SIZE, typename KT, int K_SIZE>
void BTreeNode<M_SIZE, KT, K_SIZE>::update() {
if(leaf) return;
for(int i=0; i<=size; i++) {
auto node = getNode(linkSet[i]);
node->parent = address;
node->save();
}
}
template<int M_SIZE, typename KT, int K_SIZE>
bool BTreeNode<M_SIZE, KT, K_SIZE>::enough() {
if(leaf) return size >= minLeafCount;
else return size >= minLinkCount;
}
template<int M_SIZE, typename KT, int K_SIZE>
bool BTreeNode<M_SIZE, KT, K_SIZE>::full() {
return size == maxCount;
}
#endif //INVODB_NODE_H #endif //INVODB_NODE_H

View File

@ -6,35 +6,37 @@
#include "btree/list.h" #include "btree/list.h"
int PageManager::loadDatabase(const char *filename) { int PageManager::loadDatabase(const char *filename) {
Instance().stream.open(filename); Instance().stream.open(filename);
Instance().stream.seekp(0, std::ios::end); Instance().stream.seekp(0, std::ios::end);
int index = Instance().stream.tellp() / 1024; int index = Instance().stream.tellp() / 1024;
if(index == 0) { if(index == 0) {
StoragePage(0).save(); StoragePage page(0);
page.setIntStartFrom(4, 2);
page.save();
StoragePage(1).save(); StoragePage(1).save();
StoragePage(2).save();
} }
return 0; return 0;
} }
std::shared_ptr<StoragePage> PageManager::getPage(const int &index) { StoragePage PageManager::getPage(const int &index) {
if(cache.exist(index)) { // if(cache.exist(index)) {
return cache.get(index); // return *cache.get(index);
} // }
auto page = std::make_shared<StoragePage>(index); StoragePage page(index);
// 调整指针位置 // 调整指针位置
stream.clear(); stream.clear();
stream.seekg((long long)index * 1024); stream.seekg((long long)index * 1024);
stream.read(*page, 1024); stream.read(page, 1024);
return page; return page;
} }
void PageManager::setPage(const int &index, const StoragePage &page) { void PageManager::setPage(const int &index, const StoragePage &page) {
cache.put(index, std::make_shared<StoragePage>(page));
// auto p = cache.put(index, std::make_shared<StoragePage>(page));
// if(p == nullptr) return;
stream.clear(); stream.clear();
stream.seekg((long long)index * 1024); stream.seekg((long long)index * 1024);
@ -45,35 +47,39 @@ int PageManager::allocate() {
// try to allocate from free block list // try to allocate from free block list
auto page = getPage(0); auto page = getPage(0);
int index = page->getIntStartFrom(0); int index = page.getIntStartFrom(0);
if(index != 0) { if(index != 0) {
auto allocatePage = getPage(index); auto allocatePage = getPage(index);
page->setIntStartFrom(0, allocatePage->next()); page.setIntStartFrom(0, allocatePage.next());
// reset // reset
allocatePage->clear(); allocatePage.clear();
allocatePage->save(); allocatePage.save();
page->save(); page.save();
//printf("allocate: %d\n", index); //printf("1allocate: %d\n", index);
return index; return index;
} }
index = page.getIntStartFrom(4);
//printf("2allocate: %d\n", index);
// allocate block at the end page.setIntStartFrom(4, index + 1);
stream.seekp(0, std::ios::end); page.save();
index = stream.tellp() / 1024; // allocate block at the end
// stream.seekp(0, std::ios::end);
// index = stream.tellp() / 1024;
setPage(index, StoragePage(index)); setPage(index, StoragePage(index));
return index; return index;
} }
void PageManager::release(const int &index, const bool &next) { void PageManager::release(const int &index, const bool &next) {
auto page = getPage(0); auto page = getPage(0);
int head = page->getIntStartFrom(0); int head = page.getIntStartFrom(0);
auto releasePage = getPage(index); auto releasePage = getPage(index);
releasePage->setNext(head); releasePage.setNext(head);
page->setIntStartFrom(0, releasePage->getAddress()); page.setIntStartFrom(0, releasePage.getAddress());
page->save(); page.save();
releasePage->save(); releasePage.save();
//printf("release: %d\n", index); //printf("release: %d\n", index);
} }
@ -84,11 +90,11 @@ nlohmann::json PageManager::readJSONFromFile(const int &index) {
auto page = getPage(index); auto page = getPage(index);
while(true) { while(true) {
for(int i=0; i<1016; i++) { for(int i=0; i<1016; i++) {
if((*page)[i] == '\0') break; if(page[i] == '\0') break;
content.push_back((*page)[i]); content.push_back(page[i]);
} }
if(page->next() == 0) break; if(page.next() == 0) break;
page = getPage(page->next()); page = getPage(page.next());
} }
return nlohmann::json::parse(content); return nlohmann::json::parse(content);
@ -99,21 +105,21 @@ int PageManager::saveJSONToFile(const nlohmann::json& json) {
int size = content.size(); int size = content.size();
auto page = getPage(allocate()); auto page = getPage(allocate());
int res = page->getAddress(); int res = page.getAddress();
int p = 0; int p = 0;
while(p < size) { while(p < size) {
int len = std::min(size - p, 1016); int len = std::min(size - p, 1016);
page->setStartFrom(0, &content.c_str()[p], len); page.setStartFrom(0, &content.c_str()[p], len);
page->save(); page.save();
p += len; p += len;
if(p < size) { if(p < size) {
int newPage = allocate(); int newPage = allocate();
int lastPage = page->getAddress(); int lastPage = page.getAddress();
page->setNext(newPage); page.setNext(newPage);
page->save(); page.save();
page = getPage(newPage); page = getPage(newPage);
page->setLast(lastPage); page.setLast(lastPage);
page->save(); page.save();
} }
} }
return res; return res;

View File

@ -11,7 +11,7 @@
#include "storage_page.h" #include "storage_page.h"
#include "json/json.hpp" #include "json/json.hpp"
#include "models/cache.h" #include "invodb/models/cache.h"
template<typename T, int T_SIZE> template<typename T, int T_SIZE>
class List; class List;
@ -23,8 +23,11 @@ public:
return instance; return instance;
} }
static int loadDatabase(const char *filename); static int loadDatabase(const char *filename);
std::shared_ptr<StoragePage> getPage(const int &index);
StoragePage getPage(const int &index);
void setPage(const int &index, const StoragePage &page); void setPage(const int &index, const StoragePage &page);
template<typename T>
static std::shared_ptr<T> getNode(const int &index);
int allocate(); int allocate();
void release(const int &index, const bool &next = true); void release(const int &index, const bool &next = true);
int saveJSONToFile(const nlohmann::json& json); int saveJSONToFile(const nlohmann::json& json);
@ -32,9 +35,9 @@ public:
private: private:
std::map<int, StoragePage> map; std::map<int, StoragePage> map;
std::fstream stream; std::fstream stream;
LRUCache<int, StoragePage> cache; LRUCache<int, std::shared_ptr<StoragePage>> cache;
// 私有化实现单例 // 私有化实现单例
PageManager():cache(LRUCache<int, StoragePage>(100000)) {} PageManager():cache(LRUCache<int, std::shared_ptr<StoragePage>>(100000)) {}
~PageManager() {} ~PageManager() {}
PageManager(const PageManager&); PageManager(const PageManager&);
PageManager& operator=(const PageManager&); PageManager& operator=(const PageManager&);

View File

@ -30,16 +30,23 @@ int main() {
} }
// freopen("qq.txt", "r", stdin); freopen("qq.txt", "r", stdin);
// char qq[100], phone[100]; const int n = 1000000;
// for(int i=0; i<400000; i++) { char qq[100], phone[100];
// if(i % 1000 == 0) printf("[%d/%d] Inserting!\n", i, 400000);
// scanf("%s%s", qq, phone); clock_t start = clock();
// nlohmann::json json; for(int i=0; i<n; i++) {
// json["qq"] = qq; scanf("%s%s", qq, phone);
// json["phone"] = phone; nlohmann::json json;
// col->insert(json); json["qq"] = qq;
// } json["phone"] = phone;
col->insert(json);
if(i % (n/1000) == 0) {
printf("[%d/%d] time=%fs!\n", i, n, (double)(clock() - start) / CLOCKS_PER_SEC);
start = clock();
}
}
//col->test(); //col->test();
@ -57,7 +64,7 @@ int main() {
//} //}
// )"); // )");
testAndBenchmark(50000); testAndBenchmark(20000);
return 0; return 0;
} }

View File

@ -7,6 +7,7 @@
#include <list> #include <list>
#include <map> #include <map>
#include "invodb/file/storage_page.h"
template<typename KT, typename VT> template<typename KT, typename VT>
class LRUCache { class LRUCache {
@ -17,11 +18,16 @@ public:
return hash.find(key) != hash.end(); return hash.find(key) != hash.end();
} }
std::shared_ptr<VT> get(KT const &key) { void remove(KT const &key) {
ls.erase(hash[key]);
hash.erase(key);
}
VT get(KT const &key) {
if (hash.find(key) == hash.end()) if (hash.find(key) == hash.end())
throw "cache error"; throw "cache error";
else { else {
std::shared_ptr<VT> value = hash[key]->second; VT value = hash[key]->second;
ls.erase(hash[key]); ls.erase(hash[key]);
ls.push_front(std::make_pair(key, value)); ls.push_front(std::make_pair(key, value));
hash[key] = ls.begin(); hash[key] = ls.begin();
@ -29,22 +35,27 @@ public:
} }
} }
void put(KT const &key, std::shared_ptr<VT> const &value) { VT put(KT const &key, VT const &value) {
VT res;
if (hash.find(key) != hash.end()) { if (hash.find(key) != hash.end()) {
ls.erase(hash[key]); ls.erase(hash[key]);
} }
else if (ls.size() >= capacity) { else if (ls.size() >= capacity) {
res = ls.back().second;
printf("fuck\n");
exit(0);
hash.erase(ls.back().first); hash.erase(ls.back().first);
ls.pop_back(); ls.pop_back();
} }
ls.push_front(std::make_pair(key, value)); ls.push_front(std::make_pair(key, value));
hash[key] = ls.begin(); hash[key] = ls.begin();
return res;
} }
private: private:
int capacity; int capacity;
std::list<std::pair<KT, std::shared_ptr<VT>>> ls; std::list<std::pair<KT, VT>> ls;
std::unordered_map<KT, typename std::list<std::pair<KT, std::shared_ptr<VT>>>::iterator> hash; std::unordered_map<KT, typename std::list<std::pair<KT, VT>>::iterator> hash;
}; };

View File

@ -4,7 +4,7 @@
#include "collection.h" #include "collection.h"
BTree<std::string, 32> Collection::colList(2); BTree<std::string, 32> Collection::colList(1);
std::map<std::string, Collection*> Collection::map; std::map<std::string, Collection*> Collection::map;
void Collection::loadCollections() { void Collection::loadCollections() {
@ -231,7 +231,7 @@ void Collection::removeIndex(const std::string indexName, bool indexValue, const
void Collection::test() { void Collection::test() {
index->print(); index->print();
auto qq = new BTree<std::string, 128>(8); auto qq = new BTree<std::string, 128>(7);
while(true) { while(true) {
std::string q; std::string q;
std::cin >> q; std::cin >> q;