Mobile Website Performance – Best Practices

Mobile Browsing v/s Desktop Browsing May 2011

As you could see the mobile browsing increasing day by day. So what are the best practices needed to build a scalable web application that can be browse-able on mobile.? Though the best practice similar to desktop based browsing one important thing we need to keep in mind is mobile networks have high latency than the wired broadband connections. It is also running on low processor and limited screen size.

So by and large the performance of your website depends up on three major factors.

  • Mobile Networks
  • Mobile Software
  • Mobile Hardware

We can see what are the best practices we could follow to get best out of it.

Mobile Networks

As we discussed mobile network latency is the biggest area of concern. The broadband connection on an average have 20 ms latency where the mobile network have latency ranging from 250ms to 400 ms seconds, which is more than 15 times high. Certain things not in our hand, though mobile networks are working on to reduce the latency time. Since the latency time is high we need to follow the best practice to make it as much as possible.

1. Reduce the number of request:
Reduce number of request by reduce number of objects required by the website to load. As each HTTP request to load your image, css, html and scripts file are called independent, each will consume its own latency time to load. By reduce the number of request we can reduce the latency time.
2. Eliminate Single Point of Request:
It means each and every request should be independent of each others. one should not wait for the other object to get loaded. The best way is to do like

  • Use Asynchronous methods to load JavaScript / CSS files
  • Avoid iframes
  • Avoid using Fonts.

Facebook leads the way with Async loading. Here is the sample code of it.

(function () {
    var e = document.createElement('script');
    e.src = 'http://connect.facebook.net/en_US/all.js';
    e.async = true;
    document.getElementById('fb-root').appendChild(e);
}());

3. Maintain the heart beat:

Maintain the heart beat is nothing but simple old polling technique to keep the connection alive. Typically a mobile connection alive for 2-3 seconds. So sending a dummy AJAX request for every 2 to 3 seconds will keep the connection alive. That will reduce the latency time for subsequent requests. Though one could argue it is an evil implementation as it will kill the battery life heavily one should be very careful before implementing this.

Mobile Software
Once your content delivered via your mobile network, now the mobile software taken care of rendering. Software here means your mobile OS as well as the browsers ranging from IOS to Android, from Safari to opera. The traditional browsers have two behavior,
1. It will cache the js/css files.
2. It will not allow only one or two parallel request from a domain at a time.
The mobile web browsers are no difference. However the cache size is a big problem with mobile. So the best practices are like,
1.Caching : Use HTML5 local storage :

The default cache size of the web browser on mobile platform is typically 5MB which is pretty low. Other big concern is that restarting the mobile will make the cache empty. So it is always good to use HTML5 local storage which offers 25MB of cache. The important think is it won’t flush the cache when you restart your mobile. The simple way to do the caching using HTML5 local storage is,

<script data-cacheable="1">

and your script will look like,

foreach resource {
    localStorage.setItem(resource.id, resource.contents);
    cachedResources.push(resource.id);
}
cookie['cachedResources'] = cachedResources.join('|');

2. HttpPipelining :
HTTP pipelining is a technique in which multiple HTTP requests are sent on a single TCP connection without waiting for the corresponding responses. The pipelining of requests results in a dramatic improvement in the loading times of HTML pages, especially over high latency connections such as satellite Internet connections.
All the major mobile browsers like opera and firefox supporting it and recently IOS5 also added the support for it.
The major concern with HTTP pipelining is that suppose you have requested 3 resources at once and two got response fast but the third one is too large and taking lot of time, will result the other resources also not getting loaded. So it is always important to use DNS sharding and group the resources based on the size and loading time.

3. DNS Sharding:

To enable parallel downloading we can make different subdomains and serve resource from different domain. But one should careful on two things,
a) creating many DNS will increase the DNS lookup time
b) The resource serving should be consistent (i.e) if a script getting loaded from scripts.domain.com, on all subsequent request, it should load from the same sub domain. If it is not it will affect the caching we discussed above.

Mobile Hardware
Mobile equipment usually have low CPU power compare to your desktop. So we should be careful not to do too many computations on the client side. “Slow CPU, Slow JavaScript”. We should avoid dynamic graphics using CSS and excess computation of javascript. If the application demands it,make it such a way that it loads the javascript at the end of page after we loaded a basic version of the page.

Advertisements

RESTful web services in JAVA with JBoss RestEasy, maven and best practices

You can see RESTful file upload using Apache CXF and Spring here

What is REST?

Representational State Transfer (REST) is defined as an architectural style, which means that it is not a concrete systems architecture, but instead a set of constraints that are applied when designing a systems architecture. The REST architectural have the following constraints.

  • Resource Identification (The purpose of the REST services is to identify a resource. (e-g) a product in online shopping, categories of book)
  • Uniform Interface (Small set of operation should be carried consistently for large operations. (e-g) GET operation to retrieve data and PUT to store data no matter how many operation been done on that)
  • Self-Describing Messages (The Resources should be accessed in abstract way which describe their property by them self. (e-g) return the product properties by XML or JSON format)
  • Hyper Media driven application status (The resource should be accessible via hypermedia like links and URLs)
  • Stateless interaction(All the request to access the Resources should be independent and the service should not store any state of the previous interaction)

