2010-10-22 36 views
6

Tôi có những gì tôi sẽ giả định là một thiết lập khá chuẩn ... mùa xuân, jpa (hibernate) và tôi đang cố gắng để thêm ehcache.Mùa xuân, JPA (Hibernate) & Ehcache Hiệu suất kém

Tôi đã định cấu hình và xác minh rằng nó đang hoạt động ... Tôi đang ghi nhật ký sql ngủ đông và câu lệnh bộ nhớ cache và có thể thấy bộ nhớ cache đang được gọi và khi đối tượng ở trong bộ nhớ cache, khi tôi thử để tải nó một lần nữa, câu lệnh sql không được viết ra (tức là nó không đánh vào cơ sở dữ liệu).

Tuy nhiên, hiệu suất là khủng khiếp ... nó khá nhiều hiệu suất tương tự nếu tôi nhận được đối tượng từ bộ nhớ cache hoặc từ db. Tôi nghi ngờ rằng có lẽ vấn đề là làm với mùa xuân tự động xả phiên ngủ đông, hoặc có thể là do giao dịch (mà tôi đã cố gắng tắt cho phương thức đó), hoặc có thể kết nối của tôi gộp bằng c3p0 không hoạt động tốt đủ. Dù sao đi chăng nữa, tôi hơi mất một chút ..

Tôi sẽ đăng tất cả thông tin liên quan mà tôi có và hy vọng một số thiên tài ở đây có thể giúp tôi nếu không tôi sẽ bị kẹt.

Thứ nhất, cấu hình mùa xuân của tôi:

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:hprof="http://www.nhprof.com/schema/hprof" 
xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 
http://www.nhprof.com/schema/hprof http://www.nhprof.com/schema/hprof/hprof.xsd"> 


<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

<bean id="systemPropertyManager" class="com.service.impl.SystemPropertyManagerImpl" /> 
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="mysql" /> 
    <property name="jpaVendorAdapter"> 
     <bean 
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="database" value="MYSQL" /> 
      <property name="showSql" value="true" /> 
     </bean> 
    </property> 
    <property name="jpaProperties"> 
     <props> 

      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
      <!-- always puts logging out to the console...we want it in the log file --> 
      <prop key="hibernate.connection.show_sql">false</prop> 
      <prop key="hibernate.hbm2ddl.auto">update</prop> 
     <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop> 
     <prop key="net.sf.ehcache.configurationResourceName">ehcache.xml</prop> 
      <prop key="hibernate.cache.use_second_level_cache">true</prop> 
      <prop key="hibernate.cache.use_structured_entries">true</prop> 
      <prop key="hibernate.cache.use_query_cache">true</prop> 
      <prop key="hibernate.generate_statistics">true</prop> 
      <prop key="hibernate.default_batch_fetch_size">500</prop> 
      <prop key="hibernate.max_fetch_depth">5</prop> 
      <prop key="hibernate.jdbc.batch_size">1000</prop> 
      <prop key="hibernate.use_outer_join">true</prop> 
     </props> 
    </property> 
<!-- <hprof:profiler /> --> 
</bean> 


<bean id="mysql" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
    <property name="driverClass" value="com.mysql.jdbc.Driver" /> 
    <property name="jdbcUrl" value="jdbc:mysql://localhost/daily?relaxAutoCommit=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;jdbcCompliantTruncation=false&amp;emulateLocators=true" /> 
    <property name="user" value="root" /> 
    <property name="password" value="" /> 
    <property name="initialPoolSize"><value>5</value></property> 
    <property name="minPoolSize"><value>5</value></property> 
    <property name="maxPoolSize"><value>50</value></property> 
    <property name="idleConnectionTestPeriod"><value>200</value></property> 
    <property name="acquireIncrement"><value>3</value></property> 
    <property name="numHelperThreads"><value>3</value></property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 

tập tin ehcache của tôi là như sau

