Archive for the ‘appengine’ Category

Appengine datastore uses too much CPU

Sunday, February 7th, 2010

Google App Engine is supposed to be miracle solution for everything. You can build as scalable solutions as you want to and it is almost free. After investigating technology more I am not so thrilled anymore. I was working on importing ip geolocation data to datastore and it was really tricky. Inserting one ip range that includes long fromip, long toip and string countrycode takes around 40ms and serving full request uses something like 700ms of CPU.

IP geolocation database has around 100k ip ranges and CSV file is 7MB. In separate server i used unix command split to split that CSV file to smaller files with 500 lines each. Now appengine uses urlfetch to download that file, parses this and enters all ip ranges with pm.makePersistentAll() . This processing takes around 4s and uses 20-40s of CPU. To import full DB it takes 200x30s that 1,5h of CPU whilst you only get 6,5h free per day. And thats not all. Superscalable appengine should be able to process all these batches simultaneously but it could not saying:

Request was aborted after waiting too long to attempt to service your request. Most likely, this indicates that you have reached your simultaneous dynamic request limit. This is almost always due to excessively high latency in your app. Please see http://code.google.com/appengine/docs/quotas.html for more details.

Its impossible to process all ip ranges at once. Instead task had to be separated into many smaller tasks and asynchronous task queue used. When trying to process all at once you get most severel critical error:

com.sun.faces.context.ExceptionHandlerImpl log: JSF1073: javax.faces.event.AbortProcessingException caught during processing of INVOKE_APPLICATION 5 : UIComponent-ClientId=j_idt4:j_idt12, Message=com.google.apphosting.api.DeadlineExceededException: This request (efab013ed2a2d05f) started at 2010/02/06 20:06:34.903 UTC and was still executing at 2010/02/06 20:07:03.599 UTC.

Its sayd that reading data in BigTable is much faster but i cant confirm that either. There are bit over 200 countries and loading and displaying them all takes some 3000ms on CPU.

For comparison in local dev server persisting that batch of 500 ip ranges takes in order of 10x less time and recource.

You cant always close the persitencemanager when you are done with it.

Saturday, January 23rd, 2010

I am used to close all recources when i am done with these but that seems not to be the case in app engine world.
Here is little method that gets all countries, adds these to List and closes PersistenceManager as its not needed anymore, we have all the data we need in List.

public List<Country> getCountries() {
PersistenceManager pm = PMF.get().getPersistenceManager();
String query = "select from " + Country.class.getName();
List<Country> countries = (List<Country>) pm.newQuery(query).execute();
pm.close();
return countries;
}

Countries are used in simple dataTable below, but when running this code app engine starts to complain “Object Manager has been closed”. To fix this issue pm.close(); can be commented out and hope that guys from google will close it eventually themselves. Google in its documentation does not recommend this though.

<h:dataTable value="#{countryBean.countries}" var="country">
<h:column>
</h:column>
</h:dataTable>

Probably appengine is lazy to actually get items from datastore to List but gets them only when particular item is used. So another way to fix it is to force appengine to force loading all entries from datastore by copying.

public List<Country> getCountries() {
PersistenceManager pm = PMF.get().getPersistenceManager();
String query = "select from " + Country.class.getName();
List<Country> countries = (List<Country>) pm.newQuery(query).execute();
List<Country> countries2=new ArrayList<Country>();
Collections.copy(countries, countries2);
pm.close();
return countries;
}

What i have not figured out yet is why all request take awful lot of CPU recource and how to reduce it. over 5000ms is like crazy

01-24 04:18AM 54.222 /faces/insertcountry.xhtml 200 930ms 5289cpu_ms 4570api_cpu_ms 0kb Mozilla/5.0 (X11; U; Linux x86_64; et; rv:1.9.1.7) Gecko/20100106 Ubuntu/9.10 (karmic) Firefox/3.5.7,gzip(gfe),gzip(gfe)
...
01-24 04:18AM 54.729 org.datanucleus.ObjectManagerImpl close: Outstanding nontx update being committed to datastore
An Error Occurred:
Object Manager has been closed
+- Stack Trace
 (more…)

Appengine sample Guestbook Datastore works but yours fails.

Saturday, January 23rd, 2010

When you first start experimenting with google app engine then you may get Exception below when trying to save data to datastore and checking out PercistenceManager for that. One thing to check it to see, if jdoconfig.xml in source packages and META-INF. Appengine example config is also included here.

<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

<persistence-manager-factory name="transactions-optional">
<property name="javax.jdo.PersistenceManagerFactoryClass"
value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
<property name="javax.jdo.option.ConnectionURL" value="appengine"/>
<property name="javax.jdo.option.NontransactionalRead" value="true"/>
<property name="javax.jdo.option.NontransactionalWrite" value="true"/>
<property name="javax.jdo.option.RetainValues" value="true"/>
<property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
</persistence-manager-factory>
</jdoconfig>

(more…)

JSF 2.0 dont like google appengine

Tuesday, January 19th, 2010

You write nice simple JSF application and when you try to run it in appengine browser shows:

HTTP ERROR: 404
NOT_FOUND
RequestURI=/
Powered by jetty://

Stacktrace looks like:

[java] The server is running at http://localhost:8080/
     [java] 19.01.2010 19:42:14 com.google.apphosting.utils.jetty.JettyLogger warn
     [java] WARNING: failed com.google.apphosting.utils.jetty.DevAppEngineWebAppContext@6ee3849c{/,/home/user/NetBeansProjects/HelloWorld/build/web}
     [java] java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google  App Engine developer's guide for more details.
     [java]         at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
     [java]         at com.sun.faces.config.WebConfiguration.processJndiEntries(WebConfiguration.java:578)
     [java]         at com.sun.faces.config.WebConfiguration.(WebConfiguration.java:114)
     [java]         at com.sun.faces.config.WebConfiguration.getInstance(WebConfiguration.java:174)

Problem is that appengine has issue with JSF implementation and you must rewrite jsf-impl.jar to fix it. Fortunately there is guy who already did this, see http://javadocs.wordpress.com/2009/10/17/mojarra-jsf-2-0-rc2-and-google-app-engine-sdk-1-2-6/

IMPORTANT! If this seems not to do the trick then clean and build is needed.

One more useful link is https://sites.google.com/a/wildstartech.com/adventures-in-java/Java-Platform-Enterprise-Edition/JavaServer-Faces/sun-javaserver-faces-reference-implementation/configuring-jsf-20-to-run-on-the-google-appengine