问题

使用java开源项目经常需要调优jvm,以优化gc。对于gc,如果对象都是短时对象,那么jvm相对容易优化,假如碰上像solr使用自带java cache的项目,那么gc严重受限于cache,因为cache对象并非短时对象,以至于young gc常常伴有大量的内存对象拷贝,严重影响gc性能。

Ehcache BigMemory

Java的内存管理机制极其不适用于cache,最好的办法是使用jni实现的cache系统。另一种通用办法:Ehcache BigMemory(http://ehcache.org/)。BigMemory extends Ehcache's' capabilities with an off-heap store that frees you from GC’s constraints.

对于BigMemory,直接下载免费的32G限制的版本(注: 每个jvm进程最多使用32G的off-heap空间,对大多数应用已足够)。

关于如何使用,参见官方文档: http://terracotta.org/documentation/4.0/bigmemorygo/get-started

使用示例可参考代码中自带的样例:bigmemory-go-4.0.0/code-samples/src/main/java/com/bigmemory/samples

样例代码缺少编译配置build.xml, 将下面的 build.xml 放在 bigmemory-go-4.0.0/code-samples 即可使用ant 编译示例代码:

  1. <project name="bigmemory" basedir=".">
  2. <property name="build.dir" value="${basedir}/build" />
  3. <property name="src.class.dir" value="${build.dir}" />
  4. <property name="src.dir" value="${basedir}/src" />
  5. <property name="lib.dir" value="${basedir}/../lib" />
  6. <property name="config.dir" value="${basedir}/config" />
  7. <path id="base.classpath">
  8. <pathelement location="${src.class.dir}" />
  9. <pathelement location="${config.dir}" />
  10. <fileset dir="${lib.dir}">
  11. <include name="**/*.jar" />
  12. </fileset>
  13. </path>
  14. <path id="classpath">
  15. <path refid="base.classpath" />
  16. <fileset dir="${lib.dir}">
  17. <include name="**/*.jar" />
  18. </fileset>
  19. </path>
  20. <path id="build.src.path">
  21. <pathelement location="${src.class.dir}" />
  22. </path>
  23. <target name="clean" description="clean">
  24. <delete dir="${build.dir}" />
  25. </target>
  26. <target name="compile" depends="clean" description="compile">
  27. <mkdir dir="${src.class.dir}" />
  28. <javac srcdir="${src.dir}" destdir="${src.class.dir}" source="1.6" debug="on" encoding="utf-8" includeantruntime="false">
  29. <classpath refid="base.classpath" />
  30. </javac>
  31. </target>
  32. <target name="jar" depends="compile" description="jar">
  33. <jar destfile="${build.dir}/bigmemory.jar">
  34. <fileset dir="${src.class.dir}">
  35. <exclude name="**/timer/**" />
  36. </fileset>
  37. </jar>
  38. </target>
  39. </project>

配置说明:bigmemory-go-4.0.0/config-samples/ehcache.xml 详细说明了配置参数。

限制:

1、存储对象全部使用 java.io.Serializable 做序列化和反序列化,性能有损失。

2、off-heap空间一经分配不可调整。

solr缓存

引入Ehcache bigmemory是为了优化solr的缓存。下面代码是基于solr cache基类实现的ehcache缓存类,使用上同于solr.FastLRUCache,需要ehcache的外部配置文件。

  1. package org.apache.solr.search;
  2.  
  3. import org.apache.solr.common.SolrException;
  4. import org.apache.solr.common.util.NamedList;
  5. import org.apache.solr.common.util.SimpleOrderedMap;
  6. import org.apache.solr.core.SolrCore;
  7.  
  8. import java.util.*;
  9. import java.util.concurrent.atomic.AtomicLong;
  10. import java.io.IOException;
  11. import java.net.URL;
  12.  
  13. import net.sf.ehcache.Cache;
  14. import net.sf.ehcache.CacheManager;
  15. import net.sf.ehcache.Element;
  16. import net.sf.ehcache.config.CacheConfiguration;
  17. import net.sf.ehcache.config.Configuration;
  18. import net.sf.ehcache.config.MemoryUnit;
  19.  
  20. /**
  21. * @version $Id: EhCacheWrapper.java 2013-03-27 zhenjing chen $
  22. */
  23. public class EhCacheWrapper implements SolrCache {
  24.  
  25. /* An instance of this class will be shared across multiple instances
  26. * of an LRUCache at the same time. Make sure everything is thread safe.
  27. */
  28. private static class CumulativeStats {
  29. AtomicLong lookups = new AtomicLong();
  30. AtomicLong hits = new AtomicLong();
  31. AtomicLong inserts = new AtomicLong();
  32. AtomicLong evictions = new AtomicLong();
  33. }
  34.  
  35. private CumulativeStats stats;
  36.  
  37. // per instance stats. The synchronization used for the map will also be
  38. // used for updating these statistics (and hence they are not AtomicLongs
  39. private long lookups;
  40. private long hits;
  41. private long inserts;
  42. private long evictions;
  43.  
  44. private long warmupTime = 0;
  45.  
  46. private CacheManager manager = null;
  47. private Cache map;
  48. private String name;
  49. private String cache_name;
  50. private int autowarmCount;
  51. private State state;
  52. private CacheRegenerator regenerator;
  53. private String description="Eh LRU Cache";
  54.  
  55. private static int cache_index = 0;
  56. private static Map<String, CacheManager> managerPool = null;
  57. private static Map<String, Integer> managerFlag = null;
  58. private static CacheManager managerTemplate = null;
  59. static{
  60. managerPool = new HashMap<String, CacheManager>();
  61. managerFlag = new HashMap<String, Integer>();
  62. managerTemplate = new CacheManager("/data/conf/ehcache.xml");
  63. }
  64.  
  65. private Cache GetCache() {
  66.  
  67. // use cache pool
  68. Set<String> set = managerFlag.keySet();
  69. Iterator<String> it = set.iterator();
  70. while(it.hasNext()) {
  71. String cacheName = it.next();
  72. if( managerFlag.get(cacheName) == 0 ) { // not used
  73. manager = managerPool.get(cacheName);
  74.  
  75. System.out.println("EhCacheWrapper Cache Name(Pool): " + cacheName);
  76.  
  77. managerFlag.put(cacheName, 1);
  78. cache_name = cacheName;
  79. return manager.getCache(cacheName);
  80. }
  81. }
  82.  
  83. // add zhenjing
  84. String cacheName = name + cache_index;
  85. System.out.println("EhCacheWrapper Cache Name: " + cacheName);
  86.  
  87. // create Cache from template
  88. Cache orig = managerTemplate.getCache(name);
  89. CacheConfiguration configTmp = orig.getCacheConfiguration();
  90. configTmp.setName(cacheName);
  91. Configuration managerConfiguration = new Configuration();
  92. managerConfiguration.setName(cacheName);
  93. manager = new CacheManager(managerConfiguration.cache(configTmp));
  94.  
  95. // put to cache pool
  96. managerFlag.put(cacheName, 1);
  97. managerPool.put(cacheName, manager);
  98.  
  99. // get cache
  100. cache_index++;
  101. cache_name = cacheName;
  102. return manager.getCache(cacheName);
  103. }
  104.  
  105. public Object init(Map args, Object persistence, CacheRegenerator regenerator) {
  106. state=State.CREATED;
  107. this.regenerator = regenerator;
  108. name = (String)args.get("name");
  109. String str = (String)args.get("size");
  110. final int limit = str==null ? 1024 : Integer.parseInt(str);
  111. str = (String)args.get("initialSize");
  112. final int initialSize = Math.min(str==null ? 1024 : Integer.parseInt(str), limit);
  113. str = (String)args.get("autowarmCount");
  114. autowarmCount = str==null ? 0 : Integer.parseInt(str);
  115.  
  116. // get cache
  117. map = GetCache();
  118. CacheConfiguration config = map.getCacheConfiguration();
  119.  
  120. description = "Eh LRU Cache(MaxBytesLocalOffHeap=" + config.getMaxBytesLocalOffHeap() + ", MaxBytesLocalHeap=" + config.getMaxBytesLocalHeap() + ", MaxEntriesLocalHeap=" + config.getMaxEntriesLocalHeap() + ")";
  121.  
  122. if (persistence==null) {
  123. // must be the first time a cache of this type is being created
  124. persistence = new CumulativeStats();
  125. }
  126.  
  127. stats = (CumulativeStats)persistence;
  128.  
  129. return persistence;
  130. }
  131.  
  132. public String name() {
  133. return name;
  134. }
  135.  
  136. public int size() {
  137. synchronized(map) {
  138. return map.getSize();
  139. }
  140. }
  141.  
  142. public Object put(Object key, Object value) {
  143. synchronized (map) {
  144. if (state == State.LIVE) {
  145. stats.inserts.incrementAndGet();
  146. }
  147.  
  148. // increment local inserts regardless of state???
  149. // it does make it more consistent with the current size...
  150. inserts++;
  151. map.put(new Element(key,value));
  152. return null; // fake the previous value associated with key.
  153. }
  154. }
  155.  
  156. public Object get(Object key) {
  157. synchronized (map) {
  158. Element val = map.get(key);
  159. if (state == State.LIVE) {
  160. // only increment lookups and hits if we are live.
  161. lookups++;
  162. stats.lookups.incrementAndGet();
  163. if (val!=null) {
  164. hits++;
  165. stats.hits.incrementAndGet();
  166. //System.out.println(name + " EH Cache HIT. key=" + key.toString());
  167. }
  168. }
  169. if( val == null) return null;
  170. return val.getObjectValue();
  171. }
  172. }
  173.  
  174. public void clear() {
  175. synchronized(map) {
  176. map.removeAll();
  177. }
  178. }
  179.  
  180. public void setState(State state) {
  181. this.state = state;
  182. }
  183.  
  184. public State getState() {
  185. return state;
  186. }
  187.  
  188. public void warm(SolrIndexSearcher searcher, SolrCache old) throws IOException {
  189. return;
  190. }
  191.  
  192. public void close() {
  193. clear();
  194. // flag un-used
  195. managerFlag.put(cache_name, 0);
  196. System.out.println("EhCacheWrapper Cache Name(Reuse): " + cache_name);
  197. }
  198.  
  199. //////////////////////// SolrInfoMBeans methods //////////////////////
  200.  
  201. public String getName() {
  202. return EhCacheWrapper.class.getName();
  203. }
  204.  
  205. public String getVersion() {
  206. return SolrCore.version;
  207. }
  208.  
  209. public String getDescription() {
  210. return description;
  211. }
  212.  
  213. public Category getCategory() {
  214. return Category.CACHE;
  215. }
  216.  
  217. public String getSourceId() {
  218. return " NULL ";
  219. }
  220.  
  221. public String getSource() {
  222. return " NULL ";
  223. }
  224.  
  225. public URL[] getDocs() {
  226. return null;
  227. }
  228.  
  229. // returns a ratio, not a percent.
  230. private static String calcHitRatio(long lookups, long hits) {
  231. if (lookups==0) return "0.00";
  232. if (lookups==hits) return "1.00";
  233. int hundredths = (int)(hits*100/lookups); // rounded down
  234. if (hundredths < 10) return "0.0" + hundredths;
  235. return "0." + hundredths;
  236.  
  237. /*** code to produce a percent, if we want it...
  238. int ones = (int)(hits*100 / lookups);
  239. int tenths = (int)(hits*1000 / lookups) - ones*10;
  240. return Integer.toString(ones) + '.' + tenths;
  241. ***/
  242. }
  243.  
  244. public NamedList getStatistics() {
  245. NamedList lst = new SimpleOrderedMap();
  246. synchronized (map) {
  247. lst.add("lookups", lookups);
  248. lst.add("hits", hits);
  249. lst.add("hitratio", calcHitRatio(lookups,hits));
  250. lst.add("inserts", inserts);
  251. lst.add("evictions", evictions);
  252. lst.add("size", map.getSize());
  253. }
  254.  
  255. lst.add("warmupTime", warmupTime);
  256.  
  257. long clookups = stats.lookups.get();
  258. long chits = stats.hits.get();
  259. lst.add("cumulative_lookups", clookups);
  260. lst.add("cumulative_hits", chits);
  261. lst.add("cumulative_hitratio", calcHitRatio(clookups,chits));
  262. lst.add("cumulative_inserts", stats.inserts.get());
  263. lst.add("cumulative_evictions", stats.evictions.get());
  264.  
  265. return lst;
  266. }
  267.  
  268. public String toString() {
  269. return name + getStatistics().toString();
  270. }
  271. }

外部ehcache.xml配置:

  1. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
  3. updateCheck="false" monitoring="autodetect"
  4. dynamicConfig="true" name="config">
  5.  
  6. <!--
  7. <cache name="filterCache"
  8. maxEntriesLocalHeap="1024"
  9. eternal="true"
  10. overflowToOffHeap="true"
  11. maxBytesLocalOffHeap="1g">
  12. </cache>
  13.  
  14. <cache name="fieldValueCache"
  15. maxEntriesLocalHeap="1024"
  16. eternal="true"
  17. overflowToOffHeap="true"
  18. maxBytesLocalOffHeap="1g">
  19. </cache>
  20. -->
  21.  
  22. <cache name="queryResultCache"
  23. maxEntriesLocalHeap="1"
  24. eternal="true"
  25. overflowToOffHeap="true"
  26. maxBytesLocalOffHeap="800m">
  27. </cache>
  28.  
  29. <!-- ehcache not support documentCache, encoding format error.
  30. <cache name="documentCache"
  31. maxEntriesLocalHeap="1024"
  32. eternal="true"
  33. overflowToOffHeap="true"
  34. maxBytesLocalOffHeap="1g">
  35. </cache>
  36. -->
  37.  
  38. </ehcache>

http://www.cnblogs.com/zhenjing/p/Ehcache_BigMemory.html

Ehcache BigMemory: 摆脱GC困扰(转)的更多相关文章

  1. Ehcache BigMemory: 摆脱GC困扰

    问题 使用java开源项目经常需要调优jvm,以优化gc.对于gc,如果对象都是短时对象,那么jvm相对容易优化,假如碰上像solr使用自带java cache的项目,那么gc严重受限于cache,因 ...

  2. 成为Java GC专家(4)—Apache的MaxClients参数详解及其在Tomcat执行FullGC时的影响

    下面我们看一下Apache的 MaxClients 参数在Full GC 发生时是如何影响系统的. 大部分开发人员都知道在由于GC发生而导致的”停止世界现象(STW) “(详细请参见Understan ...

  3. 【Unity优化】构建一个拒绝GC的List

    版权声明:本文为博主原创文章,欢迎转载.请保留博主链接:http://blog.csdn.net/andrewfan 上篇文章<[Unity优化]Unity中究竟能不能使用foreach?> ...

  4. 在.net中读写config文件的各种方法

    阅读目录 开始 config文件 - 自定义配置节点 config文件 - Property config文件 - Element config文件 - CDATA config文件 - Collec ...

  5. SpringMVC 学习-返回字符串中文乱码问题解决

    一.使用 SpringMVC 框架时,如果 HTTP 请求资源返回的是中文字符串,则会出现乱码.原因如下: SpringMVC 框架可以使用 @RequestBody 和 @ResponseBody ...

  6. WPF程序中App.Config文件的读与写

    WPF程序中的App.Config文件是我们应用程序中经常使用的一种配置文件,System.Configuration.dll文件中提供了大量的读写的配置,所以它是一种高效的程序配置方式,那么今天我就 ...

  7. 通用订单搜索的API设计得失录

    先把 Joshua Bloch 大神的 API PDF 放在这里膜拜下:"How to Design a Good API and Why it Matters.pdf" 总述 在 ...

  8. Spring:面向切片编程

    在之前我们记录Spring的随笔当中,都是记录的Spring如何对对象进行注入,如何对对象的属性值进行注入,即我们讲解的很大部分都是Spring的其中一个核心概念——依赖注入(或者说是控制翻转,IOC ...

  9. 在.net中读写config文件的各种方法(自定义config节点)

    http://www.cnblogs.com/fish-li/archive/2011/12/18/2292037.html 阅读目录 开始 config文件 - 自定义配置节点 config文件 - ...

随机推荐

  1. ubuntu oracle jdk

    sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-javaX-i ...

  2. Linux内核的同步机制---自旋锁

    自旋锁的思考:http://bbs.chinaunix.net/thread-2333160-1-1.html 近期在看宋宝华的<设备驱动开发具体解释>第二版.看到自旋锁的部分,有些疑惑. ...

  3. 每日回顾Shell —cat,tail,head

    Shell中常常会用到cat命令.可是总是不是特别清楚: cat命令的用途是连接文件或标准输入并打印. 这个命令经常使用来显示文件内容.或者将几个文件连接起来显示.或者从标准输入读取内容并显示,它常与 ...

  4. Tomcat中更改网站根目录和默认页的配置方法

    1.tomcat原来的默认根目录是http://localhost:8080,如果想修改访问的根目录,可以这样: 找到tomcat的server.xml(在conf目录下),找到: <Host ...

  5. Google 开源项目的风格指南

    谷歌C++代码风格指南.农业所需的代码.更难得的是不FQ,决定性的最爱!! . http://zh-google-styleguide.readthedocs.org/en/latest/google ...

  6. jenkins集群加入Windows 2012 server作为slave

    必须安装.net framework 3.5, 參考: http://technet.microsoft.com/en-us/library/dn482071.aspx 不要在windows 2012 ...

  7. Python 的PyCurl模块使用

    PycURl是一个C语言写的libcurl的python绑定库.libcurl 是一个自由的,并且容易使用的用在客户端的 URL 传输库.它的功能很强大,PycURL 是一个非常快速(参考多并发操作) ...

  8. sql dateDiff函数

    当月的数据select * from MOPICK where dateDiff(m,getdate(),START_DATE)=0

  9. i++和i--运算符优先级

    1.问题背景 /** * 測试i++和i-- */ package com.you.model; /** * @author YouHaiDong * @date 2014-08-16 */ @Sup ...

  10. 【程序员联盟】官网上线啦!coderunity.com

    内容简介 欢天喜地,[程序员联盟]官网上线咯(此处应该有鸡蛋丢过来...) [程序员联盟]官网 大家也许会问:“这几天小编都没出文章,跑哪里happy去啦?是不是偷懒去了?” 小编:“臣妾冤枉啊.” ...