diff --git a/src/main/java/me/doubledutch/pikadb/Column.java b/src/main/java/me/doubledutch/pikadb/Column.java index 24ef228..3b18f45 100644 --- a/src/main/java/me/doubledutch/pikadb/Column.java +++ b/src/main/java/me/doubledutch/pikadb/Column.java @@ -3,6 +3,10 @@ import java.util.*; import java.io.*; +import me.doubledutch.pikadb.page.Page; +import me.doubledutch.pikadb.page.PageFile; + + public class Column{ private PageFile pageFile; public int rootId; diff --git a/src/main/java/me/doubledutch/pikadb/Soup.java b/src/main/java/me/doubledutch/pikadb/Soup.java index 8239a80..81251db 100644 --- a/src/main/java/me/doubledutch/pikadb/Soup.java +++ b/src/main/java/me/doubledutch/pikadb/Soup.java @@ -2,6 +2,10 @@ import java.io.*; import java.util.*; + +import me.doubledutch.pikadb.page.Page; +import me.doubledutch.pikadb.page.PageFile; + import org.json.*; public class Soup{ diff --git a/src/main/java/me/doubledutch/pikadb/Test.java b/src/main/java/me/doubledutch/pikadb/Test.java index be35dcb..c7a518c 100644 --- a/src/main/java/me/doubledutch/pikadb/Test.java +++ b/src/main/java/me/doubledutch/pikadb/Test.java @@ -2,6 +2,10 @@ import java.io.*; import java.util.*; + +import me.doubledutch.pikadb.page.Page; +import me.doubledutch.pikadb.page.PageFile; + import org.json.*; public class Test{ @@ -229,6 +233,17 @@ public static void main(String args[]){ obj=soup.scan(RECORDS/2); // System.out.println(obj); + int totalHit, totalMiss; + totalHit = totalMiss = 0; + for (Map.Entry entry : f.pageMap.entrySet()){ + Page page=entry.getValue(); + totalHit += page.getCacheHits(); + totalMiss += page.getCacheMisses(); + //if (page.cacheMiss > 0 || page.cacheHit > 0){ + // System.out.println("Page "+entry.getKey()+": "+page.cacheHit+" hits, "+page.cacheMiss+" misses"); + //} + } + System.out.println(" -- Cache hit ratio: "+(float)totalHit/(totalMiss+totalHit)); f.close(); /* diff --git a/src/main/java/me/doubledutch/pikadb/Variant.java b/src/main/java/me/doubledutch/pikadb/Variant.java index 17fb221..e23ca12 100644 --- a/src/main/java/me/doubledutch/pikadb/Variant.java +++ b/src/main/java/me/doubledutch/pikadb/Variant.java @@ -1,7 +1,11 @@ package me.doubledutch.pikadb; import java.io.*; + +import me.doubledutch.pikadb.page.Page; + import org.json.*; + import java.util.*; public abstract class Variant implements Comparable{ diff --git a/src/main/java/me/doubledutch/pikadb/WriteAheadLog.java b/src/main/java/me/doubledutch/pikadb/WriteAheadLog.java index 1cf7424..b1bf6b1 100644 --- a/src/main/java/me/doubledutch/pikadb/WriteAheadLog.java +++ b/src/main/java/me/doubledutch/pikadb/WriteAheadLog.java @@ -1,5 +1,7 @@ package me.doubledutch.pikadb; +import me.doubledutch.pikadb.page.PageDiff; + public class WriteAheadLog{ public WriteAheadLog(String filename){ diff --git a/src/main/java/me/doubledutch/pikadb/page/LRUPageCache.java b/src/main/java/me/doubledutch/pikadb/page/LRUPageCache.java new file mode 100644 index 0000000..c52444f --- /dev/null +++ b/src/main/java/me/doubledutch/pikadb/page/LRUPageCache.java @@ -0,0 +1,35 @@ +package me.doubledutch.pikadb.page; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Map; + +class LRUPageCache implements PageCache{ + private int size; + private Map pageMap; + private Deque pageCache; + + public LRUPageCache(Map map, int size){ + this.size=size; + this.pageMap=map; + this.pageCache=new ArrayDeque(); + } + + public boolean Set(int id){ + if (!pageMap.containsKey(id)){ + return false; + } + boolean cached=false; + if (pageCache.contains(id)){ + pageCache.remove(id); + cached=true; + } + pageCache.addFirst(id); + if (pageCache.size() > size){ + Integer evictID=pageCache.removeLast(); + Page evict=pageMap.get(evictID); + evict.unloadRawData(); + } + return cached; + } +} \ No newline at end of file diff --git a/src/main/java/me/doubledutch/pikadb/page/NoopPageCache.java b/src/main/java/me/doubledutch/pikadb/page/NoopPageCache.java new file mode 100644 index 0000000..f46fc56 --- /dev/null +++ b/src/main/java/me/doubledutch/pikadb/page/NoopPageCache.java @@ -0,0 +1,8 @@ +package me.doubledutch.pikadb.page; + + +class NoopPageCache implements PageCache{ + public boolean Set(int id) { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/me/doubledutch/pikadb/Page.java b/src/main/java/me/doubledutch/pikadb/page/Page.java similarity index 93% rename from src/main/java/me/doubledutch/pikadb/Page.java rename to src/main/java/me/doubledutch/pikadb/page/Page.java index 9a7f189..3e5fb7e 100644 --- a/src/main/java/me/doubledutch/pikadb/Page.java +++ b/src/main/java/me/doubledutch/pikadb/page/Page.java @@ -1,8 +1,10 @@ -package me.doubledutch.pikadb; +package me.doubledutch.pikadb.page; import java.util.*; import java.io.*; +import me.doubledutch.pikadb.WriteAheadLog; + public class Page{ public static int UNSORTED=0; public static int SORTED=1; @@ -29,6 +31,8 @@ public class Page{ private List diffList=new LinkedList(); + private int cacheMiss, cacheHit; + public Page(int id,long offset,RandomAccessFile pageFile,PageFile pageHandler) throws IOException{ this.id=id; this.offset=offset; @@ -74,9 +78,12 @@ protected void unloadRawData(){ private void loadRawData() throws IOException{ if(rawData==null){ pageHandler.trimPageSet(id); + cacheMiss++; rawData=new byte[PAYLOAD]; pageFile.seek(offset+HEADER); pageFile.readFully(rawData); + } else { + cacheHit++; } } @@ -181,4 +188,12 @@ public void appendData(byte[] data){ dirty=true; // System.out.println("currentFill: "+id+" "+currentFill+" "+data.length); } + + public int getCacheHits() { + return cacheHit; + } + + public int getCacheMisses() { + return cacheMiss; + } } \ No newline at end of file diff --git a/src/main/java/me/doubledutch/pikadb/page/PageCache.java b/src/main/java/me/doubledutch/pikadb/page/PageCache.java new file mode 100644 index 0000000..0feedc8 --- /dev/null +++ b/src/main/java/me/doubledutch/pikadb/page/PageCache.java @@ -0,0 +1,10 @@ +package me.doubledutch.pikadb.page; + +interface PageCache{ + /** + * Sets an item in the cache + * @param id id of cached item + * @return whether or not item is cached + */ + boolean Set(int id); +} \ No newline at end of file diff --git a/src/main/java/me/doubledutch/pikadb/PageDiff.java b/src/main/java/me/doubledutch/pikadb/page/PageDiff.java similarity index 87% rename from src/main/java/me/doubledutch/pikadb/PageDiff.java rename to src/main/java/me/doubledutch/pikadb/page/PageDiff.java index b1ea028..b7f064e 100644 --- a/src/main/java/me/doubledutch/pikadb/PageDiff.java +++ b/src/main/java/me/doubledutch/pikadb/page/PageDiff.java @@ -1,4 +1,4 @@ -package me.doubledutch.pikadb; +package me.doubledutch.pikadb.page; public class PageDiff{ private int offset; diff --git a/src/main/java/me/doubledutch/pikadb/PageFile.java b/src/main/java/me/doubledutch/pikadb/page/PageFile.java similarity index 83% rename from src/main/java/me/doubledutch/pikadb/PageFile.java rename to src/main/java/me/doubledutch/pikadb/page/PageFile.java index 6651318..7850570 100644 --- a/src/main/java/me/doubledutch/pikadb/PageFile.java +++ b/src/main/java/me/doubledutch/pikadb/page/PageFile.java @@ -1,15 +1,20 @@ -package me.doubledutch.pikadb; +package me.doubledutch.pikadb.page; import java.io.*; import java.nio.channels.*; import java.util.*; +import me.doubledutch.pikadb.Column; +import me.doubledutch.pikadb.WriteAheadLog; + public class PageFile{ - private Map pageMap=new HashMap(); + public Map pageMap=new HashMap(); private RandomAccessFile pageFile; private FileChannel pageFileChannel; private String filename; private WriteAheadLog wal=null; + private PageCache cache; + private static int CACHE_SIZE = 500; public PageFile(String filename) throws IOException{ this.filename=filename; @@ -22,15 +27,15 @@ public PageFile(String filename) throws IOException{ ftest.delete(); wal=null; } + this.cache=new SLRUPageCache(pageMap, CACHE_SIZE); } private void recoverTransaction(){ // Replay everything in the write ahead log } - - private void trimPageSet(int id){ - + protected void trimPageSet(int id){ + cache.Set(id); } public Page getPage(int id) throws IOException{ @@ -71,7 +76,7 @@ public void saveChanges(boolean sort) throws IOException{ page.flatten(); Column.sort(page); } - page.commitChanges(wal); + page.commitChanges(wal); } wal.closeTransaction(); // Write to page file diff --git a/src/main/java/me/doubledutch/pikadb/page/SLRUPageCache.java b/src/main/java/me/doubledutch/pikadb/page/SLRUPageCache.java new file mode 100644 index 0000000..aeb8d43 --- /dev/null +++ b/src/main/java/me/doubledutch/pikadb/page/SLRUPageCache.java @@ -0,0 +1,49 @@ +package me.doubledutch.pikadb.page; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Map; + +class SLRUPageCache implements PageCache{ + private int size; + private Map pageMap; + private Deque l1, l2; + + public SLRUPageCache(Map map, int size){ + this.size=size; + this.pageMap=map; + this.l1=new ArrayDeque(); + this.l2=new ArrayDeque(); + } + + public boolean Set(int id){ + if (!pageMap.containsKey(id)){ + return false; + } + // If the page exists in L1, move it to L2 + // If L2 at size, move end to back of L1 + if (l1.contains(id)){ + l1.remove(id); + l2.addLast(id); + if (l2.size() > size){ + l1.addFirst(l2.removeLast()); + } + return true; + } + // If page exists in L2, move to L2 front + if (l2.contains(id)){ + l2.remove(id); + l2.addFirst(id); + return true; + } + // Put at front of L1 cache + l1.addFirst(id); + // If L1 size is at maximum, evict last page + if (l1.size() > size){ + Integer evictID=l1.removeLast(); + Page evict=pageMap.get(evictID); + evict.unloadRawData(); + } + return false; + } +}