Tuesday, November 9, 2010

"Terracotta Fairy" brings BigMemory for Java users

I used to discuss about the Java goodness with my friends working on native platforms. But they always used to crib about Java., its slower, max latency is high, Garbage Collection(GC) ruins the user experience and tuning GC is a NIGHTMARE! Didn't had anything to defend on these points :(, as its the fact.
Garbage Collection kills the Java Application.

Being in Java world, loading 100G of data on java heap sounds crazy. I did some experiments to load 100G of data on single JVM. Even for Read-only case (no writes/updates to reduce the GC problems), it wont fit in 150G of heap.

On tuning GC, reducing Young Gen Space, reducing Survivor Ratio, etc, didnt helped much. The test just gets into back-to-back full GCs, killing the application throughput and latency. To get it working had to give 200 GB of heap and it performed so badly.

Then I wished, wont it be really nice to fit whole data, without any GC problems. "Terracotta Fairy" listened to us and here we have BigMemory Ehcache. BigMemory is a GC murder weapon from Terracotta, like an AA12 ShotGun.
Now, we can store 350GB of data with no GC .
Can you believe this !! Literally NO GC!!

Wanna see it with your eyes, here are the charts from the battle of Troy - On-Heap vs BigMemory.

The following charts shows the Ehcache use case which I thought would be fair enough. Ehcache being most widely used Java cache already outperforms other available cache. Didn't wanted to choose best use case for BigMemory i.e. 100% writes NOR the best for On-Heap i.e. Read-only. The read/write ratio is 50% reads and 50% writes. The hot set is that 90% of the time cache.get() will access 10% of the key set. This is representative of the the familiar Pareto distribution that is very commonly observed. The Test loads up full data in the Ehcache and then starts doing r/w operations on it.

These test machine was a Cisco UCS box running with Intel(R) Xeon(R) Processors. It had 6 quad-core 2.93Ghz Xeon(R) cpus for a total of 24 cores, with 378GB (396191024 kB) RAM, running RHEL5.1 with Sun JDK 1.6.0_21 in 64 bit mode.

For BigMemory testcase, had just 2G of java heap even when loading 350 GB of data while for OnHeap testcases, had java heap of twice the data size.





This chart compares the Largest Full GC duration occurred during the full run of the test. The numbers are taken from verbose GC logs.
If you take a microscope, then you can see there is a small green bar beside huge Al-burj tower types red bars. Those are GC duration for BigMemory :). Merely going above 1.2 sec, BigMemory surely kills Garbage Collection and removes the stigma on the Java.



This charts compares the Max Latency during the test run. As expected, this should be equal to the Max Full GC duration, since GC just blocks the application. BigMemory fairly defeats OnHeap here. Anyway who will like to have 4-5 mins of pause in his application, not me atleast !



Lets see how BigMemory throughput behaves with increase in the data size. The chart above shows that after certain point the throughput remains unaffected by the data size. Also, did a run with 350G of data and the tps/latency was constant. (Did we ever thought of caching 350G of data in an application :O). The drop in tps from 512M - 4G of data is because for smaller data size, ehcache stores the entries on heap (remember test is 10% hotset, so till hotset is on Heap & SMALL enough to fit, its faster). And we don't have much GC occurring for smaller data size.



Latency, the most worried about factor for user experience. We don't want our users to wait for 5 secs, because first impression is the last impression. The charts show the mean latency for the tests. Note that all those numbers are in micro-seconds. So they are anyway less than 0.5 secs, meeting your deadliest SLAs. BigMemory wins undoubtedly.



Here comes biggest test for BigMemory. Why will someone use BigMemory if it doesn't performs good enough as On Heap. We can't just ignore throughput for latency. We can see the BigMemory throughput numbers outperforms On Heap numbers here also. On-Heap throughput just goes on decreasing as full GCs would be killing the test. Imagine pausing for 4 mins during the test, will surely reduce the average throughput significantly.
Note: The test which I ran is 50% writes, so we might be overshadowing the onHeap throughput but 10% writes throughput were also comparable.



