mirror of
https://github.com/YuhangQ/InvoDB.git
synced 2025-01-26 22:50:56 +00:00
add cache
This commit is contained in:
parent
e8e6a73266
commit
99265240b8
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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&);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user