c3p0缓存对象的性能问题:

时间:2012-07-17 08:31:10

标签: hibernate c3p0

我想分享一个奇怪的例子。在生产时我们的应用程序抛出OOM异常,我们进行了堆转储并开始分析后来我们发现com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache实例的问题。此对象的大小约为堆大小的50%。该应用程序正在运行,数十亿用户和服务器一次又一次地停止运行。

此应用程序在tomcat上运行,其中tomcat连接器允许300个最大并发请求,以下是c3p0配置。

jdbc.hibernate.c3p0.minPoolSize=2
jdbc.hibernate.c3p0.maxPoolSize=150
jdbc.hibernate.c3p0.maxIdleTime=0
jdbc.hibernate.c3p0.maxStatementsPerConnection=50
jdbc.hibernate.c3p0.numHelperThreads=6

从堆监控工具中我们收到以下消息

由“org.apache.catalina.loader.WebappClassLoader @ 0x82f1c58”加载的“com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache”的一个实例占用72 970 824(57,55%)个字节。内存在“com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache”的一个实例中累积,该实例由“org.apache.catalina.loader.WebappClassLoader @ 0x82f1c58”

加载

请告知: - 这个实例占据如此巨大的记忆的原因是什么? 我们使用正确的c3p0配置运行吗? 重载应用程序的推荐配置是什么?

提前致谢

3 个答案:

答案 0 :(得分:2)

您已设置maxStatementsPerConnection = 50和maxPoolSize = 150。这意味着语句缓存在任何时候都可能有多达7500个开放语句,包括驱动程序与语句关联的任何资源的内存占用量。基本上要求c3p0使用大量内存,理论上内存成本低于准备Statement的性能成本。

首先,这可能不是真的,在这种情况下,语句缓存通常是一个失败者,你应该不使用它。您应该将maxStatements和maxStatementsPerConnection都设置为零来测试您的应用程序,以测试您是否实际上从Statement缓存中获益,如果您还没有。对于在PreparedStatement对象中缓存大量解析和准备的驱动程序,语句缓存可能是一个很大的帮助。但是,您需要在缓存的内存占用和预先缓存的语句的性能优势之间进行权衡。很明显,即使语句缓存对您的表现有帮助,您也已经超出了收益超过成本的程度。

您应用中经常使用的150份预备语句中有多少?您能否将该数字设置得更小,最好更小,期望更少使用的语句会从缓存中退出并对它们有很大的帮助?或者,您可以单独保留该数字,但将maxStatementsPerConnection与全局maxStatements设置相结合(设置为小于您当前使用的隐式7500的值)。如果组合maxStatementsPerConnection和maxStatements,则在池很小时允许每个Connection最多具有maxStatementsPerConnection,但是当池变大并且内存占用成为危险时,全局语句限制将导致最近使用较少的语句启动退出缓存以保留内存。

我希望这有帮助!

答案 1 :(得分:0)

这是因为您提供了 maxIdleTime = 0

将maxIdleTime设置为非零值允许C3P0从池中删除Connections并释放数据库资源。

  

当maxIdleTime设置为0

时,永远不会发生这种情况

所以我相信没有任何连接从池中删除。 这就是为什么它的堆大小非常大。

更多参考click here

答案 2 :(得分:-1)

尝试BoneCP获得高性能连接池,它解决了许多面向性能的c3p0和Apache DBCP问题。