package com.ctriposs.bigcache;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import com.ctriposs.bigcache.CacheConfig.StorageMode;
import com.ctriposs.bigcache.utils.TestUtil;
public class BigCacheStressTest {
private static final String TEST_DIR = TestUtil.TEST_BASE_DIR + "stress/bigcache/";
private static BigCache<String> cache;
public static void main(String[] args) throws Exception {
int numKeyLimit = 1024 * 16;
int valueLengthLimit = 1024 * 16;
CacheConfig config = new CacheConfig();
config.setStorageMode(StorageMode.OffHeapPlusFile)
.setPurgeInterval(2 * 1000)
.setMergeInterval(2 * 1000)
//allocate half of the memory - leave space for keys and reference map.
.setMaxOffHeapMemorySize(5 * 1000 * 1024 * 1024L);
cache = new BigCache<String>(TEST_DIR, config);
Map<String, byte[]> map = new HashMap<String, byte[]>();
String[] rndStrings = { TestUtil.randomString(valueLengthLimit / 2),
TestUtil.randomString(valueLengthLimit),
TestUtil.randomString(valueLengthLimit + valueLengthLimit / 2) };
byte[] rndBytes = rndStrings[1].getBytes();
Random random = new Random();
System.out.println("Start from date " + new Date());
long start = System.currentTimeMillis();
for (long counter = 0;; counter++) {
int rndKey = random.nextInt(numKeyLimit);
boolean put = random.nextDouble() < 0.5 ? true : false;
if (put) {
rndBytes = rndStrings[random.nextInt(3)].getBytes();
map.put(String.valueOf(rndKey), rndBytes);
cache.put(String.valueOf(rndKey), rndBytes);
} else {
map.remove(String.valueOf(rndKey));
byte[] oldV = cache.delete(String.valueOf(rndKey));
byte[] v = cache.get(String.valueOf(rndKey));
if (v != null) {
System.out.println("should be null. Key:" + String.valueOf(rndKey) + " Value:" + new String(v));
System.out.println(" Key:" + String.valueOf(rndKey) + " oldValue:"
+ (oldV == null ? null : new String(oldV)));
}
}
cache.put(counter + "-ttl", rndBytes, (long) 10 * 1000);
if (counter % 1000000 == 0) {
System.out.println("Current date: " + new Date());
System.out.println("counter: " + counter);
System.out.println("purge: " + cache.getStats().getCacheExpire());
System.out.println("move: " + cache.getStats().getCacheMove());
System.out.println("size: " + cache.count());
long cacheUsed = cache.getStats().getStorageUsed();
System.out.println("used: " + cacheUsed);
System.out.println();
long storeUsed = cache.storageManager.getUsed();
if (cacheUsed != storeUsed) {
System.out.println("!!!! Temporarily fail the test, this could seldom occur");
System.out.println("storage used: " + storeUsed + ", but cache used: " + cacheUsed);
}
System.out.println();
System.out.println(TestUtil.printMemoryFootprint());
long end = System.currentTimeMillis();
System.out.println("timeSpent = " + (end - start));
System.out.println("ttl count = " + (cache.count() - map.size()));
System.out.println("used size = " + cache.getStats().getStorageUsed());
// validation
for (int i = 0; i < numKeyLimit; i++) {
String key = String.valueOf(i);
byte[] mapValue = map.get(key);
byte[] cacheValue = cache.get(key);
if (mapValue == null && cacheValue != null) {
System.out.println("Key:" + key);
System.out.println("Value:" + new String(cacheValue));
throw new RuntimeException("Validation exception, key exists in cache but not in map");
}
if (mapValue != null && cacheValue == null) {
throw new RuntimeException("Validation exception, key exists in map but not in cache");
}
if (mapValue != null && cacheValue != null) {
if (compare(mapValue, cacheValue) != 0) {
throw new RuntimeException("Validation exception, values in map and cache does not equal");
}
}
}
//exclude validation process from time count
start = System.currentTimeMillis();
}
}
}
public static int compare(byte[] left, byte[] right) {
for (int i = 0, j = 0; i < left.length && j < right.length; i++, j++) {
int a = (left[i] & 0xff);
int b = (right[j] & 0xff);
if (a != b) {
return a - b;
}
}
return left.length - right.length;
}
}