diff options
12 files changed, 0 insertions, 1555 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java index cbfe5d5ff01..cca6f43faa3 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/BundleMapper.java @@ -67,7 +67,6 @@ public class BundleMapper { bundleFromClass.put("com.yahoo.prelude.querytransform.RecallSearcher", searchAndDocprocBundle); bundleFromClass.put("com.yahoo.prelude.querytransform.StemmingSearcher", searchAndDocprocBundle); bundleFromClass.put("com.yahoo.prelude.searcher.BlendingSearcher", searchAndDocprocBundle); - bundleFromClass.put("com.yahoo.prelude.searcher.CachingSearcher", searchAndDocprocBundle); bundleFromClass.put("com.yahoo.prelude.searcher.DocumentSourceSearcher", searchAndDocprocBundle); bundleFromClass.put("com.yahoo.prelude.searcher.FieldCollapsingSearcher", searchAndDocprocBundle); bundleFromClass.put("com.yahoo.prelude.searcher.FillSearcher", searchAndDocprocBundle); diff --git a/config/src/test/java/com/yahoo/vespa/config/classes/testfoobar.12.def b/config/src/test/java/com/yahoo/vespa/config/classes/testfoobar.12.def index ba008565f8d..863ac2b0fed 100644 --- a/config/src/test/java/com/yahoo/vespa/config/classes/testfoobar.12.def +++ b/config/src/test/java/com/yahoo/vespa/config/classes/testfoobar.12.def @@ -497,12 +497,6 @@ com.yahoo.prelude.searcher.BoldingSearcher.source string default="" com.yahoo.prelude.searcher.JuniperSearcher.source string default="" com.yahoo.prelude.searcher.JuniperSearcher.defaultdoctype string default="" -## Query cache that can be placed anywhere in the search chain. Query/Result -## pairs (ie. entries) bigger than maxentrysizebytes will not be cached. -com.yahoo.prelude.searcher.CachingSearcher.cachesizemegabytes int default=100 -com.yahoo.prelude.searcher.CachingSearcher.timetoliveseconds int default=3600 -com.yahoo.prelude.searcher.CachingSearcher.maxentrysizebytes int default=10000 - com.yahoo.prelude.searcher.XMLStringSearcher.source string default="" ## relevancy as measured from the backend will usually be diff --git a/container-core/src/main/resources/configdefinitions/qr-searchers.def b/container-core/src/main/resources/configdefinitions/qr-searchers.def index 1f2906f45ff..e2b4836c081 100644 --- a/container-core/src/main/resources/configdefinitions/qr-searchers.def +++ b/container-core/src/main/resources/configdefinitions/qr-searchers.def @@ -19,12 +19,6 @@ com.yahoo.prelude.searcher.BlendingSearcher.docid string default="" com.yahoo.prelude.searcher.JuniperSearcher.source string default="" com.yahoo.prelude.searcher.JuniperSearcher.defaultdoctype string default="" -## Query cache that can be placed anywhere in the search chain. Query/Result -## pairs (ie. entries) bigger than maxentrysizebytes will not be cached. -com.yahoo.prelude.searcher.CachingSearcher.cachesizemegabytes int default=100 -com.yahoo.prelude.searcher.CachingSearcher.timetoliveseconds int default=3600 -com.yahoo.prelude.searcher.CachingSearcher.maxentrysizebytes int default=10000 - com.yahoo.prelude.searcher.XMLStringSearcher.source string default="" ## Default docsum class the QR server should ask the backend to diff --git a/container-search/src/main/java/com/yahoo/prelude/cache/Cache.java b/container-search/src/main/java/com/yahoo/prelude/cache/Cache.java deleted file mode 100644 index 9e0dde4b63a..00000000000 --- a/container-search/src/main/java/com/yahoo/prelude/cache/Cache.java +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.prelude.cache; - -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.yahoo.cache.SizeCalculator; -import com.yahoo.search.Result; -import com.yahoo.statistics.Statistics; -import com.yahoo.statistics.Value; - -/** - * <p>A generic cache which keeps the total memory consumed by its content - * below a configured maximum.</p> - * - * <p>Thread safe.</p> - * - * @author vegardh - */ -public class Cache<K, V> { - private Value elems = null; - private Value entrySizes = null; - - private Map<CacheKey<K>,CacheValue<K, V>> content=new LinkedHashMap<>(12500, 1.0f, true); - private SizeCalculator calc = new SizeCalculator(); - private long maxSizeBytes; - - private long currentSizeBytes=0; - - /** The time an element is allowed to live, negative for indefinite lifespan */ - private long timeToLiveMillis=-1; - - /** The max allowed size of an entry */ - private long maxEntrySizeBytes=10000; - - /** - * Creates a new cache - * - * @param maxSizeBytes the max size in bytes this cache is permitted to consume, - * including Result objects and Query keys - * @param timeToLiveMillis a negative value means unlimited time - * @param manager the current Statistics manager acquired by injection - */ - public Cache(long maxSizeBytes,long timeToLiveMillis, long maxEntrySizeBytes, Statistics manager) { - this.maxSizeBytes=maxSizeBytes; - this.timeToLiveMillis=timeToLiveMillis; - this.maxEntrySizeBytes=maxEntrySizeBytes; - initStats(manager); - } - - private void initStats(Statistics manager) { - elems = new Value("querycache_elems", manager, new Value.Parameters() - .setLogRaw(true).setNameExtension(true).setLogMax(true)); - entrySizes = new Value("querycache_entry_sizes", manager, - new Value.Parameters().setLogRaw(false).setLogMean(true) - .setNameExtension(true).setLogMax(true)); - } - - private synchronized CacheValue<K, V> synchGet(CacheKey<K> k) { - return content.get(k); - } - - private synchronized boolean synchPut(K key,V value, long keySizeBytes, long valueSizeBytes) { - // log.info("Put "+key.toString()+ " key size:"+keySizeBytes+" val size:"+valueSizeBytes); - makeRoomForBytes(valueSizeBytes+keySizeBytes); - CacheKey<K> cacheKey = new CacheKey<>(keySizeBytes, key); - CacheValue<K, V> cacheValue; - if (timeToLiveMillis<0) { - cacheValue=new CacheValue<>(valueSizeBytes,value, cacheKey); - } else { - cacheValue=new AgingCacheValue<>(valueSizeBytes,value, cacheKey); - } - currentSizeBytes+=(valueSizeBytes+keySizeBytes); - elems.put(content.size()); - content.put(cacheKey, cacheValue); - return true; - } - - /** - * Attempts to add a value to the cache - * - * @param key the key of the value - * @param value the value to add - * @return true if the value was added, false if it could not be added - */ - public boolean put(K key,V value) { - if (value instanceof Result) { // Optimized for CachingSearcher. Assuming the key is the Query. - long totalSizeBytes = calc.sizeOf(value); // Result has a Query field - if (tooBigToCache(totalSizeBytes)) { - return false; - } - entrySizes.put(totalSizeBytes); - return synchPut(key, value, 0, totalSizeBytes); - } - long keySizeBytes=calc.sizeOf(key); - long valueSizeBytes=calc.sizeOf(value); - if (tooBigToCache(keySizeBytes+valueSizeBytes)) { - return false; - } - entrySizes.put(keySizeBytes+valueSizeBytes); - return synchPut(key, value, keySizeBytes, valueSizeBytes); - } - - /** - * Don't cache elems that are too big, even if there's space - */ - private boolean tooBigToCache(long totalSize) { - if (totalSize > maxEntrySizeBytes) { - return true; - } - if (totalSize > maxSizeBytes) { - return true; - } - return false; - } - - private void makeRoomForBytes(long bytes) { - if ((maxSizeBytes-currentSizeBytes) > bytes) { - return; - } - if (content.isEmpty()) { - return; - } - for (Iterator<Map.Entry<CacheKey<K>, CacheValue<K, V>>> i = content.entrySet().iterator() ; i.hasNext() ; ) { - Map.Entry<CacheKey<K>, CacheValue<K, V>> entry = i.next(); - CacheKey<K> key = entry.getKey(); - CacheValue<K, V> value = entry.getValue(); - // Can't call this.removeField(), breaks iterator. - i.remove(); // Access order: first ones are LRU. - currentSizeBytes-=key.sizeBytes(); - currentSizeBytes-=value.sizeBytes(); - if ((maxSizeBytes-currentSizeBytes) > bytes) { - break; - } - } - } - - public boolean containsKey(K k) { - return content.containsKey(new CacheKey<>(-1, k)); - } - - /** Returns a value, if it is present in the cache */ - public V get(K key) { - // Currently it works to make a new CacheKey object without size - // because we have changed hashCode() there. - CacheKey<K> cacheKey = new CacheKey<>(-1, key); - CacheValue<K, V> value=synchGet(cacheKey); - if (value==null) { - return null; - } - if (timeToLiveMillis<0) { - return value.value(); - } - - if (value.expired(timeToLiveMillis)) { - // There was a value, which has now expired - remove(key); - return null; - } else { - return value.value(); - } - } - - /** - * Removes a cache value if present - * - * @return true if the value was removed, false if it was not present - */ - public synchronized boolean remove(K key) { - CacheValue<K, V> value=content.remove(key); - if (value==null) { - return false; - } - currentSizeBytes-=value.sizeBytes(); - currentSizeBytes-=value.getKey().sizeBytes(); - elems.put(content.size()); - return true; - } - - public int size() { - return content.size(); - } - - private static class CacheKey<K> { - private long sizeBytes; - private K key; - public CacheKey(long sizeBytes,K key) { - this.sizeBytes=sizeBytes; - this.key=key; - } - - public long sizeBytes() { - return sizeBytes; - } - - public K getKey() { - return key; - } - - public int hashCode() { - return key.hashCode(); - } - - @SuppressWarnings("rawtypes") - public boolean equals(Object k) { - if (key==null) { - return false; - } - if (k==null) { - return false; - } - if (k instanceof CacheKey) { - return key.equals(((CacheKey)k).getKey()); - } - return false; - } - - public String toString() { - return key.toString(); - } - - } - - private static class CacheValue<K, V> { - private long sizeBytes; - private V value; - private CacheKey<K> key; - public CacheValue(long sizeBytes, V value, CacheKey<K> key) { - this.sizeBytes=sizeBytes; - this.value=value; - this.key = key; - } - - public boolean expired(long ttl) { - return false; - } - - public V value() { - return value; - } - - public long sizeBytes() { - return sizeBytes; - } - - public CacheKey<K> getKey() { - return key; - } - - public String toString() { - return value.toString(); - } - - } - - private static class AgingCacheValue<K, V> extends CacheValue<K, V> { - private long birthTimeMillis; - - public AgingCacheValue(long sizeBytes,V value, CacheKey<K> key) { - super(sizeBytes,value, key); - this.birthTimeMillis=System.currentTimeMillis(); - } - - public long ageMillis() { - return System.currentTimeMillis()-birthTimeMillis; - } - - public boolean expired(long ttl) { - return (ageMillis() >= ttl); - } - } - -} diff --git a/container-search/src/main/java/com/yahoo/prelude/cache/QueryCacheKey.java b/container-search/src/main/java/com/yahoo/prelude/cache/QueryCacheKey.java deleted file mode 100644 index f627124b6f7..00000000000 --- a/container-search/src/main/java/com/yahoo/prelude/cache/QueryCacheKey.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.prelude.cache; - -import com.yahoo.search.Query; - -public class QueryCacheKey { - private Query query; - private int offset; - private int hits; - - public QueryCacheKey(Query query) { - this.query = query; - this.offset = query.getOffset(); - this.hits = query.getHits(); - } - - public boolean equals(Object key) { - if (key==null) { - return false; - } - if (query==null) { - return false; - } - if (key instanceof QueryCacheKey) { - QueryCacheKey ckey = (QueryCacheKey)key; - boolean res = equalQueryWith(ckey) && equalPathWith(ckey); - return res; - } - return false; - } - - private boolean equalQueryWith(QueryCacheKey other) { - return query.equals(other.getQuery()); - } - - private boolean equalPathWith(QueryCacheKey other) { - if (other == null) return false; - if (other.getQuery() == null) return false; - - return query.getHttpRequest().getUri().getPath().equals(other.getQuery().getHttpRequest().getUri().getPath()); - } - - public int getHits() { - return hits; - } - - public int getOffset() { - return offset; - } - - public Query getQuery() { - return query; - } - - public void setQuery(Query newQuery) { - query = newQuery; - } - - public String toString() { - if (query==null) { - return super.toString(); - } - return query.toString(); - } - - public int hashCode() { - if (query==null) { - return super.hashCode(); - } - int ret = query.hashCode(); - return ret; - } -} diff --git a/container-search/src/main/java/com/yahoo/prelude/searcher/CachingSearcher.java b/container-search/src/main/java/com/yahoo/prelude/searcher/CachingSearcher.java deleted file mode 100644 index f80d6f2e1eb..00000000000 --- a/container-search/src/main/java/com/yahoo/prelude/searcher/CachingSearcher.java +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.prelude.searcher; - -import com.yahoo.component.chain.dependencies.After; -import com.yahoo.component.chain.dependencies.Before; -import com.yahoo.container.QrSearchersConfig; -import com.yahoo.search.Query; -import com.yahoo.search.Result; -import com.yahoo.prelude.cache.Cache; -import com.yahoo.prelude.cache.QueryCacheKey; -import com.yahoo.search.Searcher; -import com.yahoo.processing.request.CompoundName; -import com.yahoo.search.searchchain.Execution; -import com.yahoo.statistics.Statistics; -import com.yahoo.statistics.Value; - -/** - * A generic caching searcher which caches all passing results. - * - * @author vegardh - */ -@After("rawQuery") -@Before("transformedQuery") -public class CachingSearcher extends Searcher { - - private static final CompoundName nocachewrite=new CompoundName("nocachewrite"); - - private Cache<QueryCacheKey, Result> cache; - private Value cacheHitRatio = null; - - public CachingSearcher(QrSearchersConfig config, Statistics manager) { - long maxSizeBytes = config.com().yahoo().prelude().searcher().CachingSearcher().cachesizemegabytes()*1024*1024; - long timeToLiveMillis = config.com().yahoo().prelude().searcher().CachingSearcher().timetoliveseconds()*1000; - long maxEntrySizeBytes = config.com().yahoo().prelude().searcher().CachingSearcher().maxentrysizebytes(); - cache=new Cache<>(maxSizeBytes, timeToLiveMillis, maxEntrySizeBytes, manager); - initRatio(manager); - } - - private void initRatio(Statistics manager) { - cacheHitRatio = new Value("querycache_hit_ratio", manager, - new Value.Parameters().setNameExtension(false).setLogRaw(false).setLogMean(true)); - } - - private synchronized void cacheHit() { - cacheHitRatio.put(1.0d); - } - - private synchronized void cacheMiss() { - cacheHitRatio.put(0.0d); - } - - private boolean noCacheWrite(Query query) { - return query.properties().getBoolean(nocachewrite); - } - - public Result search(com.yahoo.search.Query query, Execution execution) { - if (query.getNoCache()) { - return execution.search(query); - } - QueryCacheKey queryKey = new QueryCacheKey(query); - Result cachedResult=cache.get(queryKey); - if (cachedResult!=null) { - cacheHit(); - return cachedResult; - } - cacheMiss(); - Query originalQuery = query.clone(); // Need a copy, as cache hash key later on, maybe. - Result result = execution.search(query); - execution.fill(result); - if (!noCacheWrite(query)) { - queryKey.setQuery(originalQuery); // Because the query member has changed state - cache.put(queryKey,result); - } - return result; - } - -} diff --git a/container-search/src/test/java/com/yahoo/prelude/cache/test/CacheTestCase.java b/container-search/src/test/java/com/yahoo/prelude/cache/test/CacheTestCase.java deleted file mode 100644 index 5d7048f05ea..00000000000 --- a/container-search/src/test/java/com/yahoo/prelude/cache/test/CacheTestCase.java +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.prelude.cache.test; - -import com.yahoo.search.result.Hit; -import com.yahoo.search.Query; -import com.yahoo.search.Result; -import com.yahoo.statistics.Statistics; -import com.yahoo.prelude.cache.Cache; -import com.yahoo.prelude.cache.QueryCacheKey; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class CacheTestCase { - - private Result getSomeResult(Query q, String id) { - Result r = new Result(q); - r.hits().add(new Hit(id, 10)); - return r; - } - - @Test - public void testBasicGet() { - Cache<QueryCacheKey, Result> cache=new Cache<>(100*1024,3600, 100000, Statistics.nullImplementation); - Query q = new Query("/std_xmls_a00?hits=5&offset=5&query=flowers+shop&tracelevel=4&objid=ffffffffffffffff"); - Query q2 = new Query("/std_xmls_a00?hits=5&offset=5&query=flowers+shop&tracelevel=4&objid=ffffffffffffffff"); - QueryCacheKey qk = new QueryCacheKey(q); - QueryCacheKey qk2 = new QueryCacheKey(q2); - Result r = getSomeResult(q, "foo"); - Result r2 = getSomeResult(q, "bar"); - assertNull(cache.get(qk)); - cache.put(qk, r); - assertNotNull(cache.get(qk)); - assertEquals(cache.get(qk), r); - cache.put(qk2, r); - assertEquals(cache.get(qk2), r); - cache.put(qk, r2); - assertEquals(cache.get(qk), r2); - } - - @Test - public void testPutTooLarge() { - byte[] tenKB = new byte[10*1024]; - for (int i = 0 ; i <10*1024 ; i++) { - tenKB[i]=127; - } - byte[] sevenKB = new byte[7*1024]; - for (int i = 0 ; i <7*1024 ; i++) { - sevenKB[i]=127; - } - Cache cache=new Cache(9*1024,3600, 100*1024, Statistics.nullImplementation); // 9 KB - assertFalse(cache.put("foo", tenKB)); - assertTrue(cache.put("foo", sevenKB)); - assertEquals(cache.get("foo"), sevenKB); - } - - @Test - public void testInvalidate() { - byte[] tenKB = new byte[10*1024]; - for (int i = 0 ; i <10*1024 ; i++) { - tenKB[i]=127; - } - byte[] sevenKB = new byte[7*1024]; - for (int i = 0 ; i <7*1024 ; i++) { - sevenKB[i]=127; - } - Cache cache=new Cache(11*1024,3600, 100*1024, Statistics.nullImplementation); // 11 KB - assertTrue(cache.put("foo", sevenKB)); - assertTrue(cache.put("bar", tenKB)); - assertNull(cache.get("foo")); - assertEquals(cache.get("bar"), tenKB); - } - - @Test - public void testInvalidateLRU() { - Cache cache=new Cache(10*1024,3600, 100*1024, Statistics.nullImplementation); // 10 MB - byte[] fiveKB = new byte[5*1024]; - for (int i = 0 ; i <5*1024 ; i++) { - fiveKB[i]=127; - } - - byte[] twoKB = new byte[2*1024]; - for (int i = 0 ; i <2*1024 ; i++) { - twoKB[i]=127; - } - - byte[] fourKB = new byte[4*1024]; - for (int i = 0 ; i <4*1024 ; i++) { - fourKB[i]=127; - } - assertTrue(cache.put("five", fiveKB)); - assertTrue(cache.put("two", twoKB)); - Object dummy = cache.get("five"); // Makes two LRU - assertEquals(dummy, fiveKB); - assertTrue(cache.put("four", fourKB)); - assertNull(cache.get("two")); - assertEquals(cache.get("five"), fiveKB); - assertEquals(cache.get("four"), fourKB); - - // Same, without the access, just to check - cache=new Cache(10*1024,3600, 100*1024, Statistics.nullImplementation); // 10 KB - assertTrue(cache.put("five", fiveKB)); - assertTrue(cache.put("two", twoKB)); - assertTrue(cache.put("four", fourKB)); - assertEquals(cache.get("two"), twoKB); - assertNull(cache.get("five")); - assertEquals(cache.get("four"), fourKB); - } - - @Test - public void testPutSameKey() { - Cache cache=new Cache(10*1024,3600, 100*1024, Statistics.nullImplementation); // 10 MB - byte[] fiveKB = new byte[5*1024]; - for (int i = 0 ; i <5*1024 ; i++) { - fiveKB[i]=127; - } - - byte[] twoKB = new byte[2*1024]; - for (int i = 0 ; i <2*1024 ; i++) { - twoKB[i]=127; - } - - byte[] fourKB = new byte[4*1024]; - for (int i = 0 ; i <4*1024 ; i++) { - fourKB[i]=127; - } - assertTrue(cache.put("five", fiveKB)); - assertTrue(cache.put("two", twoKB)); - assertEquals(cache.get("two"), twoKB); - assertEquals(cache.get("five"), fiveKB); - assertTrue(cache.put("five", twoKB)); - assertEquals(cache.get("five"), twoKB); - assertEquals(cache.get("two"), twoKB); - } - - @Test - public void testExpire() throws InterruptedException { - Cache cache=new Cache(10*1024,50, 10000, Statistics.nullImplementation); // 10 KB, 50ms expire - boolean success = false; - for (int tries = 0; tries < 10; tries++) { - long before = System.currentTimeMillis(); - cache.put("foo", "bar"); - cache.put("hey", "ho"); - Object got1 = cache.get("foo"); - Object got2 = cache.get("hey"); - long after = System.currentTimeMillis(); - if (after - before < 50) { - assertEquals(got1, "bar"); - assertEquals(got2, "ho"); - success = true; - break; - } - } - assertTrue(success); - Thread.sleep(100); - assertNull(cache.get("foo")); - assertNull(cache.get("hey")); - } - - @Test - public void testInsertSame() { - Cache cache=new Cache(100*1024,500, 100000, Statistics.nullImplementation); // 100 KB, .5 sec expire - Query q = new Query("/std_xmls_a00?hits=5&offset=5&query=flowers+shop&tracelevel=4&objid=ffffffffffffffff"); - Result r = getSomeResult(q, "foo"); - QueryCacheKey k = new QueryCacheKey(q); - cache.put(k, r); - assertEquals(1, cache.size()); - q = new Query("/std_xmls_a00?hits=5&offset=5&query=flowers+shop&tracelevel=4&objid=ffffffffffffffff"); - k = new QueryCacheKey(q); - cache.put(k, r); - assertEquals(1, cache.size()); - } - - @Test - public void testMaxSize() { - Cache cache=new Cache(20*1024,500, 3*1024, Statistics.nullImplementation); - byte[] fourKB = new byte[4*1024]; - for (int i = 0 ; i <4*1024 ; i++) { - fourKB[i]=127; - } - byte[] twoKB = new byte[2*1024]; - for (int i = 0 ; i <2*1024 ; i++) { - twoKB[i]=127; - } - assertFalse(cache.put("four", fourKB)); - assertTrue(cache.put("two", twoKB)); - assertNull(cache.get("four")); - assertNotNull(cache.get("two")); - } - -} diff --git a/container-search/src/test/java/com/yahoo/prelude/searcher/test/CachingSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/searcher/test/CachingSearcherTestCase.java deleted file mode 100644 index 570402fdaae..00000000000 --- a/container-search/src/test/java/com/yahoo/prelude/searcher/test/CachingSearcherTestCase.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.prelude.searcher.test; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.yahoo.component.chain.Chain; -import com.yahoo.container.QrSearchersConfig; -import com.yahoo.prelude.fastsearch.FastHit; -import com.yahoo.prelude.searcher.CachingSearcher; -import com.yahoo.prelude.searcher.DocumentSourceSearcher; -import com.yahoo.search.Query; -import com.yahoo.search.Result; -import com.yahoo.search.Searcher; -import com.yahoo.search.searchchain.Execution; -import com.yahoo.statistics.Statistics; - -/** - * Check CachingSearcher basically works. - * - * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> - */ -public class CachingSearcherTestCase { - - private static final String QUERY_A_NOCACHEWRITE_TRUE = "/?query=a&nocachewrite=true"; - private static final String QUERY_A = "/?query=a"; - private Chain<Searcher> searchChain; - private DocumentSourceSearcher hits; - - @Before - public void setUp() throws Exception { - hits = new DocumentSourceSearcher(); - QrSearchersConfig config = new QrSearchersConfig( - new QrSearchersConfig.Builder() - .com(new QrSearchersConfig.Com.Builder() - .yahoo(new QrSearchersConfig.Com.Yahoo.Builder() - .prelude(new QrSearchersConfig.Com.Yahoo.Prelude.Builder() - .searcher(new QrSearchersConfig.Com.Yahoo.Prelude.Searcher.Builder() - .CachingSearcher( - new QrSearchersConfig.Com.Yahoo.Prelude.Searcher.CachingSearcher.Builder() - .cachesizemegabytes(10) - .maxentrysizebytes(5 * 1024 * 1024) - .timetoliveseconds(86400))))))); - CachingSearcher cache = new CachingSearcher(config, Statistics.nullImplementation); - searchChain = new Chain<>(cache, hits); - } - - public void readyResult(String q) { - Query query = new Query(q); - Result r = new Result(query); - for (int i = 0; i < 10; ++i) { - FastHit h = new FastHit("http://127.0.0.1/" + i, - 1.0 - ((double) i) / 10.0); - r.hits().add(h); - } - hits.addResultSet(query, r); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public final void test() { - readyResult(QUERY_A); - Execution e = new Execution(searchChain, Execution.Context.createContextStub()); - Result r = e.search(new Query(QUERY_A)); - assertEquals(10, r.hits().getConcreteSize()); - Query query = new Query(QUERY_A); - Result expected = new Result(query); - hits.addResultSet(query, expected); - e = new Execution(searchChain, Execution.Context.createContextStub()); - r = e.search(new Query(QUERY_A)); - assertEquals(10, r.hits().getConcreteSize()); - assertEquals(1, hits.getQueryCount()); - } - - @Test - public final void testNoCacheWrite() { - readyResult(QUERY_A_NOCACHEWRITE_TRUE); - Execution e = new Execution(searchChain, Execution.Context.createContextStub()); - Result r = e.search(new Query(QUERY_A_NOCACHEWRITE_TRUE)); - assertEquals(10, r.hits().getConcreteSize()); - Query query = new Query(QUERY_A_NOCACHEWRITE_TRUE); - Result expected = new Result(query); - hits.addResultSet(query, expected); - e = new Execution(searchChain, Execution.Context.createContextStub()); - r = e.search(new Query(QUERY_A_NOCACHEWRITE_TRUE)); - assertEquals(0, r.hits().getConcreteSize()); - assertEquals(2, hits.getQueryCount()); - } - -} diff --git a/vespajlib/src/main/java/com/yahoo/cache/Cache.java b/vespajlib/src/main/java/com/yahoo/cache/Cache.java deleted file mode 100644 index af3bb7db21b..00000000000 --- a/vespajlib/src/main/java/com/yahoo/cache/Cache.java +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.cache; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * <p>A generic cache which keeps the total memory consumed by its content - * below a configured maximum.</p> - * - * <p>Thread safe.</p> - * - * @author vegardh - */ -public class Cache<K, V> { - private Map<CacheKey<K>,CacheValue<K, V>> content=new LinkedHashMap<>(12500, 1.0f, true); - private SizeCalculator calc = new SizeCalculator(); - private long maxSizeBytes; - - private long currentSizeBytes=0; - - /** The time an element is allowed to live, negative for indefinite lifespan */ - private long timeToLiveMillis=-1; - - /** The max allowed size of an entry, negative for no limit */ - private long maxEntrySizeBytes=10000; - - /** - * Creates a new cache - * - * @param maxSizeBytes the max size in bytes this cache is permitted to consume, - * including Result objects and Query keys - * @param timeToLiveMillis a negative value means unlimited time - * @param maxEntrySizeBytes never cache objects bigger than this, negative for no such limit - */ - public Cache(long maxSizeBytes,long timeToLiveMillis, long maxEntrySizeBytes) { - this.maxSizeBytes=maxSizeBytes; - this.timeToLiveMillis=timeToLiveMillis; - this.maxEntrySizeBytes=maxEntrySizeBytes; - } - - private synchronized CacheValue<K, V> synchGet(CacheKey<K> k) { - return content.get(k); - } - - private synchronized boolean synchPut(K key,V value, long keySizeBytes, long valueSizeBytes) { - // log.info("Put "+key.toString()+ " key size:"+keySizeBytes+" val size:"+valueSizeBytes); - if ((valueSizeBytes+keySizeBytes)>maxSizeBytes) { - return false; - } - makeRoomForBytes(valueSizeBytes+keySizeBytes); - CacheKey<K> cacheKey = new CacheKey<>(keySizeBytes, key); - CacheValue<K, V> cacheValue; - if (timeToLiveMillis<0) { - cacheValue=new CacheValue<>(valueSizeBytes,value, cacheKey); - } else { - cacheValue=new AgingCacheValue<>(valueSizeBytes,value, cacheKey); - } - currentSizeBytes+=(valueSizeBytes+keySizeBytes); - content.put(cacheKey, cacheValue); - return true; - } - - /** - * Attempts to add a value to the cache - * - * @param key the key of the value - * @param value the value to add - * @return true if the value was added, false if it could not be added - */ - public boolean put(K key,V value) { - long keySizeBytes=calc.sizeOf(key); - long valueSizeBytes=calc.sizeOf(value); - if (tooBigToCache(keySizeBytes+valueSizeBytes)) { - return false; - } - return synchPut(key, value, keySizeBytes, valueSizeBytes); - } - - /** - * Don't cache elems that are too big, even if there's space - * @return true if the argument is too big to cache. - */ - private boolean tooBigToCache(long totalSize) { - if (maxEntrySizeBytes<0) { - return false; - } - if (totalSize > maxEntrySizeBytes) { - return true; - } - return false; - } - - private void makeRoomForBytes(long bytes) { - if ((maxSizeBytes-currentSizeBytes) > bytes) { - return; - } - if (content.isEmpty()) { - return; - } - for (Iterator<Map.Entry<CacheKey<K>, CacheValue<K, V>>> i = content.entrySet().iterator() ; i.hasNext() ; ) { - Map.Entry<CacheKey<K>, CacheValue<K, V>> entry = i.next(); - CacheKey<K> key = entry.getKey(); - CacheValue<K, V> value = entry.getValue(); - // Can't call this.remove(), breaks iterator. - i.remove(); // Access order: first ones are LRU. - currentSizeBytes-=key.sizeBytes(); - currentSizeBytes-=value.sizeBytes(); - if ((maxSizeBytes-currentSizeBytes) > bytes) { - break; - } - } - } - - public boolean containsKey(K k) { - return content.containsKey(new CacheKey<>(-1, k)); - } - - /** Returns a value, if it is present in the cache */ - public V get(K key) { - // Currently it works to make a new CacheKey object without size - // because we have changed hashCode() there. - CacheKey<K> cacheKey = new CacheKey<>(-1, key); - CacheValue<K, V> value=synchGet(cacheKey); - if (value==null) { - return null; - } - if (timeToLiveMillis<0) { - return value.value(); - } - - if (value.expired(timeToLiveMillis)) { - // There was a value, which has now expired - remove(key); - return null; - } else { - return value.value(); - } - } - - /** - * Removes a cache value if present - * - * @return true if the value was removed, false if it was not present - */ - public synchronized boolean remove(K key) { - CacheValue<K, V> value=content.remove(key); - if (value==null) { - return false; - } - currentSizeBytes-=value.sizeBytes(); - currentSizeBytes-=value.getKey().sizeBytes(); - return true; - } - - public long getTimeToLiveMillis() { - return timeToLiveMillis; - } - - public int size() { - return content.size(); - } - - private static class CacheKey<K> { - private long sizeBytes; - private K key; - public CacheKey(long sizeBytes,K key) { - this.sizeBytes=sizeBytes; - this.key=key; - } - - public long sizeBytes() { - return sizeBytes; - } - - public K getKey() { - return key; - } - - public int hashCode() { - return key.hashCode(); - } - - @SuppressWarnings("rawtypes") - public boolean equals(Object k) { - if (key==null) { - return false; - } - if (k==null) { - return false; - } - if (k instanceof CacheKey) { - return key.equals(((CacheKey)k).getKey()); - } - return false; - } - } - - private static class CacheValue<K, V> { - private long sizeBytes; - private V value; - private CacheKey<K> key; - public CacheValue(long sizeBytes, V value, CacheKey<K> key) { - this.sizeBytes=sizeBytes; - this.value=value; - this.key = key; - } - - public boolean expired(long ttl) { - return false; - } - - public V value() { - return value; - } - - public long sizeBytes() { - return sizeBytes; - } - - public CacheKey<K> getKey() { - return key; - } - } - - private static class AgingCacheValue<K, V> extends CacheValue<K, V> { - private long birthTimeMillis; - - public AgingCacheValue(long sizeBytes,V value, CacheKey<K> key) { - super(sizeBytes,value, key); - this.birthTimeMillis=System.currentTimeMillis(); - } - - public long ageMillis() { - return System.currentTimeMillis()-birthTimeMillis; - } - - public boolean expired(long ttl) { - return (ageMillis() >= ttl); - } - } - - /** - * Empties the cache - */ - public synchronized void clear() { - content.clear(); - currentSizeBytes=0; - } - - /** - * Collection of keys. - */ - public Collection<K> getKeys() { - Collection<K> ret = new ArrayList<>(); - for (Iterator<CacheKey<K>> i = content.keySet().iterator(); i.hasNext();) { - ret.add(i.next().getKey()); - } - return ret; - } - - /** - * Collection of values. - */ - public Collection<V> getValues() { - Collection<V> ret = new ArrayList<>(); - for (Iterator<CacheValue<K, V>> i = content.values().iterator(); i.hasNext();) { - ret.add(i.next().value()); - } - return ret; - } - -} diff --git a/vespajlib/src/main/java/com/yahoo/cache/SizeCalculator.java b/vespajlib/src/main/java/com/yahoo/cache/SizeCalculator.java deleted file mode 100644 index e062ad8783f..00000000000 --- a/vespajlib/src/main/java/com/yahoo/cache/SizeCalculator.java +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.cache; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; - -/** - * Size calculator for objects. - * Thread safe. - * @author vegardh - * @see <a href="http://www.javaspecialists.co.za/archive/Issue078.html">MemoryCounter by Dr H M Kabutz</a> - */ -public class SizeCalculator { - - private static class ObjectSet { - private final Map<Object, Object> map = new IdentityHashMap<>(); - - public boolean had(Object obj) { - if (map.containsKey(obj)) { - return true; - } - map.put(obj, null); - return false; - } - } - - private int getPointerSize() { - return 4; - } - - private int getClassSize() { - return 8; - } - - private int getArraySize() { - return 16; - } - - @SuppressWarnings("serial") - private final IdentityHashMap<Class<?>, Integer> primitiveSizes = new IdentityHashMap<Class<?>, Integer>() { - { - put(boolean.class, 1); - put(byte.class, 1); - put(char.class, 2); - put(short.class, 2); - put(int.class, 4); - put(float.class, 4); - put(double.class, 8); - put(long.class, 8); - } - }; - - // Only called on un-visited objects and only with array. - private long sizeOfArray(Object a, ObjectSet visitedObjects) { - long sum = getArraySize(); - int length = Array.getLength(a); - if (length == 0) { - return sum; - } - Class<?> elementClass = a.getClass().getComponentType(); - if (elementClass.isPrimitive()) { - sum += length * (primitiveSizes.get(elementClass)); - return sum; - } else { - for (int i = 0; i < length; i++) { - Object val = Array.get(a, i); - sum += getPointerSize(); - sum += sizeOfObject(val, visitedObjects); - } - return sum; - } - } - - private long getSumOfFields(Class<?> clas, Object obj, - ObjectSet visitedObjects) { - long sum = 0; - Field[] fields = clas.getDeclaredFields(); - for (Field field : fields) { - if (!Modifier.isStatic(field.getModifiers())) { - if (field.getType().isPrimitive()) { - sum += primitiveSizes.get(field.getType()); - } else { - sum += getPointerSize(); - field.setAccessible(true); - try { - sum += sizeOfObject(field.get(obj), visitedObjects); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - } - } - return sum; - } - - // Skip literal strings - private boolean isIntern(Object obj) { - if (obj instanceof String) { - if (obj == ((String) obj).intern()) { - return true; - } - } - return false; - } - - // Only called on non-visited non-arrays. - private long sizeOfNonArray(Class<?> clas, Object obj, - ObjectSet visitedObjects) { - if (isIntern(obj)) { - return 0; - } - long sum = getClassSize(); - while (clas != null) { - sum += getSumOfFields(clas, obj, visitedObjects); - clas = clas.getSuperclass(); - } - return sum; - } - - private long sizeOfObject(Object obj, ObjectSet visitedObjects) { - if (obj == null) { - return 0; - } - if (visitedObjects.had(obj)) { - return 0; - } - Class<?> clas = obj.getClass(); - if (clas.isArray()) { - return sizeOfArray(obj, visitedObjects); - } - return sizeOfNonArray(clas, obj, visitedObjects); - } - - /** - * Returns the heap size of an object/array - * - * @return Number of bytes for object, approximately - */ - public long sizeOf(Object value) { - ObjectSet visitedObjects = new ObjectSet(); - return sizeOfObject(value, visitedObjects); - } - - /** - * Returns the heap size of two objects/arrays, common objects counted only - * once - * - * @return Number of bytes for objects, approximately - */ - public long sizeOf(Object value1, Object value2) { - ObjectSet visitedObjects = new ObjectSet(); - return sizeOfObject(value1, visitedObjects) - + sizeOfObject(value2, visitedObjects); - } - - /** - * The approximate size in bytes for a list of objects, viewed as a closure, - * ie. common objects are counted only once. - * - * @return total number of bytes - */ - public long sizeOf(List<?> objects) { - ObjectSet visitedObjects = new ObjectSet(); - long sum = 0; - for (Object o : objects) { - sum += sizeOfObject(o, visitedObjects); - } - return sum; - } - -} diff --git a/vespajlib/src/test/java/com/yahoo/cache/CacheTestCase.java b/vespajlib/src/test/java/com/yahoo/cache/CacheTestCase.java deleted file mode 100644 index 8f14016b542..00000000000 --- a/vespajlib/src/test/java/com/yahoo/cache/CacheTestCase.java +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.cache; - -import junit.framework.TestCase; - -import java.util.ArrayList; -import java.util.Collection; - -public class CacheTestCase extends TestCase { - - public void testBasicGet() { - Cache<String, String> cache = new Cache<>(100 * 1024 * 1024, 3600, 10000); - String q = "/std_xmls_a00?hits=5&offset=5&query=flowers+shop&tracelevel=4&objid=ffffffffffffffff"; - String q2 = "/std_xmls_a00?hits=5&offset=5&query=flowers+shop&tracelevel=4&objid=ffffffffffffffff"; - String r = "result"; - String r2 = "result2"; - assertNull(cache.get(q)); - cache.put(q, r); - assertNotNull(cache.get(q)); - assertEquals(cache.get(q), r); - cache.put(q2, r); - assertEquals(cache.get(q2), r); - cache.put(q, r2); - assertEquals(cache.get(q), r2); - } - - public void testPutTooLarge() { - byte[] tenMB = new byte[10*1024*1024]; - for (int i = 0 ; i <10*1024*1024 ; i++) { - tenMB[i]=127; - } - byte[] sevenMB = new byte[7*1024*1024]; - for (int i = 0 ; i <7*1024*1024 ; i++) { - sevenMB[i]=127; - } - Cache<String, byte[]> cache=new Cache<>(9*1024*1024,3600, 100*1024*1024); // 9 MB - assertFalse(cache.put("foo", tenMB)); - assertTrue(cache.put("foo", sevenMB)); - assertEquals(cache.get("foo"), sevenMB); - } - - public void testInvalidate() { - byte[] tenMB = new byte[10*1024*1024]; - for (int i = 0 ; i <10*1024*1024 ; i++) { - tenMB[i]=127; - } - byte[] sevenMB = new byte[7*1024*1024]; - for (int i = 0 ; i <7*1024*1024 ; i++) { - sevenMB[i]=127; - } - //log.info("10 MB: "+calc.sizeOf(tenMB)); - //log.info("7 MB: "+calc.sizeOf(sevenMB)); - Cache<String, byte[]> cache=new Cache<>(11*1024*1024,3600, 100*1024*1024); // 11 MB - assertTrue(cache.put("foo", sevenMB)); - assertTrue(cache.put("bar", tenMB)); - assertNull(cache.get("foo")); - assertEquals(cache.get("bar"), tenMB); - } - - public void testInvalidateLRU() { - Cache<String, byte[]> cache=new Cache<>(10*1024*1024,3600, 100*1024*1024); // 10 MB - byte[] fiveMB = new byte[5*1024*1024]; - for (int i = 0 ; i <5*1024*1024 ; i++) { - fiveMB[i]=127; - } - - byte[] twoMB = new byte[2*1024*1024]; - for (int i = 0 ; i <2*1024*1024 ; i++) { - twoMB[i]=127; - } - - byte[] fourMB = new byte[4*1024*1024]; - for (int i = 0 ; i <4*1024*1024 ; i++) { - fourMB[i]=127; - } - assertTrue(cache.put("five", fiveMB)); - assertTrue(cache.put("two", twoMB)); - Object dummy = cache.get("five"); // Makes two LRU - assertEquals(dummy, fiveMB); - assertTrue(cache.put("four", fourMB)); - assertNull(cache.get("two")); - assertEquals(cache.get("five"), fiveMB); - assertEquals(cache.get("four"), fourMB); - - // Same, without the access, just to check - cache=new Cache<>(10*1024*1024,3600, 100*1024*1024); // 10 MB - assertTrue(cache.put("five", fiveMB)); - assertTrue(cache.put("two", twoMB)); - assertTrue(cache.put("four", fourMB)); - assertEquals(cache.get("two"), twoMB); - assertNull(cache.get("five")); - assertEquals(cache.get("four"), fourMB); - } - - public void testPutSameKey() { - Cache<String, byte[]> cache=new Cache<>(10*1024*1024,3600, 100*1024*1024); // 10 MB - byte[] fiveMB = new byte[5*1024*1024]; - for (int i = 0 ; i <5*1024*1024 ; i++) { - fiveMB[i]=127; - } - - byte[] twoMB = new byte[2*1024*1024]; - for (int i = 0 ; i <2*1024*1024 ; i++) { - twoMB[i]=127; - } - - byte[] fourMB = new byte[4*1024*1024]; - for (int i = 0 ; i <4*1024*1024 ; i++) { - fourMB[i]=127; - } - assertTrue(cache.put("five", fiveMB)); - assertTrue(cache.put("two", twoMB)); - assertEquals(cache.get("two"), twoMB); - assertEquals(cache.get("five"), fiveMB); - assertTrue(cache.put("five", twoMB)); - assertEquals(cache.get("five"), twoMB); - assertEquals(cache.get("two"), twoMB); - } - - public void testExpire() throws InterruptedException { - Cache<String, String> cache=new Cache<>(10*1024*1024,400, 10000); // 10 MB, .4 sec expire - cache.put("foo", "bar"); - cache.put("hey", "ho"); - assertEquals(cache.get("foo"), "bar"); - assertEquals(cache.get("hey"), "ho"); - Thread.sleep(600); - assertNull(cache.get("foo")); - assertNull(cache.get("hey")); - } - - public void testInsertSame() { - Cache<String, String> cache=new Cache<>(10*1024*1024,500, 10000); // 10 MB, .5 sec expire - String k = "foo"; - String r = "bar"; - cache.put(k, r); - assertEquals(cache.size(), 1); - cache.put(k, r); - assertEquals(cache.size(), 1); - } - - public void testMaxSize() { - Cache<String, byte[]> cache=new Cache<>(20*1024*1024,500, 3*1024*1024); - byte[] fourMB = new byte[4*1024*1024]; - for (int i = 0 ; i <4*1024*1024 ; i++) { - fourMB[i]=127; - } - byte[] twoMB = new byte[2*1024*1024]; - for (int i = 0 ; i <2*1024*1024 ; i++) { - twoMB[i]=127; - } - assertFalse(cache.put("four", fourMB)); - assertTrue(cache.put("two", twoMB)); - assertNull(cache.get("four")); - assertNotNull(cache.get("two")); - } - - public void testMaxSizeNoLimit() { - Cache<String, byte[]> cache=new Cache<>(20*1024*1024,500, -1); - byte[] fourMB = new byte[4*1024*1024]; - for (int i = 0 ; i <4*1024*1024 ; i++) { - fourMB[i]=127; - } - byte[] twoMB = new byte[2*1024*1024]; - for (int i = 0 ; i <2*1024*1024 ; i++) { - twoMB[i]=127; - } - assertTrue(cache.put("four", fourMB)); - assertTrue(cache.put("two", twoMB)); - assertNotNull(cache.get("four")); - assertNotNull(cache.get("two")); - } - - public void testGetKeysAndValuesAndClear() { - Cache<String, String> cache=new Cache<>(10*1024*1024,500, 10000); // 10 MB, .5 sec expire - assertEquals(cache.getKeys().size(), 0); - assertEquals(cache.getValues().size(), 0); - cache.put("a", "b"); - cache.put("c", "d"); - cache.put("e", "f"); - Collection<String> keys = new ArrayList<>(); - keys.add("a"); - keys.add("c"); - keys.add("e"); - Collection<String> values = new ArrayList<>(); - values.add("b"); - values.add("d"); - values.add("f"); - assertEquals(cache.getKeys().size(), 3); - assertEquals(cache.getValues().size(), 3); - assertTrue(cache.getKeys().containsAll(keys)); - assertTrue(cache.getValues().containsAll(values)); - cache.clear(); - assertEquals(cache.getKeys().size(), 0); - assertEquals(cache.getValues().size(), 0); - } - -} diff --git a/vespajlib/src/test/java/com/yahoo/cache/CalcTestCase.java b/vespajlib/src/test/java/com/yahoo/cache/CalcTestCase.java deleted file mode 100644 index 6d9a6b6f422..00000000000 --- a/vespajlib/src/test/java/com/yahoo/cache/CalcTestCase.java +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.cache; - -import java.util.ArrayList; -import java.util.List; - -import static java.lang.Boolean.TRUE; - -public class CalcTestCase extends junit.framework.TestCase { - - private SizeCalculator calc; - - - public CalcTestCase (String name) { - super(name); - } - - public void setUp() { - calc = new SizeCalculator(); - } - - public void testCalc1() { - assertEquals(calc.sizeOf(new Object()), 8); - } - - public void testCalc2() { - assertEquals(calc.sizeOf(new SixtyFourBooleans()), 8+64); - } - - public void testBoolean() { - assertEquals(8+1, calc.sizeOf(TRUE)); - } - - public void testArrayPrimitive() { - byte[] eightBytes = new byte[]{1,1,1,1,1,1,1,1,}; - assertEquals(16+8, calc.sizeOf(eightBytes)); - } - - public void testArrayObjects() { - SixtyFourBooleans[] bunchOfBooleans = new SixtyFourBooleans[]{new SixtyFourBooleans(), - new SixtyFourBooleans(), new SixtyFourBooleans()}; - assertEquals(16+(3*(8+64)+(3*4)), calc.sizeOf(bunchOfBooleans)); - - } - - public void testSizeOfList() { - SixtyFourBooleans sfb = new SixtyFourBooleans(); - List<Object> dupList1 = new ArrayList<>(); - dupList1.add(new Object()); - dupList1.add(sfb); - dupList1.add(sfb); - dupList1.add(sfb); - List<Object> dupList2 = new ArrayList<>(); - dupList2.addAll(dupList1); - dupList2.add(sfb); - dupList2.add(sfb); - dupList2.add(sfb); - dupList2.add(new Object()); - dupList2.add(new Object()); - assertEquals(calc.sizeOf(dupList2), calc.sizeOf(dupList1)+8+8); - } - - public void testSizeOfTuple() { - SixtyFourBooleans[] bunchOfBooleans = new SixtyFourBooleans[]{new SixtyFourBooleans(), - new SixtyFourBooleans(), new SixtyFourBooleans()}; - SixtyFourBooleans[] bunchOfBooleans2 = new SixtyFourBooleans[]{new SixtyFourBooleans(), - new SixtyFourBooleans(), new SixtyFourBooleans()}; - assertEquals(16+(3*(8+64)+(3*4)), calc.sizeOf(bunchOfBooleans)); - assertEquals(2* (16+(3*(8+64)+(3*4))), calc.sizeOf(bunchOfBooleans, bunchOfBooleans2)); - } - - /*public void testEmptyArrayList() { - assertEquals(80, calc.sizeOf(new ArrayList())); - }*/ - - /*public void testFullArrayList() { - ArrayList arrayList = new ArrayList(10000); - - for (int i = 0; i < 10000; i++) { - arrayList.add(new Object()); - } - - assertEquals(120040, calc.sizeOf(arrayList)); - }*/ - - /*public void testHashMap() { - assertEquals(120, calc.sizeOf(new HashMap())); - - Byte[] all = new Byte[256]; - for (int i = -128; i < 128; i++) { - all[i + 128] = new Byte((byte) i); - } - assertEquals(5136, calc.sizeOf(all)); - - HashMap hm = new HashMap(); - for (int i = -128; i < 128; i++) { - hm.put("" + i, new Byte((byte) i)); - } - assertEquals(30776, calc.sizeOf(hm)); - }*/ - - /*public void testThousandBooleansObjects() { - Boolean[] booleans = new Boolean[1000]; - - for (int i = 0; i < booleans.length; i++) - booleans[i] = new Boolean(true); - - assertEquals(20016, calc.sizeOf(booleans)); - }*/ - - @SuppressWarnings("unused") - private static class SixtyFourBooleans { - boolean a0; - boolean a1; - boolean a2; - boolean a3; - boolean a4; - boolean a5; - boolean a6; - boolean a7; - boolean b0; - boolean b1; - boolean b2; - boolean b3; - boolean b4; - boolean b5; - boolean b6; - boolean b7; - boolean c0; - boolean c1; - boolean c2; - boolean c3; - boolean c4; - boolean c5; - boolean c6; - boolean c7; - boolean d0; - boolean d1; - boolean d2; - boolean d3; - boolean d4; - boolean d5; - boolean d6; - boolean d7; - boolean e0; - boolean e1; - boolean e2; - boolean e3; - boolean e4; - boolean e5; - boolean e6; - boolean e7; - boolean f0; - boolean f1; - boolean f2; - boolean f3; - boolean f4; - boolean f5; - boolean f6; - boolean f7; - boolean g0; - boolean g1; - boolean g2; - boolean g3; - boolean g4; - boolean g5; - boolean g6; - boolean g7; - boolean h0; - boolean h1; - boolean h2; - boolean h3; - boolean h4; - boolean h5; - boolean h6; - boolean h7; - } -} |