A simple Spring application that uses standard Hikari connector and Eclipselink as JPA provider takes double time (aprox) if executed using embeded Tomcat. I also tried hibernate with similar result.
@Entity
@Table(name = "chats")
public class Chat{
@Id
private String id;
public Chat() { }
public String getId() {
return id;
}
}
//Repo
public interface ChatRepository extends JpaRepository<Chat, String> {
}
Configuration:
@Configuration
public class EclipseLinkJpaConfigurationHikari {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("project");
em.setJpaVendorAdapter(new EclipseLinkJpaVendorAdapter());
hace que selecciones uno de persitance.xml
Map<String, Object> properties = new HashMap<>();
properties.put("eclipselink.weaving", "false");
properties.put("eclipselink.logging.level", "INFO");
properties.put("eclipselink.ddl-generation", "none");
em.setJpaPropertyMap(properties);
return em;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
Controller
@RestController
@RequestMapping("/")
public class TestController {
private final ChatRepository chatRepository;
@PersistenceContext
EntityManager em;
public TestController(ChatRepository chatRepository) {
this.chatRepository = chatRepository;
}
@Transactional
@GetMapping("/test")
public String test() {
long t = System.currentTimeMillis();
for( int x=1 ; x <1500;x++){
List<Chat> chats = chatRepository.findAll();
Chat c = chats.get(0);
}
long time = (System.currentTimeMillis() - t);
return t + "ms";
}
}
application.properties
spring.application.name=TestConnection
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.connection.provider_class=com.zaxxer.hikari.hibernate.HikariConnectionProvider
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost/db?useSSL=false
spring.datasource.username=xxx
spring.datasource.password=yyy
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.connection-timeout=50000
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=900000
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.pool-name=ConnPool
spring.datasource.hikari.connection-test-query=select 1 from dual
spring.datasource.hikari.data-source-properties.cachePrepStmts=true
spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250
spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048
spring.datasource.hikari.data-source-properties.useServerPrepStmts=true
spring.datasource.hikari.data-source-properties.useLocalSessionState=true
spring.datasource.hikari.data-source-properties.rewriteBatchedStatements=true
spring.datasource.hikari.data-source-properties.cacheResultSetMetadata=true
spring.datasource.hikari.data-source-properties.cacheServerConfiguration=true
spring.datasource.hikari.data-source-properties.elideSetAutoCommits=true
spring.datasource.hikari.data-source-properties.maintainTimeStats=false
logging.level.com.zaxxer.hikari.HikariConfig=DEBUG
logging.level.com.zaxxer.hikari=TRACE
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
If I execute this request, the processing times are:
External tomcat -> 494ms, 232msms, 217ms, 193ms, 198ms, 214ms, 155ms, 155ms, 107ms (stabilizes around 100ms any further request )
Embedded tomcat -> 363ms, 200ms, 189ms , 207ms, 201ms, 194ms, 193ms, 185ms, 192ms (stabilizes around 195ms any further request )
What is going on? I am using the same configuration, same tomcat version, same libraries from gradle. After first request cache starts working but it seems to work better for external tomcat. In general, the performance for any request that access the dabase is twice faster when using external tomcat.
Note: if I remove @Transactional from controller's method, processing time is even larger, from 200ms to 280ms (embedded) and from 100ms to 150ms (external tomcat).
After several days of investigation I found out the reason why the application had different performance while using external tomcat or the configuration provided by Intellij Idea.
After enabling the option Disable launch optimization (-XX:TieredStopAtLevel=1), the performance is as good as executed by external Tomcat.