<ehcache> 
<diskStore path="c:/cache"/> 

    <defaultCache eternal="false" 
      overflowToDisk="false" 
      maxElementsInMemory="50000" 
      timeToIdleSeconds="30" 
      timeToLiveSeconds="6000" 
      memoryStoreEvictionPolicy="LRU" 
      /> 
    <cache name="com.model.SystemProperty" 
      maxElementsInMemory="5000" 
      eternal="true" 
      overflowToDisk="false" 
      memoryStoreEvictionPolicy="LFU" />    

đối tượng lưu trữ của tôi được chú thích để gọi bộ nhớ cache như sau:

package com.model; 

import javax.persistence.*; 

import org.hibernate.annotations.Cache; 
import org.hibernate.annotations.CacheConcurrencyStrategy; 

@Entity 
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region="com.model.SystemProperty", include="non-lazy") 
@EntityListeners(com.util.GenericEntityLogger.class) 
public class SystemProperty extends BaseObject{ 

    private String name; 
    private String value; 

    // default constructor 
    public SystemProperty(){ 

    } 
    public SystemProperty(String name, String value){ 
     this.name = name; 
     this.value = value; 
    } 

    @Id 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 

    public String getValue() { 
     return value; 
    } 
    public void setValue(String value) { 
     this.value = value; 
    } 

    @Override 
    public boolean equals(Object o) { 
     // TODO Auto-generated method stub 
     return false; 
    } 
    @Override 
    public int hashCode() { 
     // TODO Auto-generated method stub 
     return 0; 
    } 
    @Override 
    public String toString() { 
     // TODO Auto-generated method stub 
     return null; 
    } 


} 

và thực hiện của tôi về giao diện của tôi sử dụng để lưu và nhận được đối tượng SystemProperty với mùa xuân phương pháp @Transactional là như sau:

package com.service.impl; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.springframework.transaction.annotation.Transactional; 

import com.model.SystemProperty; 
import com.service.SystemPropertyManager; 


public class SystemPropertyManagerImpl extends BaseManagerImpl implements SystemPropertyManager { 

    // logging 
    protected final Log log = LogFactory.getLog(getClass()); 

    public SystemProperty find(String name){ 
     return (SystemProperty) super.entityManager.find(SystemProperty.class, name); 
    } 

    @Transactional 
    public SystemProperty save(SystemProperty prop){ 
     return (SystemProperty) super.save(prop); 
    } 

} 

Lưu ý rằng @Transactional chỉ trên phương pháp tiết kiệm. Cuối cùng, tôi đã tạo cơ sở dữ liệu mysql với 3000 đối tượng thuộc tính hệ thống và sau đó đã viết một tệp thử nghiệm nhỏ, tải chúng lên gấp hai lần.

Lần đầu tiên tải chúng, tôi có thể thấy sql được tạo và bộ nhớ cache không bị ảnh hưởng. Lần thứ hai, bộ nhớ cache không nhận được nhấn và sql không được tạo ra.

Unit Test:

@Test 
public void testGetCachedUser1(){ 
    log.debug("starting testGetCachedUser"); 
    SystemPropertyManager mgr = ManagerFactory.getSystemPropertyManager(); 
    EntityManager em = mgr.getEntityManager(); 

    log.debug("start timing 1"); 
    for(int i = 0; i<3000; i ++){ 
     mgr.find("name_"+i); 
    } 
    log.debug("end timing 1"); 
    log.debug("start timing 2"); 
    for(int i = 0; i<3000; i ++){ 
     mgr.find("name_"+i); 
    } 
    log.debug("end timing 2"); 
} 

Các file log có rất nhiều thông tin. Tôi sẽ đăng phần từ tệp nhật ký trong vùng "bắt đầu thời gian 1". Điều này tương ứng với những gì xảy ra chỉ dành cho các đối tượng đầu tiên mà được nạp khi nó không phải là trong bộ nhớ cache:

