mirror of
				https://github.com/Clortox/LRUCache.git
				synced 2025-07-17 12:52:11 +00:00 
			
		
		
		
	Initial Commit
This commit is contained in:
		
						commit
						5c81b63fe8
					
				
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | #ignore all .o files | ||||||
|  | src/**/*.o | ||||||
|  | 
 | ||||||
|  | #ignore all swp files | ||||||
|  | **/*.swp | ||||||
|  | 
 | ||||||
|  | #ignore all executables, but still keep the bin folder | ||||||
|  | bin/* | ||||||
|  | !bin/.gitkeep | ||||||
							
								
								
									
										43
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | ###############################################################################
 | ||||||
|  | # Tyler Perkins
 | ||||||
|  | # 7-21-21
 | ||||||
|  | # Makefile
 | ||||||
|  | #
 | ||||||
|  | 
 | ||||||
|  | CC = g++ | ||||||
|  | 
 | ||||||
|  | FLAGS = -pipe | ||||||
|  | 
 | ||||||
|  | CFLAGS  = -Wall | ||||||
|  | CFLAGS += -Ofast | ||||||
|  | #CFLAGS += -g
 | ||||||
|  | CFLAGS += -pg | ||||||
|  | 
 | ||||||
|  | LIBRARIES =  | ||||||
|  | 
 | ||||||
|  | SRC = $(shell find . -name '*.cpp') | ||||||
|  | HPP = $(shell find . -name '*.hpp') | ||||||
|  | OBJ = $(subst .cpp,.o,$(SRC)) | ||||||
|  | BIN = ./bin | ||||||
|  | 
 | ||||||
|  | TARGET = lrucache-test.out | ||||||
|  | 
 | ||||||
|  | all : $(BIN)/$(TARGET) | ||||||
|  | 
 | ||||||
|  | $(BIN)/$(TARGET) : $(OBJ) | ||||||
|  | 	@echo LD $(TARGET) | ||||||
|  | 	@$(CC) $(FLAGS) $(CFLAGS) -o $(BIN)/$(TARGET) $(OBJ) $(LIBRARIES) | ||||||
|  | 
 | ||||||
|  | .cpp.o : | ||||||
|  | 	@echo CC $< | ||||||
|  | 	@$(CC) $(FLAGS) $(CFLAGS) $(LIBRARIES) -c $< -o $@ -D_LRU_DEBUG_ | ||||||
|  | 
 | ||||||
|  | clean : | ||||||
|  | 	find . -type f -name '*.o' -delete | ||||||
|  | 	rm -rf $(TARGET) performance.prof gmon.out | ||||||
|  | 
 | ||||||
|  | sanity : $(BIN)/$(TARGET) | ||||||
|  | 	$(BIN)/$(TARGET) | ||||||
|  | 
 | ||||||
|  | profile: sanity | ||||||
|  | 	gprof $(BIN)/$(TARGET) > performance.prof | ||||||
							
								
								
									
										104
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | |||||||
|  | LRUCache | ||||||
|  | ======== | ||||||
|  | 
 | ||||||
|  | This is my implementation of a LRU (Least Recently Used) Cache. | ||||||
|  | The cache will store values and keep track of what was accessed most recently. | ||||||
|  | This is great to help reduce the amount of repetitive malloc calls, for | ||||||
|  | example.  | ||||||
|  | 
 | ||||||
|  | This implementation differs from most in that: | ||||||
|  | 
 | ||||||
|  | 1. It is associate | ||||||
|  | 2. Get always returns a value | ||||||
|  | 
 | ||||||
|  | The big use for me was get() creating values. If a value is not found in the | ||||||
|  | cache, it creates the value T(Key) and returns that. This does not have to be | ||||||
|  | used, however, if you only use get() on values you are positive have been put() | ||||||
|  | into the cache. | ||||||
|  | 
 | ||||||
|  | To use this in a project, just copy lru.hpp into your own projects source tree. | ||||||
|  | The namespace it uses is clortox | ||||||
|  | 
 | ||||||
|  | Run tests | ||||||
|  | ========= | ||||||
|  | 
 | ||||||
|  | You can run the test suite with the following: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | make sanity | ||||||
|  | 
 | ||||||
|  | # Relies on gprof | ||||||
|  | make profile | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Interface | ||||||
|  | ========= | ||||||
|  | 
 | ||||||
|  | Constructors | ||||||
|  | ------------ | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | LRUCache() | ||||||
|  | LRUCache(size_t max_size) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Defaults size of cache to 50 | ||||||
|  | 
 | ||||||
|  | Utility | ||||||
|  | ------- | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | void clear() | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Clears out the contents of the cache | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | bool empty() const | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Returns true if the cache is empty | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | bool full() const | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Returns true if the cache is full | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | size_t getMaxCacheSize() const | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Returns the cache size, passed as `max_size` when constructing | ||||||
|  | 
 | ||||||
|  | Accessors | ||||||
|  | -------- | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | T& get(const Key&) | ||||||
|  | T& operator[](const Key&) | ||||||
|  | T& operator[](Key&) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Returns T associated with Key. If none exists, creates T(key), inserts it into | ||||||
|  | the cache, and returns a reference to it | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | void put(const Key&, const T&) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Places (Key, T) into the cache as the most recent item | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | bool erase(const Key&) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Erases element associated with Key. Use this if you know that item is not | ||||||
|  | likely to accessed soon and would like to delete ahead of time | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | void pop_back() | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Removes oldest element from the cache. Can be used, however is more often used | ||||||
|  | internally | ||||||
							
								
								
									
										0
									
								
								bin/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								bin/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										272
									
								
								src/lru/lru.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								src/lru/lru.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,272 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Tyler Perkins
 | ||||||
|  | // 8-23-21
 | ||||||
|  | // LRU cache implementation
 | ||||||
|  | //
 | ||||||
|  | 
 | ||||||
|  | #ifndef _LRUCACHE_HPP_ | ||||||
|  | #define _LRUCACHE_HPP_ | ||||||
|  | 
 | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <list> | ||||||
|  | #include <cstddef> | ||||||
|  | 
 | ||||||
|  | #include <iostream> | ||||||
|  | 
 | ||||||
|  | namespace clortox { | ||||||
|  |     constexpr size_t __default_max_cache_size = 50; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     template<class Key, class T> | ||||||
|  |     struct value_iterator { | ||||||
|  |         typename std::list<Key>::iterator it; | ||||||
|  |         T value; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     template<class Key, class T, class Hash = std::hash<Key>> | ||||||
|  |     class LRUCache{ | ||||||
|  |     public: | ||||||
|  |         LRUCache(); | ||||||
|  |         LRUCache(size_t); | ||||||
|  |         ~LRUCache(); | ||||||
|  |         LRUCache(const LRUCache&); | ||||||
|  |         LRUCache& operator=(const LRUCache&); | ||||||
|  | 
 | ||||||
|  |         void swap(LRUCache&); | ||||||
|  | 
 | ||||||
|  |         //utility
 | ||||||
|  |         void          clear          (); | ||||||
|  |         inline bool   empty          () const; | ||||||
|  |         inline bool   full           () const; | ||||||
|  |         inline size_t getMaxCacheSize() const; | ||||||
|  | 
 | ||||||
|  |         //accessors functions
 | ||||||
|  |         T&            get       (const Key&); | ||||||
|  |         inline T&     operator[](const Key&); | ||||||
|  |         inline T&     operator[](Key&); | ||||||
|  |         void          put       (const Key&, const T&); | ||||||
|  |         bool          erase     (const Key&); | ||||||
|  |         void          pop_back  (); | ||||||
|  | 
 | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |         bool          wasHit = false; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         //list
 | ||||||
|  |         std::list<Key> _list; | ||||||
|  |         //hashmap
 | ||||||
|  |         std::unordered_map<Key, value_iterator<Key, T>, Hash> _hash_map; | ||||||
|  | 
 | ||||||
|  |         size_t _max_cache_size; | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Implementation /////////////////////////////////////////////////////////////
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Default Ctor
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | clortox::LRUCache<Key, T, Hash>::LRUCache()  | ||||||
|  |     : LRUCache(__default_max_cache_size) {}; | ||||||
|  | 
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | clortox::LRUCache<Key, T, Hash>::LRUCache( | ||||||
|  |         size_t max_size) : _max_cache_size(max_size){ | ||||||
|  | 
 | ||||||
|  |     _hash_map.reserve(max_size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Dector
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | clortox::LRUCache<Key, T, Hash>::~LRUCache(){ | ||||||
|  |     while(!empty()){ | ||||||
|  |         pop_back(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Copy ctor
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | clortox::LRUCache<Key, T, Hash>::LRUCache(const LRUCache& rhs){ | ||||||
|  |     _max_cache_size = rhs._max_cache_size; | ||||||
|  |     _hash_map       = rhs._hash_map; | ||||||
|  |     _list           = rhs._list; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Assignment operator
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | clortox::LRUCache<Key, T, Hash>& clortox::LRUCache< | ||||||
|  |     Key, T, Hash>::operator=(const LRUCache& rhs){ | ||||||
|  | 
 | ||||||
|  |     if(this != &rhs){ | ||||||
|  |         _max_cache_size = rhs._max_cache_size; | ||||||
|  |         _hash_map       = rhs._hash_map; | ||||||
|  |         _list           = rhs._list; | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Swap function
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | void clortox::LRUCache<Key, T, Hash>::swap(LRUCache& rhs){ | ||||||
|  |     decltype(_hash_map) tmphashmap = rhs._hash_map; | ||||||
|  |     rhs._hash_map = _hash_map; | ||||||
|  |     _hash_map = tmphashmap; | ||||||
|  | 
 | ||||||
|  |     decltype(_list) tmplist = rhs._list; | ||||||
|  |     rhs._list = _list; | ||||||
|  |     _list = tmplist; | ||||||
|  | 
 | ||||||
|  |     decltype(_max_cache_size) tmpmax = rhs._max_cache_size; | ||||||
|  |     rhs._max_cache_size = _max_cache_size; | ||||||
|  |     _max_cache_size = tmpmax; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Clears out all elements from cache
 | ||||||
|  | // This should only be called if all 
 | ||||||
|  | // elements in the cache are not likely
 | ||||||
|  | // to be used again
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | void clortox::LRUCache<Key, T, Hash>::clear(){ | ||||||
|  |     for(auto it = _hash_map.begin(); it != _hash_map.end();){ | ||||||
|  |         _list.erase(it->second.it); | ||||||
|  |         it = _hash_map.erase(it); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Returns true if the cache is empty
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | bool clortox::LRUCache<Key, T, Hash>::empty() const{ | ||||||
|  |     return _list.empty(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Check if cache is full
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | bool clortox::LRUCache<Key, T, Hash>::full() const{ | ||||||
|  |     return _list.size() == _max_cache_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Returns the max cache size
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | size_t clortox::LRUCache<Key, T, Hash>::getMaxCacheSize() const{ | ||||||
|  |     return _max_cache_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Accessor functions /////////////////////////////////////////////////////////
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // get element from cache. If it does
 | ||||||
|  | // not exist, create it
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | T& clortox::LRUCache<Key, T, Hash>::get(const Key& key){ | ||||||
|  |     if(_hash_map.find(key) != _hash_map.end()){ //cache hit
 | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |         wasHit = true; | ||||||
|  | #endif | ||||||
|  |         //update list
 | ||||||
|  |         _list.erase(_hash_map[key].it); | ||||||
|  |         _list.push_front(key); | ||||||
|  |         _hash_map[key].it = _list.begin(); | ||||||
|  | 
 | ||||||
|  |         return _hash_map[key].value; | ||||||
|  |     } else { //cache miss
 | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |         wasHit = false; | ||||||
|  | #endif | ||||||
|  |         //if cache is full, remove oldest element
 | ||||||
|  |         if(_list.size() == _max_cache_size){ | ||||||
|  |             _hash_map.erase(_list.back()); | ||||||
|  |             _list.pop_back(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //add new element
 | ||||||
|  |         _list.push_front(key); | ||||||
|  | 
 | ||||||
|  |         _hash_map[key] = { .it = _list.begin(), .value = T(key) }; | ||||||
|  |         return _hash_map[key].value; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Index operator returns value with 
 | ||||||
|  | // assoc key. If it does not exist, we 
 | ||||||
|  | // create it
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | T& clortox::LRUCache<Key, T, Hash>::operator[](const Key& key){ | ||||||
|  |     return get(key); | ||||||
|  | } | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | T& clortox::LRUCache<Key, T, Hash>::operator[](Key& key){ | ||||||
|  |     return get(key); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Puts the key value pair into the 
 | ||||||
|  | // cache
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | void clortox::LRUCache<Key, T, Hash>::put(const Key& key, const T& value){ | ||||||
|  |     if(_hash_map.find(key) != _hash_map.end()){ //cache hit
 | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |         wasHit = true; | ||||||
|  | #endif | ||||||
|  |         //update list
 | ||||||
|  |         _list.erase(_hash_map[key].it); | ||||||
|  |         _list.push_front(key); | ||||||
|  |         _hash_map[key].it = _list.begin(); | ||||||
|  | 
 | ||||||
|  |         _hash_map[key].value = value; | ||||||
|  |     } else { //cache hit, insert new element
 | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |         wasHit = false; | ||||||
|  | #endif | ||||||
|  |         //if cache is full, remove oldest element
 | ||||||
|  |         if(_list.size() == _max_cache_size){ | ||||||
|  |             _hash_map.erase(_list.back()); | ||||||
|  |             _list.pop_back(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //add new element
 | ||||||
|  |         _list.push_front(key); | ||||||
|  |         _hash_map[key] = { .it = _list.begin(), .value = value }; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Remove element from cache. Only do
 | ||||||
|  | // this if positive it will not be
 | ||||||
|  | // referenced again
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | bool clortox::LRUCache<Key, T, Hash>::erase(const Key& key){ | ||||||
|  |     if(_hash_map.find(key) != _hash_map.end()){ //cache hit
 | ||||||
|  |         //remove element
 | ||||||
|  |         _list.erase(_hash_map[key].it); | ||||||
|  |         _hash_map.erase(key); | ||||||
|  |         return true; | ||||||
|  |     } //not in cache, return false
 | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////////////////////
 | ||||||
|  | // Remove oldest element
 | ||||||
|  | template<class Key, class T, class Hash> | ||||||
|  | void clortox::LRUCache<Key, T, Hash>::pop_back(){ | ||||||
|  |     if(!_list.empty()){ | ||||||
|  |         _hash_map.erase(_list.back()); | ||||||
|  |         _list.pop_back(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif //!_LRUCACHE_HPP_
 | ||||||
							
								
								
									
										172
									
								
								src/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								src/main.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,172 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Tyler Perkins
 | ||||||
|  | // 8-23-21
 | ||||||
|  | //
 | ||||||
|  | 
 | ||||||
|  | #include "lru/lru.hpp" | ||||||
|  | #include <iostream> | ||||||
|  | #include <cassert> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <time.h> | ||||||
|  | #include <chrono> | ||||||
|  | 
 | ||||||
|  | using clortox::LRUCache; | ||||||
|  | 
 | ||||||
|  | class arr{ | ||||||
|  | public: | ||||||
|  |     arr() { ptr = nullptr; }; | ||||||
|  |     arr(int size){  | ||||||
|  |         ptr = new int[size]; | ||||||
|  |         for(int i = 0; i < size; ++i) | ||||||
|  |             ptr[i] = i; | ||||||
|  |     } | ||||||
|  |     ~arr(){ delete[] ptr; }; | ||||||
|  |     int get(int index) const { return ptr[index]; }; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     int* ptr; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int main(int argc, char** argv){ | ||||||
|  |     std::cout << "===== LRUCache Tests =====" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Testing if cannonical..." << std::endl; | ||||||
|  |     { | ||||||
|  |         LRUCache<int, char> cache; | ||||||
|  |         assert(cache.getMaxCacheSize() == clortox::__default_max_cache_size); | ||||||
|  |         assert(cache.empty()); | ||||||
|  |          | ||||||
|  |         LRUCache<int, char> ccache(25); | ||||||
|  |         assert(ccache.getMaxCacheSize() == 25); | ||||||
|  | 
 | ||||||
|  |         LRUCache<int, char> dcache(ccache); | ||||||
|  |         assert(dcache.getMaxCacheSize() == 25); | ||||||
|  | 
 | ||||||
|  |         ccache = cache; | ||||||
|  |         assert(ccache.getMaxCacheSize() == clortox::__default_max_cache_size); | ||||||
|  | 
 | ||||||
|  |         ccache.swap(dcache); | ||||||
|  |         assert(ccache.getMaxCacheSize() == 25); | ||||||
|  |         assert(dcache.getMaxCacheSize() == clortox::__default_max_cache_size); | ||||||
|  |     } | ||||||
|  |     std::cout << "Testing if cannonical passed!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Testing put functions..." << std::endl; | ||||||
|  |     { | ||||||
|  |         LRUCache<int, char> cache(5); | ||||||
|  |         cache.put(1, 'a'); | ||||||
|  |         cache.put(26, 'z'); | ||||||
|  |         cache.put(10, 'j'); | ||||||
|  |         cache.put(3, 'b'); | ||||||
|  | 
 | ||||||
|  |         assert(cache.get(26) == 'z'); | ||||||
|  |         cache.put(10, 'j'); | ||||||
|  |         assert(cache.get(10) == 'j'); | ||||||
|  |         cache.put(2, 'b'); | ||||||
|  |         assert(cache.get(2) == 'b'); | ||||||
|  |          | ||||||
|  |         cache.put(1, 'a'); | ||||||
|  |         assert(cache.get(1) == 'a'); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |     std::cout << "Testing put functions passed!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Testing get functions with custom types..." << std::endl; | ||||||
|  |     { | ||||||
|  |         LRUCache<int, arr> cache(3); | ||||||
|  |         assert(cache.get(5).get(3) == 3); | ||||||
|  |         assert(cache.get(6).get(5) == 5); | ||||||
|  |         assert(cache.get(10).get(7) == 7); | ||||||
|  |         //cache hit
 | ||||||
|  |         assert(cache.get(6).get(5) == 5); | ||||||
|  | 
 | ||||||
|  |         //drop last element of cache
 | ||||||
|  |         assert(cache.get(2).get(1) == 1); | ||||||
|  |     } | ||||||
|  |     std::cout << "Testing get functions with custom types passed!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Testing operator[] with custom types..." << std::endl; | ||||||
|  |     { | ||||||
|  |         LRUCache<int, arr> cache(3); | ||||||
|  |         assert(cache[5].get(3) == 3); | ||||||
|  |         assert(cache[6].get(5) == 5); | ||||||
|  |         assert(cache[10].get(7) == 7); | ||||||
|  |         //cache hit
 | ||||||
|  |         assert(cache[6].get(5) == 5); | ||||||
|  | 
 | ||||||
|  |         //drop last element of cache
 | ||||||
|  |         assert(cache[2].get(1) == 1); | ||||||
|  |     } | ||||||
|  |     std::cout << "Testing operator[] with custom passed!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Testing erase function..." << std::endl; | ||||||
|  |     { | ||||||
|  |         LRUCache<int, char> cache(5); | ||||||
|  |         cache.put(1, 'a'); | ||||||
|  |         cache.put(2, 'b'); | ||||||
|  |         cache.put(3, 'c'); | ||||||
|  |         cache.put(4, 'd'); | ||||||
|  |         cache.put(5, 'e'); | ||||||
|  | 
 | ||||||
|  |         assert(cache.full() == true); | ||||||
|  | 
 | ||||||
|  |         assert(cache.erase(26) == false); | ||||||
|  | 
 | ||||||
|  |         assert(cache.erase(1) == true); | ||||||
|  | 
 | ||||||
|  |         assert(cache.full() == false); | ||||||
|  |     } | ||||||
|  |     std::cout << "Testing erase function passed!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Testing pop_back..." << std::endl; | ||||||
|  |     { | ||||||
|  |         LRUCache<int, char> cache(5); | ||||||
|  |         cache.put(1, 'a'); | ||||||
|  |         cache.put(2, 'b'); | ||||||
|  |         cache.put(3, 'c'); | ||||||
|  |         cache.put(4, 'd'); | ||||||
|  |         cache.put(5, 'e'); | ||||||
|  | 
 | ||||||
|  |         assert(cache.full() == true); | ||||||
|  | 
 | ||||||
|  |         cache.pop_back(); | ||||||
|  |          | ||||||
|  |         assert(cache.full() == false); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |     std::cout << "Testing pop_back passed!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "Performance testing..." << std::endl; | ||||||
|  |     { | ||||||
|  |         srand(time(NULL)); | ||||||
|  |         size_t hits = 0; | ||||||
|  | 
 | ||||||
|  |         std::cout << "Cache size        : 1000\n"; | ||||||
|  |         std::cout << "Range of elements : 10000\n"; | ||||||
|  |         std::cout << "Iterations        : 1000000\n"; | ||||||
|  | 
 | ||||||
|  |         LRUCache<int, arr> cache(1000); | ||||||
|  | 
 | ||||||
|  |         auto start = std::chrono::high_resolution_clock::now(); | ||||||
|  | 
 | ||||||
|  |         for(size_t i = 0; i < 1000000; ++i){ | ||||||
|  |             cache.get(rand() % 10000 + 1); | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |             if(cache.wasHit) | ||||||
|  |                 hits++; | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         auto end = std::chrono::high_resolution_clock::now(); | ||||||
|  |         std::cout << "Running time: " <<  | ||||||
|  |             std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() | ||||||
|  |             << " milliseconds" << std::endl; | ||||||
|  | #ifdef _LRU_DEBUG_ | ||||||
|  |         std::cout << "Cache hits: " << hits << std::endl; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |     std::cout << "Performance testing finished!" << std::endl; | ||||||
|  | 
 | ||||||
|  |     std::cout << "===== LRUCache Tests =====" << std::endl; | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tyler Perkins
						Tyler Perkins