Mean latency graphs also says the same story which I have been saying all over my blog. BigMemory outperforms OnHeap :)


Do-it-yourself: Here is the svn link to the test, a Maven-based performance comparisons between different store configurations.
Note: You will need to get a demo license key and install it as discussed above to run the test.

So bottom line:
If you are fed-up of GCs, check BigMemory.
If you want to cache 350GB of data, check BigMemory.
If you want to use most AWESOME java cache ever made, check BigMemory.


If you like the post, vote it up on dzone. :)

Wednesday, September 30, 2009

Fire up Firefox

Make you firefox rock and change the way you browse. Optimize your bandwidth. Get what you want, exclude unwanted. Add-ons that change firefox
  1. Adblock Plus - This one rocks than any other damn plugin. Blocks all the ads and you can put your own regex to block
  2. All-in-One Gestures - Make gestures on Firefox to do what you want. Make a gesture zoom-in a image, open tab, much more.
  3. Tweak Network - Have bandwidth still firefox downloading pages slowly. Install this and change to power mode.
  4. Tiny Menu - Want more screen space for webpage than menus, etc.
  5. Flashgot - Strictly for heavy downloaders. Configure to use Leechget and fire up your downloading.
  6. Speed Dial - Speed dial your fav sites, instead of typing and wasting time.
  7. Session Manager - Did you ever wanted to recover your last session, get your searches and pages back. Try this.
  8. RAM Back - Firefox eating up your RAM. Get your RAM back.
  9. Web Developer - Using GPRS/slow connection, dont want to waste your bandwidth on images etc, block them using this. Clear cookies, and more for a web developer.
  10. IE Tab - Few of damned sites work on IE only, use this to get rid of them. Configure to use IE rendering engine everytime you visit those sites.
  11. Firebug - Like developing/inspecting web applications, wanted to know whats slowing your page. Check this out!!!
  12. Fox Clocks - Boss in different continent. Get this to get time there.
  13. Cooliris - iPhone interface to browse images
  14. Better Gmail2 - Gmail users try this out. Nice one!!!
  15. ForecastFox - Get forecast on your firefox.

Tuesday, September 29, 2009

Glassfish with Standalone Terracotta Ehcache