The web is a perfect restful services as web nothing but,
web = (URI + HTTP + HTML / XML / JSON)

Now we can see a sample REST based API using JBoss RestEasy

your pom.xml file will be like,

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.ananth.app</groupId>
  <artifactId>my-webapp</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <name>my-webapp Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
      <dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxrs</artifactId>
			<version>2.2.1.GA</version>

     </dependency>

      <dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxb-provider</artifactId>
			<version>2.2.1.GA</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-jaxrs</artifactId>
			<version>1.8.0</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.codehaus.jettison</groupId>
			<artifactId>jettison</artifactId>
			<version>1.3</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jettison-provider</artifactId>
			<version>2.2.1.GA</version>
			<scope>compile</scope>
		</dependency>

       <!-- Spring 3 dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>
		<!-- need for solution 1, if your container don't have this -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
		</dependency>
  </dependencies>
  <repositories>
	   <repository>
		  <id>JBoss repository</id>
		  <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
	   </repository>
	</repositories>
  <build>
       <plugins>
            <!-- enable java 6 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>

            <!-- skip tests -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.4.2</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

            <!-- automatically clean before build -->
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <executions>
                    <execution>
                        <id>auto-clean</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
      </plugins>
    <finalName>rest</finalName>
  </build>
</project>

This will include all the dependency needed for the project. The your web.xml will be,

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Restful web services</display-name>


    <!-- Auto scan REST service -->
<!--	<context-param>
		<param-name>resteasy.scan</param-name>
		<param-value>true</param-value>
	</context-param>     -->

    <context-param>
		<param-name>resteasy.resources</param-name>
		<param-value>com.ananth.service.HelloWorldService</param-value>
	</context-param>

	<!-- this need same with resteasy servlet url-pattern -->
	<context-param>
		<param-name>resteasy.servlet.mapping.prefix</param-name>
		<param-value>/service</param-value>
	</context-param>

    <listener>
		<listener-class>
			org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
		</listener-class>
	</listener>

    <listener>
		<listener-class>
                        org.springframework.web.context.ContextLoaderListener
                </listener-class>
	</listener>

	<servlet>
		<servlet-name>resteasy-servlet</servlet-name>
		<servlet-class>
			org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
		</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>resteasy-servlet</servlet-name>
		<url-pattern>/service/*</url-pattern>
	</servlet-mapping>

</web-app>

Note
I have commented out

<!--	<context-param>
		<param-name>resteasy.scan</param-name>
		<param-value>true</param-value>
	</context-param>     -->

The current version of JBoss RestEasy have some bug that prevent autoscan working.So you need to manually define your service classes here.
Second you should always define JBoss RestEasy listener above the Spring Listener.

The spring applicationContext.xml is very straight forward defines a simple bean,

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">

	<bean id="emp" class="com.ananth.service.EmpImpl">
        </bean>
    <bean class="com.ananth.context.SpringApplicationContext"></bean>
</beans>

Now the HelloWorldService.java will be like

package com.ananth.service;

import com.ananth.context.SpringApplicationContext;
import com.ananth.vo.Emp;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 21/12/11
 * Time: 5:21 PM
 * This is the REST based webservice class
 */
@Path("/message")
public class HelloWorldService {

    @GET
	@Path("/{param}")
	public Response printMessage(@PathParam("param") String msg) {

		String result = "Restful example : " + msg;
		return Response.status(200).entity(result).build();

	}

    @GET
    @Path("/emp/getall")
    @Produces({MediaType.APPLICATION_JSON, "application/*+json"})
    public Response getEmp() {
        Emp emp = new Emp();
        emp.setEmpId("001");
        emp.setName("hi");
        return Response.status(200).entity(emp).build();
    }
    @GET
    @Path("/emp/get")
    @Produces({MediaType.APPLICATION_JSON, "application/*+json"})
    public Response getEmpname() {
        IEmp emp = (IEmp) SpringApplicationContext.getBean("emp");
        String name = emp.getName();
        return Response.status(200).entity(name).build();
    }
}

To access the respective method all you need to do is open the browser and follow the URL pattern

where IEmp is a simple interface and EmpImpl is the implementation of IEmp interface.

package com.ananth.service;
/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 23/12/11
 * Time: 4:11 PM
 * To change this template use File | Settings | File Templates.
 */
public interface IEmp {

    String getName();

}
package com.ananth.service;

/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 23/12/11
 * Time: 4:12 PM
 * To change this template use File | Settings | File Templates.
 */
