1 package net.sf.ehcache;
2
3 import net.sf.ehcache.config.CacheConfiguration;
4 import net.sf.ehcache.config.Configuration;
5 import net.sf.ehcache.config.MemoryUnit;
6 import net.sf.ehcache.pool.sizeof.AgentSizeOf;
7 import net.sf.ehcache.pool.sizeof.ReflectionSizeOf;
8 import net.sf.ehcache.pool.sizeof.SizeOf;
9 import net.sf.ehcache.pool.sizeof.SizeOfAgent;
10 import net.sf.ehcache.pool.sizeof.UnsafeSizeOf;
11 import net.sf.ehcache.store.Store;
12 import org.junit.Before;
13 import org.junit.Ignore;
14 import org.junit.Test;
15 import org.mockito.internal.matchers.EqualsWithDelta;
16
17 import java.lang.reflect.Field;
18 import java.util.concurrent.atomic.AtomicLong;
19
20 import static org.hamcrest.CoreMatchers.is;
21 import static org.junit.Assert.assertThat;
22
23 /***
24 * @author Alex Snaps
25 */
26 public class PoolCacheManagerTest {
27
28 @Before
29 public void setup() {
30 getSizeOfEngine().sizeOf("");
31 System.err.println("Testing for a " + System.getProperty("java.version") + " JDK on a "
32 + System.getProperty("sun.arch.data.model") + "bit VM");
33 }
34
35 @Ignore
36 @Test
37 public void testOnHeapConsumption() throws Exception {
38 SizeOf sizeOf = getSizeOfEngine();
39 CacheManager cacheManager = new CacheManager(new Configuration().maxBytesLocalHeap(40, MemoryUnit.MEGABYTES));
40 cacheManager.addCache(new Cache(new CacheConfiguration("one", 0).overflowToDisk(false)));
41 cacheManager.addCache(new Cache(new CacheConfiguration("double", 0).overflowToDisk(false)));
42
43 Cache oneSize = cacheManager.getCache("one");
44 Cache doubleSize = cacheManager.getCache("double");
45
46 Element test = new Element("test", new Pair("0", new Object()));
47 oneSize.put(test);
48 doubleSize.put(test);
49 sizeOf.deepSizeOf(test);
50 oneSize.remove(test.getKey());
51 int size = 60000;
52 for (int i = 0; i < size; i++) {
53
54
55
56 doubleSize.put(new Element(new Object(), new Object()));
57
58 }
59 doubleSize.removeAll();
60
61 long usedBefore = measureMemoryUse();
62
63 for (int i = 0; i < size; i++) {
64
65
66
67 oneSize.put(new Element(new Object(), new Object()));
68
69 }
70
71 long mem = 0;
72 for (Object key : oneSize.getKeys()) {
73 Element element = oneSize.get(key);
74 mem += sizeOf.deepSizeOf(element);
75 }
76 for (Object key : doubleSize.getKeys()) {
77 Element element = doubleSize.get(key);
78 mem += sizeOf.deepSizeOf(element);
79 }
80
81 assertThat(MemoryUnit.MEGABYTES.toBytes(40) - mem >= 0, is(true));
82 long consumes = measureMemoryUse() - usedBefore;
83 assertThat(consumes +" bytes are actually being used, while we believe " + mem + " are",
84 mem / (float)consumes, new EqualsWithDelta(1f, 0.025f));
85 }
86
87 private long getInMemorySizeInBytes(final Cache oneSize) throws Exception {
88 Field store = Cache.class.getDeclaredField("compoundStore");
89 store.setAccessible(true);
90 return ((Store) store.get(oneSize)).getInMemorySizeInBytes();
91 }
92
93 protected long measureMemoryUse() throws InterruptedException {
94 System.gc();
95 Thread.sleep(2000);
96 System.gc();
97 return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
98 }
99
100 private static final class Pair {
101 private static final AtomicLong counter = new AtomicLong(Long.MIN_VALUE);
102 private final Object one;
103 private final Object two;
104 private final Object oneHidden;
105 private final Object twoHidden;
106 private final Object threeHidden;
107 private final Object fourHidden;
108 private final long instanceNumber;
109
110 private Pair(final Object one, final Object two) {
111 this.one = one;
112 this.two = two;
113 instanceNumber = counter.getAndIncrement();
114 if(instanceNumber % 4 == 1) {
115 oneHidden = new Object();
116 twoHidden = new Object();
117 threeHidden = new Object();
118 fourHidden = new Object();
119 } else {
120 oneHidden = null;
121 twoHidden = null;
122 threeHidden = null;
123 fourHidden = null;
124 }
125 }
126 }
127
128 private static SizeOf getSizeOfEngine() {
129 try {
130 return new AgentSizeOf();
131 } catch (UnsupportedOperationException e) {
132 try {
133 return new UnsafeSizeOf();
134 } catch (UnsupportedOperationException f) {
135 try {
136 return new ReflectionSizeOf();
137 } catch (UnsupportedOperationException g) {
138 throw new CacheException("A suitable SizeOf engine could not be loaded: " + e + ", " + f + ", " + g);
139 }
140 }
141 }
142 }
143 }