Simple run-time profiling 
Joachim Van der Auwera 
Eliwan bvba 
#Devox#xD #Vr1tP4r o#fYilionugrTag @YourTwitterHa@ndjoleachimvda
Simple? 
● Usable in production 
● Limited run-time overhead 
● Short-term and long-term feedback 
● No additional resources 
● You control the aggregations 
#Devoxx #rtProfiling @joachimvda
++++ REST calls: 
| 1558 | 30241 | 19.41 
group | count | total time | avg time 
BestandService:save | 4 | 42 | 10.50 
TaakZoekService:search | 1 | 305 | 305.00 
VaststellingServiceV2:getNew | 40 | 383 | 9.58 
VaststellingServiceV2:save | 44 | 14225 | 323.30 
VaststellingsverslagService:voorbereiden | 12 | 1215 | 101.25 
++++ JDBC calls (by method): 
| 109707 | 9814 | 0.09 
group | count | total time | avg time 
Connection.clearWarnings | 1761 | 5 | 0.00 
Connection.commit | 1738 | 1342 | 0.77 
Driver.connect | 15 | 58 | 3.87 
PreparedStatement.executeQuery | 7299 | 4727 | 0.65 
PreparedStatement.executeUpdate | 1358 | 583 | 0.43 
++++ JDBC calls (by REST service): 
| 109707 | 9814 | 0.09 
group | count | total time | avg time 
| 1395 | 243 | 0.17 
BestandService:save | 224 | 15 | 0.07 
TaakZoekService:search | 71 | 13 | 0.18 
VaststellingServiceV2:getNew | 601 | 49 | 0.08 
VaststellingServiceV2:save | 21803 | 3543 | 0.16 
VaststellingsverslagService:voorbereiden | 10526 | 489 | 0.05 
#Devoxx #rtProfiling @joachimvda
++++ data grouped by REST call: 
group | count | total time | avg time | %total 
TaakZoekService:search | 1 | 305 | 305.00 | 100.00 
JDBC | 71 | 13 | 0.18 | 4.26 
Elasticsearch | 2 | 92 | 46.00 | 30.16 
gateway | 2 | 0 | 0.00 | 0.00 
* rest | 1558 | 30241 | 19.41 | 100.00 
JDBC | 108312 | 9571 | 0.09 | 31.65 
Elasticsearch | 464 | 3429 | 7.39 | 11.34 
gateway | 4058 | 53 | 0.01 | 0.18 
VaststellingServiceV2:getNew | 40 | 383 | 9.58 | 100.00 
JDBC | 601 | 49 | 0.08 | 12.79 
Elasticsearch | 0 | 0 | 0.00 | 0.00 
gateway | 80 | 1 | 0.01 | 0.26 
* not REST | 0 | 958 | 0.00 | 100.00 
JDBC | 1395 | 243 | 0.17 | 25.37 
Elasticsearch | 6 | 715 | 119.17 | 74.63 
gateway | 0 | 0 | 0.00 | 0.00 
VaststellingsverslagService:voorbereiden | 12 | 1215 | 101.25 | 100.00 
JDBC | 10526 | 489 | 0.05 | 40.25 
Elasticsearch | 76 | 303 | 3.99 | 24.94 
gateway | 24 | 0 | 0.00 | 0.00 
#Devoxx #rtProfiling @joachimvda
How to get details 
● Logged and cleared daily 
– just before midnight 
● REST call to get current counters 
– Reset option 
#Devoxx #rtProfiling @joachimvda
How? Containers 
● RESTEasy interceptor registers REST calls 
● Profiling containers 
– Summerize details using LMAX Disruptor 
<bean name="restProfilingRegistrar" 
class="be.eliwan.profiling.service.ProfilingContainer"> 
<property name="ringSize" value="128" /> 
</bean> 
<bean name="jdbcServiceProfiling" class="be.eliwan.profiling.service.ProfilingContainer"> 
<property name="ringSize" value="128" /> 
</bean> 
<bean name="jdbcMethodProfiling" class="be.eliwan.profiling.service.ProfilingContainer"> 
<property name="ringSize" value="128" /> 
</bean> 
#Devoxx #rtProfiling @joachimvda
How? JDBC 
● RESTEasy interceptor which registers REST calls 
● JDBC URL: 
db.url=profiling:jdbc:postgresql://localhost:5432/db 
@Autowired @Qualifier("jdbcMethodProfiling") 
private ProfilingContainer jdbcMethodProfiling; 
@Autowired @Qualifier("jdbcServiceProfiling") 
private ProfilingContainer jdbcServiceProfiling; 
public void afterPropertiesSet() { ProfilingDriver.addListener(this); } 
@Override 
public void register(String group, long durationMillis) { 
jdbcMethodProfiling.register(group, durationMillis); 
jdbcServiceProfiling.register(MyRestInterceptor.PROFILE_GROUP.get(), durationMillis); 
} 
#Devoxx #rtProfiling @joachimvda
How? AOP for Gateways 
<bean name="profiling.GatewayProfilingInterceptor" 
class="be.vlaanderen.awv.dc.profiling.GatewayProfilingInterceptor"> 
<property name="byMethodProfilingContainer" ref="gatewayMethodProfiling" /> 
<property name="byServiceProfilingContainer" ref="gatewayServiceProfiling" /> 
</bean> 
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
<property name="beanNames" value="*GatewayMock,*Gateway,*GatewayReal"/> 
<property name="interceptorNames"> 
<list> 
<value>profiling.GatewayProfilingInterceptor</value> 
</list> 
</property> 
</bean> 
public Object invoke(MethodInvocation invocation) throws Throwable { 
long start = System.currentTimeMillis(); 
Object result = invocation.proceed(); 
long duration = System.currentTimeMillis() ­start; 
byServiceProfiling.register(MyRestInterceptor.PROFILE_GROUP.get(), duration); 
byMethodProfiling.register(invocation.getMethod().getDeclaringClass().getSimpleName() 
+ ":" + invocation.getMethod().getName(), duration); 
return result; 
} 
#Devoxx #rtProfiling @joachimvda
Alternatives? 
– Xrebel 
– Metrics (dropwizard) 
#Devoxx #rtProfiling @joachimvda
XRebel 
● Agent: -javaagent:/path/to/xrebel.jar 
● Development 
●Warnings, thresholds 
– JDBC 
– Session size/increase 
#Devoxx #rtProfiling @joachimvda
#Devoxx #rtProfiling @joachimvda
#Devoxx #rtProfiling @joachimvda
metrics 
● Registry 
– Meter, Gauge, Counter, Histogram, Timer 
● Health checks 
● Reporting 
– JMX, servlet, console, csv, log, ganglia, graphite 
#Devoxx #rtProfiling @joachimvda
metrics 
#Devoxx #rtProfiling @joachimvda
metrics 
#Devoxx #rtProfiling @joachimvda
metrics 
InstrumentedFilter 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
throws IOException, ServletException { 
AbstractInstrumentedFilter.StatusExposingServletResponse wrappedResponse = ... 
this.activeRequests.inc(); 
Context context = this.requestTimer.time(); 
try { 
chain.doFilter(request, wrappedResponse); 
} finally { 
context.stop(); 
this.activeRequests.dec(); 
this.markMeterForStatusCode(wrappedResponse.getStatus()); 
} 
} 
#Devoxx #rtProfiling @joachimvda
Thank you! 
Projects: 
http://eliwan.be/oss/ew-profiling 
http://zeroturnaround.com/software/xrebel/ 
https://dropwizard.github.io/metrics/ 
Joachim Van der Auwera 
joachim@eliwan.be 
#Devoxx #rtProfiling @joachimvda

