View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.store;
18  
19  import net.sf.ehcache.Element;
20  import net.sf.ehcache.MemoryStoreTester;
21  import org.junit.Before;
22  import org.junit.Ignore;
23  import org.junit.Test;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import static junit.framework.Assert.assertTrue;
28  import static org.junit.Assert.assertEquals;
29  import static org.junit.Assert.assertNull;
30  
31  
32  /***
33   * Test cases for the LruMemoryStore.
34   * <p/>
35   * There are no tests of expiry because this is handled by {@link net.sf.ehcache.Cache#get}
36   * <p/>
37   * <b>Performance:</b>
38   * v1.38 of DiskStore
39   * INFO: Time for benhmarkPutGetSurya: 7355
40   * INFO: Time for Bulk Load: 13
41   * INFO: Time for benhmarkPutGetRemove: 264
42   * INFO: Time for benhmarkPutGet: 154
43   * <p/>
44   * v 1.42 of DiskStore
45   * INFO: Time for Bulk Load: 12
46   * INFO: Time for benhmarkPutGetRemove: 256
47   * INFO: Time for benhmarkPutGet: 165
48   *
49   * @author Greg Luck
50   * @version $Id: LruMemoryStoreTest.html 13146 2011-08-01 17:12:39Z oletizi $
51   */
52  public class LruMemoryStoreTest extends MemoryStoreTester {
53  
54      private static final Logger LOG = LoggerFactory.getLogger(LruMemoryStoreTest.class.getName());
55  
56      /***
57       * setup test
58       */
59      @Override
60      @Before
61      public void setUp() throws Exception {
62  
63          super.setUp();
64          createMemoryOnlyStore(MemoryStoreEvictionPolicy.LRU);
65      }
66  
67  
68      /***
69       * Test the LRU policy
70       */
71      @Test
72      public void testPolicy() throws Exception {
73          createMemoryOnlyStore(MemoryStoreEvictionPolicy.LRU, 5);
74  
75          //Make sure that the store is empty to start with
76          assertEquals(0, cache.getSize());
77  
78          // Populate the store till the max limit
79          Element element = new Element("key1", "value1");
80          cache.put(element);
81          assertEquals(1, store.getSize());
82  
83          element = new Element("key2", "value2");
84          cache.put(element);
85          assertEquals(2, store.getSize());
86  
87          Thread.sleep(1020);
88          element = new Element("key3", "value3");
89          cache.put(element);
90          assertEquals(3, store.getSize());
91  
92          element = new Element("key4", "value4");
93          cache.put(element);
94          assertEquals(4, store.getSize());
95  
96          element = new Element("key5", "value5");
97          cache.put(element);
98          assertEquals(5, store.getSize());
99  
100         // Now access the elements to boost the hits count, although irrelevant for this test just to demonstrate
101         // hit count is immaterial for this test.
102         cache.get("key1");
103         cache.get("key1");
104         Thread.sleep(1020);
105         cache.get("key3");
106         cache.get("key3");
107         cache.get("key3");
108         Thread.sleep(1020);
109         cache.get("key4");
110 
111         //Create a new element and put in the store so as to force the policy
112         element = new Element("key6", "value6");
113         cache.put(element);
114 
115         Thread.sleep(1020);
116         cache.get("key6");
117 
118         //max size
119         assertEquals(5, store.getSize());
120 
121         //The element with key "key2" should be the least recently used
122         assertNull(store.get("key2"));
123         cache.get("key2");
124 
125         // Make some more accesses
126         Thread.sleep(1020);
127         cache.get("key5");
128         cache.get("key5");
129 
130         // Insert another element to force the policy
131         element = new Element("key7", "value7");
132         cache.put(element);
133         assertEquals(5, store.getSize());
134 
135         //key1 should now be the least recently used.
136         assertNull(store.get("key1"));
137     }
138 
139     /***
140      * Test the LRU policy
141      */
142     @Ignore
143     @Test
144     public void testProbabilisticEvictionPolicy() throws Exception {
145         createMemoryOnlyStore(MemoryStoreEvictionPolicy.LRU, 500);
146 
147         //Make sure that the store is empty to start with
148         assertEquals(0, cache.getSize());
149 
150         // Populate the store till the max limit
151         Element element = new Element("key1", "value1");
152         for (int i = 0; i < 500; i++) {
153             cache.put(new Element("" + i, "value1"));
154         }
155         //Let the last used timestamps be effective for the evictor
156         Thread.sleep(3010);
157 
158         //Now read to update the put count
159         for (int i = 0; i < 500; i++) {
160             cache.get("" + i);
161         }
162 
163         //Let the last used timestamps be effective for the evictor
164         //Note: This should not be necessary. It became necessary in 1.7 because the timestamp precision was changed to 1 second
165 //        Thread.sleep(3010);
166 
167 
168         //Add some fresher content
169         for (int i = 501; i < 750; i++) {
170             cache.put(new Element("" + i, "value1"));
171         }
172 
173         //The fresh ones should be kept.
174         int lastPutCount = 0;
175         for (int i = 501; i < 750; i++) {
176             if (cache.get("" + i) != null) {
177                 lastPutCount++;
178             }
179         }
180         LOG.info("Last Put count: " + lastPutCount);
181 
182         assertTrue("Ineffective eviction algorithm. Less than 230 of the last 249 put Elements remain: " + lastPutCount, lastPutCount >= 245);
183     }
184 
185 
186     /***
187      * Multi-thread read, put and removeAll test.
188      * This checks for memory leaks
189      * using the removeAll which was the known cause of memory leaks with MemoryStore in JCS
190      */
191     @Override
192     @Test
193     public void testMemoryLeak() throws Exception {
194         super.testMemoryLeak();
195     }
196 
197 
198     /***
199      * Specifically to verify the sampling algorithm.
200      * <p/>
201      * This test demonstrates a memory leak if we let the store simply get bigger on an eviction sampling miss.
202      * as is done in r960. e.g.
203      * Jun 9, 2009 10:47:30 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
204      * INFO: Store size is: 12538
205      * Jun 9, 2009 10:47:32 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
206      * INFO: Store size is: 13527
207      * Jun 9, 2009 10:47:34 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
208      * INFO: Store size is: 14475
209      * Jun 9, 2009 10:47:37 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
210      * INFO: Store size is: 15446
211      * Jun 9, 2009 10:47:39 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
212      * INFO: Store size is: 16424
213      * Jun 9, 2009 10:47:41 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
214      * INFO: Store size is: 17399
215      * Jun 9, 2009 10:47:43 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
216      * INFO: Store size is: 18353
217      * Jun 9, 2009 10:47:46 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
218      * INFO: Store size is: 19324
219      * Jun 9, 2009 10:47:48 AM net.sf.ehcache.store.LruMemoryStoreTest testMemoryLeakPutGetRemove
220      * INFO: Store size is: 20300
221      * <p/>
222      * Now fixed and this test consistently gives a size of 12000
223      */
224     @Test
225     public void testMemoryLeakPutGetRemove() throws Exception {
226 
227         //use MemoryOnly to isolate out the effects of the DiskStore
228         createMemoryOnlyStore(MemoryStoreEvictionPolicy.LRU);
229 
230         final String key = "key";
231         String value = "value";
232 
233         for (int j = 0; j < 1200000; j += 300000) {
234 
235             for (int i = j; i < 300000 + j; i++) {
236                 Element element = new Element(key + i, value);
237                 store.put(element);
238             }
239             assertEquals(12000, store.getSize());
240             LOG.info("Store size is: " + store.getSize());
241         }
242     }
243 
244 }