Проблема производительности с объектом кэша 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

Из инструмента мониторинга кучи мы получаем следующее сообщение

Один экземпляр com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache, "загруженный"org.apache.catalina.loader.WebappClassLoader @ 0x82f1c58, занимает 72 970 824 (57,75%) байта. Память накапливается в одном экземпляре com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache, "загруженном"org.apache.catalina.loader.WebappClassLoader @ 0x82f1c58".

Пожалуйста, посоветуйте, пожалуйста:- В чем может быть причина того, что этот экземпляр занимает такую ​​огромную память? Работаем ли мы с правильной конфигурацией c3p0? Какие конфигурации рекомендуются для сильно загруженного приложения?

заранее спасибо

3 ответа

Вы установили maxStatementsPerConnection=50 и maxPoolSize=150. Это означает, что кэш операторов может иметь до 7500 открытых операторов одновременно, включая объем памяти любых ресурсов, которые ваш драйвер связывает с операторами. По сути, вы просите c3p0 использовать много памяти, полагая, что стоимость памяти ниже по сравнению с затратами на производительность при подготовке Statement.

Во-первых, это может быть совсем не так, и в этом случае кэширование операторов в целом проигрышно, и вам просто не следует его использовать. Вы должны сравнить свое приложение с maxStatements и maxStatementsPerConnection, установленными в ноль, чтобы проверить, действительно ли вы получаете выгоду от кэширования операторов, если вы этого еще не сделали. Для драйверов, которые кешируют много разборов и подготовки в объектах PreparedStatement, кэширование операторов может быть большой помощью. Но вы сталкиваетесь с компромиссом между объемом занимаемой памяти кеш-памяти и преимуществом производительности при наличии предварительно кэшированных операторов. Совершенно очевидно, что даже если кеширование операторов полезно для вашей производительности, вы превысили уровень, когда выгоды превышают затраты.

Сколько из этих 150 подготовленных утверждений в вашем приложении часто используются? Можете ли вы сделать это число меньшим, предпочтительно намного меньшим, ожидая, что более редко используемые операторы будут выпадать из кеша и к ним не прибавиться? В качестве альтернативы вы можете оставить это число в покое, но объедините maxStatementsPerConnection с глобальным параметром maxStatements (задайте значение, меньшее неявного 7500, который вы используете в данный момент). Если вы комбинируете maxStatementsPerConnection и maxStatements, каждому соединению будет разрешено иметь значение maxStatementsPerConnection, пока пул мал, но по мере того, как пул становится большим, а объем памяти становится опасным, глобальный лимит операторов приведет к запуску реже используемых операторов выпадение из кеша для сохранения памяти.

Надеюсь, это поможет!

Это потому, что вы дали maxIdleTime = 0.

Установка для maxIdleTime ненулевого значения позволяет C3P0 удалять подключения из пула и освобождать ресурсы базы данных.

Это никогда не произойдет, когда maxIdleTime установлен в 0

,

Поэтому я считаю, что ни одно из ваших соединений не удаляется из пула. Вот почему он становится огромным в размере кучи.

Для получения дополнительной информации нажмите здесь.

Попробуйте BoneCP для высокопроизводительного пула соединений, он решает многие проблемы производительности c3p0 и Apache DBCP.

Другие вопросы по тегам