Simple run-time profiling quickie devoxx14

  • 1.
    Simple run-time profiling Joachim Van der Auwera Eliwan bvba #Devox#xD #Vr1tP4r o#fYilionugrTag @YourTwitterHa@ndjoleachimvda
  • 2.
    Simple? ● Usablein production ● Limited run-time overhead ● Short-term and long-term feedback ● No additional resources ● You control the aggregations #Devoxx #rtProfiling @joachimvda
  • 3.
    ++++ REST calls: | 1558 | 30241 | 19.41 group | count | total time | avg time BestandService:save | 4 | 42 | 10.50 TaakZoekService:search | 1 | 305 | 305.00 VaststellingServiceV2:getNew | 40 | 383 | 9.58 VaststellingServiceV2:save | 44 | 14225 | 323.30 VaststellingsverslagService:voorbereiden | 12 | 1215 | 101.25 ++++ JDBC calls (by method): | 109707 | 9814 | 0.09 group | count | total time | avg time Connection.clearWarnings | 1761 | 5 | 0.00 Connection.commit | 1738 | 1342 | 0.77 Driver.connect | 15 | 58 | 3.87 PreparedStatement.executeQuery | 7299 | 4727 | 0.65 PreparedStatement.executeUpdate | 1358 | 583 | 0.43 ++++ JDBC calls (by REST service): | 109707 | 9814 | 0.09 group | count | total time | avg time | 1395 | 243 | 0.17 BestandService:save | 224 | 15 | 0.07 TaakZoekService:search | 71 | 13 | 0.18 VaststellingServiceV2:getNew | 601 | 49 | 0.08 VaststellingServiceV2:save | 21803 | 3543 | 0.16 VaststellingsverslagService:voorbereiden | 10526 | 489 | 0.05 #Devoxx #rtProfiling @joachimvda
  • 4.
    ++++ data groupedby REST call: group | count | total time | avg time | %total TaakZoekService:search | 1 | 305 | 305.00 | 100.00 JDBC | 71 | 13 | 0.18 | 4.26 Elasticsearch | 2 | 92 | 46.00 | 30.16 gateway | 2 | 0 | 0.00 | 0.00 * rest | 1558 | 30241 | 19.41 | 100.00 JDBC | 108312 | 9571 | 0.09 | 31.65 Elasticsearch | 464 | 3429 | 7.39 | 11.34 gateway | 4058 | 53 | 0.01 | 0.18 VaststellingServiceV2:getNew | 40 | 383 | 9.58 | 100.00 JDBC | 601 | 49 | 0.08 | 12.79 Elasticsearch | 0 | 0 | 0.00 | 0.00 gateway | 80 | 1 | 0.01 | 0.26 * not REST | 0 | 958 | 0.00 | 100.00 JDBC | 1395 | 243 | 0.17 | 25.37 Elasticsearch | 6 | 715 | 119.17 | 74.63 gateway | 0 | 0 | 0.00 | 0.00 VaststellingsverslagService:voorbereiden | 12 | 1215 | 101.25 | 100.00 JDBC | 10526 | 489 | 0.05 | 40.25 Elasticsearch | 76 | 303 | 3.99 | 24.94 gateway | 24 | 0 | 0.00 | 0.00 #Devoxx #rtProfiling @joachimvda
  • 5.
    How to getdetails ● Logged and cleared daily – just before midnight ● REST call to get current counters – Reset option #Devoxx #rtProfiling @joachimvda
  • 6.
    How? Containers ●RESTEasy interceptor registers REST calls ● Profiling containers – Summerize details using LMAX Disruptor <bean name="restProfilingRegistrar" class="be.eliwan.profiling.service.ProfilingContainer"> <property name="ringSize" value="128" /> </bean> <bean name="jdbcServiceProfiling" class="be.eliwan.profiling.service.ProfilingContainer"> <property name="ringSize" value="128" /> </bean> <bean name="jdbcMethodProfiling" class="be.eliwan.profiling.service.ProfilingContainer"> <property name="ringSize" value="128" /> </bean> #Devoxx #rtProfiling @joachimvda
  • 7.
    How? JDBC ●RESTEasy interceptor which registers REST calls ● JDBC URL: db.url=profiling:jdbc:postgresql://localhost:5432/db @Autowired @Qualifier("jdbcMethodProfiling") private ProfilingContainer jdbcMethodProfiling; @Autowired @Qualifier("jdbcServiceProfiling") private ProfilingContainer jdbcServiceProfiling; public void afterPropertiesSet() { ProfilingDriver.addListener(this); } @Override public void register(String group, long durationMillis) { jdbcMethodProfiling.register(group, durationMillis); jdbcServiceProfiling.register(MyRestInterceptor.PROFILE_GROUP.get(), durationMillis); } #Devoxx #rtProfiling @joachimvda
  • 8.
    How? AOP forGateways <bean name="profiling.GatewayProfilingInterceptor" class="be.vlaanderen.awv.dc.profiling.GatewayProfilingInterceptor"> <property name="byMethodProfilingContainer" ref="gatewayMethodProfiling" /> <property name="byServiceProfilingContainer" ref="gatewayServiceProfiling" /> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames" value="*GatewayMock,*Gateway,*GatewayReal"/> <property name="interceptorNames"> <list> <value>profiling.GatewayProfilingInterceptor</value> </list> </property> </bean> public Object invoke(MethodInvocation invocation) throws Throwable { long start = System.currentTimeMillis(); Object result = invocation.proceed(); long duration = System.currentTimeMillis() ­start; byServiceProfiling.register(MyRestInterceptor.PROFILE_GROUP.get(), duration); byMethodProfiling.register(invocation.getMethod().getDeclaringClass().getSimpleName() + ":" + invocation.getMethod().getName(), duration); return result; } #Devoxx #rtProfiling @joachimvda
  • 9.
    Alternatives? – Xrebel – Metrics (dropwizard) #Devoxx #rtProfiling @joachimvda
  • 10.
    XRebel ● Agent:-javaagent:/path/to/xrebel.jar ● Development ●Warnings, thresholds – JDBC – Session size/increase #Devoxx #rtProfiling @joachimvda
  • 11.
  • 12.
  • 13.
    metrics ● Registry – Meter, Gauge, Counter, Histogram, Timer ● Health checks ● Reporting – JMX, servlet, console, csv, log, ganglia, graphite #Devoxx #rtProfiling @joachimvda
  • 14.
  • 15.
  • 16.
    metrics InstrumentedFilter publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { AbstractInstrumentedFilter.StatusExposingServletResponse wrappedResponse = ... this.activeRequests.inc(); Context context = this.requestTimer.time(); try { chain.doFilter(request, wrappedResponse); } finally { context.stop(); this.activeRequests.dec(); this.markMeterForStatusCode(wrappedResponse.getStatus()); } } #Devoxx #rtProfiling @joachimvda
  • 17.
    Thank you! Projects: http://eliwan.be/oss/ew-profiling http://zeroturnaround.com/software/xrebel/ https://dropwizard.github.io/metrics/ Joachim Van der Auwera joachim@eliwan.be #Devoxx #rtProfiling @joachimvda