While running standalone ehcache sample app (https://svn.terracotta.org/repo/forge/projects/tim-ehcache/branches/tc-3.1/tim-ehcache-1.7-sample) with glassfish server, glassfish client was able to make connection to tc server but fails with java.nio.channels.CancelledKeyException.


terracotta-server.logs

2009-09-25 12:34:56,037 [L2_L1:TCComm Main Selector Thread (listen 0:0:0:0:0:0:0:0:9510)] INFO com.tc.net.protocol.transport.ServerMessageTransport - ConnectionID(14.e02630feb1904743b5782b6324fa26a2): Attaching new connection: com.tc.net.core.TCConnectionJDK14@24008846: connected: true, closed: false local=10.0.4.158:9510 remote=10.0.4.158:53243 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=1ms [28 read, 0 write]
2009-09-25 12:34:56,038 [L2_L1:TCComm Main Selector Thread (listen 0:0:0:0:0:0:0:0:9510)] WARN com.tc.net.core.CoreNIOServices - Skipping modifyInterest - WRITE on com.tc.net.core.TCConnectionJDK14@24008846: connected: true, closed: false local=10.0.4.158:9510 remote=10.0.4.158:53243 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=0ms [28 read, 0 write]
2009-09-25 12:34:56,038 [L2_L1:TCComm Main Selector Thread (listen 0:0:0:0:0:0:0:0:9510)] INFO com.tc.net.core.TCWorkerCommManager - Selecting [L2_L1:TCWorkerComm # 0, wt:0] from [[L2_L1:TCWorkerComm # 0, wt:0], [L2_L1:TCWorkerComm # 1, wt:0]]
2009-09-25 12:35:06,041 [L2_L1:TCWorkerComm # 0] WARN com.tc.net.core.CoreNIOServices - Exception trying to shutdown socket output: Transport endpoint is not connected
2009-09-25 12:35:06,042 [L2_L1:TCWorkerComm # 0] WARN com.tc.net.protocol.transport.ServerMessageTransport - ConnectionID(14.e02630feb1904743b5782b6324fa26a2): CLOSE EVENT : com.tc.net.core.TCConnectionJDK14@24008846: connected: false, closed: true local=10.0.4.158:9510 remote=10.0.4.158:53243 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=10004ms [81 read, 81 write]. STATUS : START
2009-09-25 12:35:06,042 [L2_L1:TCWorkerComm # 0] WARN com.tc.net.protocol.transport.ServerMessageTransport - ConnectionID(14.e02630feb1904743b5782b6324fa26a2): closing down connection - com.tc.net.core.TCConnectionJDK14@24008846: connected: false, closed: true local=10.0.4.158:9510 remote=10.0.4.158:53243 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=10004ms [81 read, 81 write]

terracotta-client.logs

2009-09-25 12:34:56,035 [httpSSLWorkerThread-8081-0] INFO com.tc.net.protocol.transport.ClientMessageTransport - ConnectionID(-1.ffffffffffffffffffffffffffffffff): Attaching new connection: com.tc.net.core.TCConnectionJDK14@13859800: connected: true, closed: false local=10.0.4.158:53243 remote=10.0.4.158:9510 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=1ms [0 read, 0 write]

2009-09-25 12:35:06,044 [L1_L2:TCComm Main Selector Thread (listen 0:0:0:0:0:0:0:0:50565)] WARN com.tc.net.protocol.transport.ClientMessageTransport - ConnectionID(-1.ffffffffffffffffffffffffffffffff): CLOSE EVENT : com.tc.net.core.TCConnectionJDK14@13859800: connected: false, closed: true local=10.0.4.158:53243 remote=10.0.4.158:9510 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=10009ms [0 read, 81 write]. STATUS : SYN_SENT
2009-09-25 12:35:06,044 [L1_L2:TCComm Main Selector Thread (listen 0:0:0:0:0:0:0:0:50565)] WARN com.tc.net.protocol.transport.ClientMessageTransport - ConnectionID(-1.ffffffffffffffffffffffffffffffff): closing down connection - com.tc.net.core.TCConnectionJDK14@13859800: connected: false, closed: true local=10.0.4.158:53243 remote=10.0.4.158:9510 connect=[Fri Sep 25 12:34:56 PDT 2009] idle=10009ms [0 read, 81 write]
2009-09-25 12:35:06,044 [httpSSLWorkerThread-8081-0] WARN com.terracottatech.console - Timeout connecting to server: Timeout of 10000 milliseconds occured
2009-09-25 12:35:06,044 [L1_L2:TCComm Main Selector Thread (listen 0:0:0:0:0:0:0:0:50565)] WARN com.tc.net.core.CoreNIOServices - java.nio.channels.CancelledKeyException occured

glassfish logs

[#|2009-09-25T12:37:21.157-0700|WARNING|sun-appserver9.1|javax.enterprise.system.stream.err|_ThreadID=15;_ThreadName=httpSSLWorkerThread-8081-0;_RequestID=f34b40b7-5245-48d5-9df8-03fb63e09a7c;|2009-09-25 12:37:21,157 WARN - Timeout connecting to server: Timeout of 10000 milliseconds occured
[#|2009-09-25T12:37:36.169-0700|WARNING|sun-appserver9.1|javax.enterprise.system.stream.err|_ThreadID=15;_ThreadName=httpSSLWorkerThread-8081-0;_RequestID=f34b40b7-5245-48d5-9df8-03fb63e09a7c;|2009-09-25 12:37:36,169 WARN - Timeout connecting to server: Timeout of 10000 milliseconds occured



This could be solved by adding the following jvm option to glassfish domain.xml.

<jvm-options>-Dcom.sun.enterprise.server.ss.ASQuickStartup=false</jvm-options>

Multiple Instances of Weblogic on same node

While QAing terracotta standalone ehcache and terracottta standalone hibernate, we need to test the kit with different containers such as tomcat, jetty, glassfish, weblogic, jboss. It is good if we have all setup in same machine. When trying to install weblogic server on same machine, we can start a managed server on the same machine or create another domain and use terracotta server to cluster it.

I came across a helpful blog to create new domains and a PDF file attached to it.
http://blogs.oracle.com/learnwithpavan/2008/09/any_application_server_need_to.html
http://blogs.oracle.com/learnwithpavan/mydocs/weblogic/Creating%20a%20new%20Weblogic%20Domain.pdf
On step 7 as mentioned in the pdf, we can change the listen port to any other unused port like 8001 and you are good to go.

We can start two different domain weblogic servers on same machine now.

Getting JAR version programmatically

While QAing Ehcache, just to make sure that we have correct JAR loaded and tested, we tried to get the version of JAR from the pom.properties in ehcache-core-xxx.jar. Following code help us accessing the jar file for a particular class, and subsequently the files in it.

 public String getEhcacheVersion(){
String ehcacheVersion = null;
JarInputStream jarIn = null;
File file = null;
try {
file = new File(Ehcache.class.getProtectionDomain()
.getCodeSource().getLocation().toURI());
jarIn = new JarInputStream(new FileInputStream(file));
JarEntry entry;

while ((entry = jarIn.getNextJarEntry()) != null) {
if (entry.getName().toUpperCase().equalsIgnoreCase("META-INF/maven/"
+"net.sf.ehcache/ehcache-core/pom.properties")){

BufferedReader reader = new BufferedReader(new InputStreamReader(jarIn));
String line = null;
while ((line = reader.readLine()) != null) {
if(line.startsWith("version")){
ehcacheVersion=line;
break;
}
}
}
}
}
catch (URISyntaxException e1) {e1.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
finally {
if (jarIn != null)
try { jarIn.close(); } catch (Exception e) {}
}
return
ehcacheVersion;
}
mvn puts data into META-INF/maven/net.sf.ehcache/ehcache-core/pom.properties

#Generated by Maven
#Thu Sep 24 12:20:41 PDT 2009
version=xxx
groupId=net.sf.ehcache
artifactId=ehcache-core

We can also use MANIFEST.MF to get required data.

Friday, September 18, 2009

Hibernate 3 with Weblogic results in ClassNotFoundException HqlToken

When using Hibernate 3 with Weblogic Server 10.3, I was getting the following exception when deploying Terracotta h2lc tutorial application.

org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [from org.hibernate.tutorial.domain.Person p]
at org.hibernate.hql.ast.HqlLexer.panic(HqlLexer.java:80)
at antlr.CharScanner.setTokenObjectClass(CharScanner.java:340)
at org.hibernate.hql.ast.HqlLexer.setTokenObjectClass(HqlLexer.java:54)
at antlr.CharScanner.(CharScanner.java:51)
at antlr.CharScanner.(CharScanner.java:60)
at org.hibernate.hql.antlr.HqlBaseLexer.(HqlBaseLexer.java:56)
at org.hibernate.hql.antlr.HqlBaseLexer.(HqlBaseLexer.java:53)
at org.hibernate.hql.antlr.HqlBaseLexer.(HqlBaseLexer.java:50)
at org.hibernate.hql.ast.HqlLexer.(HqlLexer.java:49)
at org.hibernate.hql.ast.HqlParser.getInstance(HqlParser.java:67)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:268)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:182)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:94)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1651)
at org.hibernate.tutorial.web.EventManagerServlet.init(EventManagerServlet.java:28)
at javax.servlet.GenericServlet.init(GenericServlet.java:241)
at weblogic.servlet.internal.StubSecurityHelper$ServletInitAction.run(StubSecurityHelper.java:283)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.StubSecurityHelper.createServlet(StubSecurityHelper.java:64)
at weblogic.servlet.internal.StubLifecycleHelper.createOneInstance(StubLifecycleHelper.java:58)
at weblogic.servlet.internal.StubLifecycleHelper.(StubLifecycleHelper.java:48)
at weblogic.servlet.internal.ServletStubImpl.prepareServlet(ServletStubImpl.java:521)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:235)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
at org.hibernate.tutorial.web.SessionInterceptor.doFilter(SessionInterceptor.java:41)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3496)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)

This seems to be a known issue https://www.hibernate.org/250.html#A25

Solution:

For WAR files, Add WEB-INF/weblogic.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>

Note: All the dependencies should be in the WAR
Warning: The above code can lead you to some ClassCastExceptions which is due to conflicting classes in WEB-INF/lib and system libs.
For me, it threw
java.lang.ClassCastException: weblogic.xml.jaxp.RegistryXMLReader cannot be cast to org.xml.sax.XMLReader  
at org.xml.sax.helpers.XMLReaderFactory.loadClass(Unknown Source)
at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(Unknown Source)
at org.dom4j.io.SAXHelper.createXMLReader(SAXHelper.java:83)
at org.dom4j.io.SAXReader.createXMLReader(SAXReader.java:894)
at org.dom4j.io.SAXReader.getXMLReader(SAXReader.java:715)

so needed to remove xml-apis jar from WEB-INF/lib.

The above solution is for Web Archives only. For other applications, we might need to add the following code. Didnt tested this though :)