public class EmpImpl implements IEmp{
    @Override
    public String getName() {
        return "some string to return";
    }
}

finally the Emp.java is a getter/setter to demonstrated how we can map the complex object in JSON format.

package com.ananth.vo;
import javax.xml.bind.annotation.XmlRootElement;
/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 21/12/11
 * Time: 5:28 PM
 * To change this template use File | Settings | File Templates.
 */


@XmlRootElement
public class Emp {

    private String empId = null;
    private String name = null;

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

for best practices APIGee blog have some very good articles on it.

Forum Tools comparison- JForum, PHPBB3 & vBulletion

Last week I did some comparative study about various forum based tools available. We also taken hosted forum services like Hoop.la!, but we decide to host our own forum since the user base is large for our site. Eventually we shortlisted the following tools.

  • JForum
  • PHPBB3
  • vBulletion
  • Forum Comparison. JForum, PHPBB3 & vBulletin

    Though most of the feature been supported by all the tools, It is disappointed that JForum is not supporting SEO URLs. We need our custom implementation to do it. Though they revamp their architecture on coming release (JForum 3.0), which is currently on beta. There is no definite statement about it’s production ready. Bot vBulletion and PHPBB3 supports SEO urls by modules we you need to plug in. It won’t support by default.

    SSO feature is not covered in the diagram where JForum support with custom module. You need to extract their SSO class and override it. PHPBB3 does have session sharing support, but not having SSO option. vBulletion has it in build.

    Conclusion:

    If you are a java expert and don’t like to code with PHP go with JForum, though you will need fair bit of customization.There is nothing much feature support difference from vBulletion and PHPBB3. If you willing to spend around $199 go for vBulletion but you can’t customize as you like. Best fit in that case obviously PHPBB3.

WHY NOSQL- PART 2 – OVERVIEW OF DATA MODEL,RELATIONAL & NOSQL

This is part 2 of Why NoSQL series. You can view the first part here. In this post we will have an overview about various data model been which upon NoSQL databases been build and compare it with RDBMS data model.

NoSQL databases
NoSQL Databases.

All through the post we can examine different data model with famous employee data. Typically in an office employee will have following records,

  • empid
  • emp_name
  • department
  • designation

and consider the company has different department.
Let us examine the relational database model first.
Relational Database model:
Relational database model first been proposed by Edgar F. Codd in late 1969. The fundamental assumption of the relational data model is that the data is represented as a mathematical n-ary relation which is a subset of Cartesian product. The data been accessed by means of relational algebra using set theory and the consistency been achieved by applying constraints like primary and foreign keys.
So the typical data model for employee problem will be,

Data model for Employee
Employee RDBMS Data model

NoSQL data model:
The NoSQL databases taken a completed different approach and implements day-to-day data structure based solutions. There are different types of data models been implemented.

  • 1. Column Families or wide column store
  • 2. Document Store
  • 3. Key/ value Store
  • 4. Graph Data store

1. Column Families or wide column store
Examples: Cassandra, HBase
Typical usages : Distributed data storage.
The column families basically extends the typical key/value pair storage and provide two level of nesting. The nested key/value pair is called column in column family storage. Each column can be grouped with a key and thus provide super column functionality as well. The typical use case will be the application with extensive read/write operation. Facebook messenger uses Hbase. Typically the employee data model will look like below,

Column Family Data Model

2. Document Store
Examples: CouchDB, MongoDB
Typical usages : Web applications.
Document based data model used to store and retrieve document oriented or semi-structured information which is common on web-based applications. Typically all the modern document based data models follow the XML,JSON or BSON model that is easy map with the data model. It is also enable APIs easily interact with the databases as most of the modern-day languages support these formats in build. The data model of Employee will look like,

Id = “001”,FirstName=”Ananth”, LastName=”Durai”, Department=[{Id:”DIT”,DeptName:”IT”}],Designation=[{Desig=”Software Programmer”, Salary:0}]

3. Key/ Value store
Examples: Membase, Redis
Typical usages : Distributed Hash table, caching
Key / value store function as typical Hash table where it will store the value against a key. This will enable to create schema less storage. It will be best in use when we have excess read operation than write operation. Say for example we have to display Latest post on forum on every 2 minutes, It makes sense to run a background job on every 2 minutes and store as key value pair and read data from there. Lot of content intensive websites using in memory key / value pair storage system.

4. Graph Databases
Examples: Neo4J, InfoGrid
Typical usages: Social networking, Recommendations
Graph data model typically follows the Graph algorithm to store data with nodes and edges. Graph databases are best suit where we face recursive data model. Each an every node will have the following attributes

  • Node
  • Property
  • Relationship (Edges)

We can map it to the our Employee object.
Here

Node : Employee
Property: first name, last name, designation and department
Relationship : Employee part of a department

We can see more like eventual consistency and best use cases on the next series.