DEBUG 2010-10-22 11:57:49,533 [main][] org.springframework.transaction.annotation.AnnotationTransactionAttributeSource - Adding transactional method [find] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] 
DEBUG 2010-10-22 11:57:49,533 [main][] org.hibernate.impl.SessionImpl - opened session at timestamp: 5274603804807168 
DEBUG 2010-10-22 11:57:49,533 [main][] org.hibernate.transaction.JDBCTransaction - begin 
DEBUG 2010-10-22 11:57:49,533 [main][] org.hibernate.jdbc.ConnectionManager - opening JDBC connection 
DEBUG 2010-10-22 11:57:49,533 [main][] com.mchange.v2.resourcepool.BasicResourcePool - trace [email protected] [managed: 5, unused: 4, excluded: 0] (e.g. [email protected]) 
DEBUG 2010-10-22 11:57:49,533 [main][] org.hibernate.transaction.JDBCTransaction - current autocommit status: true 
DEBUG 2010-10-22 11:57:49,533 [main][] org.hibernate.transaction.JDBCTransaction - disabling autocommit 
DEBUG 2010-10-22 11:57:49,533 [main][] org.hibernate.jdbc.JDBCContext - after transaction begin 
DEBUG 2010-10-22 11:57:49,549 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [[email protected]] for key [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 31ghzi8b1mphf1c19l14qo|149105b, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.p6spy.engine.spy.P6SpyDriver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 31ghzi8b1mphf1c19l14qo|149105b, idleConnectionTestPeriod -> 200, initialPoolSize -> 5, jdbcUrl -> jdbc:mysql://localhost/daily?relaxAutoCommit=true&useUnicode=true&characterEncoding=UTF-8&jdbcCompliantTruncation=false&emulateLocators=true, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 50, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]] to thread [main] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [[email protected]] for key [org[email protected]11b99c4] to thread [main] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization 
DEBUG 2010-10-22 11:57:49,549 [main][] org.springframework.transaction.interceptor.TransactionInterceptor - Getting transaction for [com.service.SystemPropertyManager.find] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [[email protected]] for key [org[email protected]11b99c4] bound to thread [main] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.event.def.DefaultLoadEventListener - loading entity: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.event.def.DefaultLoadEventListener - attempting to resolve: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.event.def.DefaultLoadEventListener - object not resolved in any cache: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.persister.entity.AbstractEntityPersister - Fetching entity: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.loader.Loader - loading entity: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0) 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.SQL - select systemprop0_.name as name11_0_, systemprop0_.value as value11_0_ from SystemProperty systemprop0_ where systemprop0_.name=? 
DEBUG 2010-10-22 11:57:49,549 [main][] org.hibernate.jdbc.AbstractBatcher - preparing statement 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.type.StringType - binding 'name_0' to parameter: 1 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0) 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.loader.Loader - processing result set 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.loader.Loader - result set row: 0 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.loader.Loader - result row: EntityKey[com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.loader.Loader - Initializing object from ResultSet: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.persister.entity.AbstractEntityPersister - Hydrating entity: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.type.StringType - returning 'value_0' as column: value11_0_ 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.loader.Loader - done processing result set (1 rows) 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1) 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1) 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.jdbc.AbstractBatcher - closing statement 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.loader.Loader - total objects hydrated: 1 
DEBUG 2010-10-22 11:57:49,580 [main][] org.hibernate.engine.TwoPhaseLoad - resolving associations for [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.engine.TwoPhaseLoad - adding entity to second-level cache: [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.cache.ReadOnlyCache - Caching: com.model.SystemProperty#name_0 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.engine.TwoPhaseLoad - done materializing entity [com.model.SystemProperty#name_0] 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.engine.StatefulPersistenceContext - initializing non-lazy collections 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.loader.Loader - done entity load 
DEBUG 2010-10-22 11:57:49,596 [main][] org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [com.service.SystemPropertyManager.find] 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.transaction.JDBCTransaction - commit 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.impl.SessionImpl - automatically flushing session 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - flushing session 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - processing flush-time cascades 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.engine.Cascade - processing cascade ACTION_PERSIST_ON_FLUSH for: com.model.SystemProperty 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.engine.Cascade - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.model.SystemProperty 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - dirty checking collections 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - Flushing entities and processing referenced collections 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - Processing unreferenced collections 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - Scheduling collection removes/(re)creates/updates 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.pretty.Printer - listing entities: 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.pretty.Printer - com.model.SystemProperty{name=name_0, value=value_0} 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - executing flush 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.jdbc.ConnectionManager - registering flush begin 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.jdbc.ConnectionManager - registering flush end 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.event.def.AbstractFlushingEventListener - post flush 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.jdbc.JDBCContext - before transaction completion 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.impl.SessionImpl - before transaction completion 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.transaction.JDBCTransaction - re-enabling autocommit 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.transaction.JDBCTransaction - committed JDBC Connection 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.jdbc.JDBCContext - after transaction completion 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.jdbc.ConnectionManager - aggressively releasing JDBC connection 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
DEBUG 2010-10-22 11:57:49,596 [main][] com.mchange.v2.resourcepool.BasicResourcePool - trace [email protected] [managed: 5, unused: 4, excluded: 0] (e.g. [email protected]) 
DEBUG 2010-10-22 11:57:49,596 [main][] org.hibernate.impl.SessionImpl - after transaction completion 
DEBUG 2010-10-22 11:57:49,596 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Clearing transaction synchronization 
DEBUG 2010-10-22 11:57:49,596 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [[email protected]] for key [org[email protected]11b99c4] from thread [main] 
DEBUG 2010-10-22 11:57:49,612 [main][] org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [[email protected]] for key [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 31ghzi8b1mphf1c19l14qo|149105b, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.p6spy.engine.spy.P6SpyDriver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 31ghzi8b1mphf1c19l14qo|149105b, idleConnectionTestPeriod -> 200, initialPoolSize -> 5, jdbcUrl -> jdbc:mysql://localhost/daily?relaxAutoCommit=true&useUnicode=true&characterEncoding=UTF-8&jdbcCompliantTruncation=false&emulateLocators=true, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 50, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]] from thread [main] 
DEBUG 2010-10-22 11:57:49,612 [main][] org.hibernate.impl.SessionImpl - closing session 
DEBUG 2010-10-22 11:57:49,612 [main][] org.hibernate.jdbc.ConnectionManager - connection already null in cleanup : no action 

Bạn có thể thấy rằng nó nhận được nạp vào bộ nhớ cache, phiên Hibernate được mở ra và đóng lại và đỏ ửng.

Tôi sẽ đăng tệp nhật ký thứ hai của mình trong nhận xét bên dưới khi tôi đã đạt đến độ dài tối đa đã có của câu hỏi này. Điểm chính là, tất cả có vẻ ok, vấn đề thực sự duy nhất là nó sooo damn chậm.

Khi tôi tải 3000 đối tượng lần đầu tiên (ví dụ, nhấn db), nó sẽ mất khá nhiều chính xác giống như lần thứ hai (tức là, nhấn bộ nhớ cache).Như tôi đã nói, có phải là cos trên không đang mở và đóng kết nối, xả phiên, giao dịch với các giao dịch? Tôi không chắc. Nhưng nó khá tàn bạo ở mức nào. Giúp tôi stackoverflow ... bạn đang hy vọng duy nhất của tôi :)

+0

Tôi dường như không thể thêm một nhận xét khác hiển thị đủ chi tiết của tệp nhật ký thứ hai của tôi. Đủ để nói rằng đó là chính xác giống như lần đầu tiên ngoại trừ việc nó nhấn bộ nhớ cache. Ví dụ: đoạn mã: – Brian

+0

Nếu bạn cần đính kèm thêm nhật ký/mã, http://pastebin.com/ rất hữu ích – skaffman

+0

org.hibernate.engine.StatefulPersistenceContext - khởi tạo các bộ sưu tập không lười biếng org.hibernate.event.def.DefaultLoadEventListener - đối tượng được giải quyết trong bộ nhớ cache cấp hai: [com.model.SystemProperty # name_0] org.springframework.transaction.interceptor.TransactionInterceptor - Hoàn tất giao dịch cho [com.service.SystemPropertyManager.find] org.hibernate.transaction.JDBCTransaction - cam kết org.hibernate.impl.SessionImpl - tự động xóa phiên – Brian

Trả lời

2

Điểm chính là, tất cả đều ổn, vấn đề thực sự duy nhất là nó sooo damn chậm.

Chết tiệt chậm là một đơn vị đo lường chủ quan :)

Khi tôi tải 3000 đối tượng lần đầu tiên (ví dụ, nhấn db) phải mất khá nhiều giống hệt như lần thứ hai (tức là, nhấn cache).

Hiện số liệu, không có tất cả các chi phí khai thác gỗ (và cũng không P6Spy), sử dụng System.nanoTime()

long startTime = System.nanoTime(); 
// ... the code being measured ... 
long estimatedTime = System.nanoTime() - startTime; 

lẽ cũng cố gắng để thực hiện thử nghiệm của bạn bên trong một giao dịch duy nhất, sử dụng một đơn EntityManager, chỉ để nhìn thấy mọi thứ hoạt động như thế nào trong những điều kiện này.

Như tôi đã nói, có phải cos trên không đang mở và đóng kết nối, xóa phiên, xử lý giao dịch không? Tôi không chắc. Nhưng nó khá tàn bạo ở mức nào.

Không thể nói, bạn nên cấu hình mã của mình để xem thời gian được sử dụng (và cũng giám sát hoạt động GC).

Nhưng về mặt lý thuyết:

  • Các connection trong một Session là lười biếng (sẽ được mua chỉ khi có yêu cầu)
  • Thu hút một connection từ C3P0 nên được khá nhanh (không đáng kể)
  • Kể từ khi tổ chức của bạn được lưu vào bộ nhớ cache dưới dạng chỉ đọc, số flush phải là khá nhanh

Nói cách khác, tôi sẽ ' Tôi hy vọng các hoạt động trên sẽ tốn kém (vì vậy tôi sẽ tập trung vào các bộ phận xung quanh). Nhưng như tôi đã nói, hồ sơ (và theo dõi hoạt động GC).

+0

Tất cả các điểm hợp lý tốt Pascal. Ok, cho Chạy 1 (Nhấn DB), thời gian trung bình cho mỗi lần tải trên 3.000 trong nano giây 18,029,219 so với Chạy 2: 16,610,083. Bây giờ, nếu tôi loại bỏ giao dịch mùa xuân sẽ trở thành: 2.520.817 cho chạy 1 so với 498,435 cho chạy 2 mà hiển thị cải thiện tốt. Nhưng về cơ bản, nó ngụ ý rằng việc thêm các giao dịch mùa xuân là một chi phí đáng kể. Tôi sẽ hồ sơ ứng dụng như bạn đã đề xuất để xác nhận. Cảm ơn rất nhiều – Brian

+0

@Brian Tốt, ít nhất bạn biết những gì là ** không ** dành thời gian ngay bây giờ. Tôi chỉ ngạc nhiên rằng các giao dịch mùa xuân rất tốn kém, đặc biệt là do phương thức đọc của bạn không phải là '@ Transactional' được chú thích. Là một lưu ý phụ, bạn có thể tận hưởng [Chiến lược giao dịch: Hiểu các cạm bẫy giao dịch] (http://www.ibm.com/developerworks/java/library/j-ts1.html) (điều này sẽ không thực sự giúp bạn, nhưng đó là một đọc tốt). –

+1

Xin chào Pascal, cảm ơn nhận xét của bạn về bài viết này. Tôi cũng ngạc nhiên vì chúng quá đắt. Hồ sơ xác nhận rằng các giao dịch là vấn đề đắt tiền. Thay đổi tham số propogation thành Support từ Requires_New đã giúp một chút. Đánh giá cao sự giúp đỡ của bạn. Brian – Brian

4

Tôi khuyên bạn nên cố gắng thay thế mức sử dụng bộ nhớ cache cấp 2 bằng bộ nhớ cache đơn giản. Khi tôi kiểm tra hiệu suất bộ nhớ cache cấp 2 của Hibernate trong quá khứ, tôi nhận thấy nó không hiệu quả lắm. Điều này là do cách dữ liệu được lưu trữ được cấu trúc - tương tự như tập hợp kết quả - đó là dữ liệu dạng bảng đang được lưu trữ và không phải là các đối tượng. Điều này có nghĩa là nhiều yêu cầu bộ nhớ cache, mà hóa ra là tốn kém.

Để tách mã bộ nhớ cache khỏi logic tồn tại, tôi sử dụng AOP. Vì bạn sử dụng Spring nên việc này dễ dàng.

+0

Các phép đo được thực hiện bởi OP cho thấy bộ nhớ cache L2 hoàn toàn thực hiện công việc của mình, một cách hiệu quả. Đó không phải là vấn đề. Và trong khi phải bù nước các thực thể với dữ liệu dạng bảng từ bộ nhớ cache (so với lưu trữ các thực thể trong bộ nhớ đệm) có thể có một chi phí nhỏ, điều này chắc chắn vẫn không đáng kể so với truy cập cơ sở dữ liệu (thậm chí cục bộ). Tôi thực sự muốn có thông tin chi tiết về băng ghế dự bị của bạn, việc triển khai bộ nhớ cache được sử dụng, cấu hình, thứ tự độ lớn ... Theo kinh nghiệm của tôi, API cache Hibernate L2 khá hiệu quả. –

+0

@Pascal, Tại nơi làm việc của tôi, chúng tôi đã thực hiện một số thử nghiệm - Hibernate 2 cấp bộ nhớ đệm VS ứng dụng bộ nhớ đệm bằng cách sử dụng AOP interceptor chúng tôi đã viết, trên đầu trang của lớp dịch vụ của chúng tôi. Nghĩa là, bộ nhớ đệm cũng ngăn chặn bắt đầu một TX, và có được một kết nối.Tôi đã thực hiện một trong các thử nghiệm này, sau khi một nhà phát triển khác báo cáo hiệu suất kém từ bộ nhớ cache cấp 2. Các kết quả khá giống với những gì OP mô tả, và chiến lược bộ nhớ đệm ứng dụng cho thấy hiệu suất cao, theo thứ tự độ lớn. Tôi không còn có quyền truy cập vào kết quả nữa, nhưng thật dễ dàng để tạo lại ... –

+0

@Eran Rất thú vị, thêm điều này vào danh sách cần làm của tôi (mặc dù tôi vẫn cho rằng vấn đề có liên quan nhiều hơn đến việc phân định địa chỉ TX). Cảm ơn bạn đã trả lời. –

2

bạn có chắc là bạn không đánh cơ sở dữ liệu trong cuộc gọi bộ nhớ cache của mình không? cho phép hibernate sql debug logger để xem nếu nó đang làm đúng. Tôi chưa bao giờ sử dụng quản lý thực thể trước đây. Tôi luôn sử dụng phiên ngủ đông. Nếu bạn bật bộ đệm truy vấn, bạn vẫn phải thực hiện setCache (true) trong truy vấn ngủ đông. Nếu không, nó vẫn sẽ nhấn db. Chú thích @Cache trong thực thể chỉ lưu nó bằng id trong ehcache. Khi bạn đặt truy vấn của mình là có thể lưu vào bộ nhớ cache, khóa bộ nhớ cache là truy vấn của bạn và kết quả là id tổ chức, sau đó nó sẽ cố gắng giải quyết thực thể trong ehcache theo id.

2

Thử nghiệm của bạn sử dụng trực tiếp EntityManager mà không cần giao dịch. Một EntityManager được đưa vào một đơn vị công việc, thường là một giao dịch đơn lẻ. Bạn có thể buộc phải có giao dịch mới. tra cứu trong nhóm kết nối DB cho mọi lệnh gọi tìm.

Đây là những gì tôi sẽ đề nghị:

  • sử dụng read-only giao dịch cho lưu phi phương pháp thay vì không có ranh giới TX
  • quấn đậu DataSource của bạn trong một LazyConnectionDataSourceProxy để tránh nhận được một kết nối nếu bạn don 't thực sự cần phải nói chuyện với cơ sở dữ liệu của bạn (ví dụ trong trường hợp của một bộ nhớ cache hit)
  • cập nhật thử nghiệm của bạn để nói chuyện với bean dịch vụ của bạn thay vì trực tiếp sử dụng một EntityManager.
Các vấn đề liên quan