<?xml version="1.0" encoding="ISO-8859-1"?>
<weblogic-application>
<prefer-application-packages>
<package-name>antlr.*</package-name>
</prefer-application-packages>
</weblogic-application>

Monday, March 2, 2009

Examinator 16 Nodes - Test Run Results

Below is the result of the script for 16 tomcat server runs with Terracotta server. The MySQL server has been cleaned and restarted before the test run.

Analyzing Jmeter logs ...
==============================
502 Error = 0
503 Error = 0
DEV-1929 = 0

Response Time
==============================
Average JMeter response time [e1s31] = 96.8721
Average JMeter response time = 35.7428

Server Latency Stats
=====================
Average = 4.76148 ms
Minimum = 0 ms
Maximum = 7036 ms
Std. Deviation = 59.4633
Total # of Requests = 5407000
Nodes = 16

L2 Configuration
==============================
TC_OPTS=-Xms4g -Xmx4g -XX:+DisableExplicitGC -XX:-TraceClassUnloading -XX:TargetSurvivorRatio=90 -Xss128k -XX:+AggressiveHeap -Dcom.tc.l2.objectmanager.fault.logging.enabled=true -Dcom.tc.l2.cachemanager.logging.enabled=true -Dcom.tc.l2.berkeleydb.je.maxMemoryPercent=15 -XX:SurvivorRatio=12

L1 Configuration
==============================
CATALINA_OPTS=-Duse.async.processing=true -Dasync.concurrency=5 -Dcom.tc.hibernate.useFineGrainedLocking=false -Dcom.tc.l1.cachemanager.enabled=false -Duse.pojoizer=true -Xms1024m -Xmx1024m -server -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -verbose:gc -XX:TargetSurvivorRatio=90 -Xss128k -XX:NewSize=512m -XX:MaxNewSize=512m

Object DB Size
==============================
26G /export1/bench/perfTests/terracotta/server/data/objectdb

L2 VerboseGC log Analysis

GC Report
================
Avg Full GC Duration = 6.12302 secs
Avg Full GC Interval = 99.5817 secs
Total Full GC Time = 385.75 secs

No. of Full GC = 63
Avg Young GC Duration = 0.234307 secs
Avg Young GC Interval = 10.8526 secs
No. of Young GC = 589
Total Young GC Time = 136.44 secs

Avg Young GC Occurence b/w Full GC = 9.34921
Avg Young GC Time b/w Full GC = 2.16571 secs