Showing posts with label Performance. Show all posts
Showing posts with label Performance. Show all posts

Wednesday, 12 November 2014

Performance and the Entity Framework

Introduction

If you are using the Entity Framework (EF), then you need to understand the best practices for improving its performance, or you will suffer the consequences!

Background

My team has spent almost 2 years with the first version of the Entity Framework in an enterprise application (including the beta). Our application has a Service Oriented Architecture (SOA) that uses the .NET 3.5 Framework SP1, SQL Server 2008 and IIS 7.0 on Windows Server 2008. During development we ran into significant issues with performance which we overcame by finding and following several best practices. The intent of this article is to explain these best practices. This article assumes that you are familiar with what the EF is and how to use it. If you need more of an introductory overview, check out the Introduction to the Entity Framework article.

Best Practices

Our application has a database with 400+ tables, some of which are very inter-connected. All of our Entity Framework calls are contained in our web service projects. Many of our EF calls took 8.5 seconds to complete on first time calls. By making certain changes (see the chart below) to our web service projects, we were able to improve these calls to 3 seconds. Second EF calls became almost instant. The chart below gives an indication of the overall performance impact with respect to the EF and the level of refactoring it took us to implement the change.
Best PracticeImpactRequired Refactoring
Pre-generated Your ViewMajorMinor
Use Small EDMX FilesMinorModerate
Create Smart Connection StringsMinorMinor
Disable Change TrackingMinorMinor
Use Compiled QueriesModerateModerate
Be Careful With IncludesModerateMajor
The following sections in this article will explain these best practices in more detail- so read on!

Pre-generated Your View

The most expensive operation (it takes over 50% of the initial query) is View Generation. A big part of creating an abstracted view of the database is providing the actual view for queries and updates in the store’s native language. During View Generation, the store views are created. Fortunately we can eliminate the expense of building the in-memory view by running the EDM generator (EdmGen.exe) command line tool with the view generation command parameter /mode:ViewGeneration (see below).
Running this tool will create a code file (either .cs or .vb) with a pre-generated view that can be included and compiled in your project. Having the view pre-generated reduces the startup time considerably. The first time the EF ObjectContext is created the view must be generated, so pre-generating the view and deploying it with your application is important. The disadvantage of doing this is that you must keep the generated views synchronized with any changes you make to the data model.
"%windir%\Microsoft.NET\Framework\v3.5\EdmGen.exe" 
    /mode:ViewGeneration 
    /language:CSharp 
    /nologo 
    "/inssdl:MyEntityModel.ssdl" 
    "/incsdl:MyEntityModel.csdl" 
    "/inmsl:MyEntityModel.msl" 
    "/outviews:MyEntityModel.Views.cs"
The EdmGen.exe tool is installed in the .NET Framework directory. In many cases, this is located inC:\windows\Microsoft.NET\Framework\v3.5. For 64-bit systems, this is located inC:\windows\Microsoft.NET\Framework64\v3.5. You can also access the EdmGen.exe tool from the Visual Studio command prompt (Click Start, point to All Programs, point to Microsoft Visual Studio 2008, point to Visual Studio Tools, and then click Visual Studio 2008 Command Prompt). In order to get the input .ssdl.csdl and .msl files, you need to use Visual Studio to do the following:
  1. Open the project that contains your Entity Framework project.
  2. Open the EDMX file in the designer.
  3. Click the background of the model to open the model's Properties window.
  4. Change the Metadata Artifact Processing property to: Copy to Output Directory.
  5. Save the project- this will create the .ssdl.csdl, and .msl files.
Another way to do this is by running the EDM generator command line tool with the full generation command parameter /mode:FullGeneration (see below). EdmGen.exe requires only a valid connection string to your database to generate the conceptual model (.csdl), storage model (.ssdl), and mapping (.msl) files, as well as the pre-generated view file. All options shown are required:
"%windir%\Microsoft.NET\Framework\v3.5\EdmGen.exe" 
    /mode:FullGeneration 
    /c:"Data Source=localhost;Initial Catalog=MyDatabase; Integrated Security=true" 
    /nologo 
    /language:CSharp 
    /entitycontainer:MyEntities 
    /namespace:MyModel 
    "/outviews:MyEntityModel.Views.cs" 
    "/outssdl:MyEntityModel.ssdl" 
    "/outcsdl:MyEntityModel.csdl" 
    "/outmsl:MyEntityModel.msl" 
    "/outobjectlayer:MyEntities.ObjectLayer.cs"

Use Smaller EDMX Files

The Entity Framework is capable of handling large entity data models but you can run into performance problems if the data model is very inter-connected. In general you should start thinking about breaking up a data model (into multiple .edmx files) when it has reached an order of 100 entities.
The size of the .xml schema files is somewhat proportional to the number of tables in the database that you generated the model from. As the size of the schema files increase, the time it takes to parse and create an in-memory model for this metadata will also increase. As stated earlier, this is a one-time cost incurred perObjectContext instance and can be shortened by pre-generating the view. The Visual Studio Designer also starts to suffer from poor performance when the number of entities gets too large. The disadvantage of having several smaller data models is that you must keep the individual .edmx files synchronized when you make changes to the database.

Smart Connection Strings

The ObjectContext object retrieves connection information automatically from the application config file when creating object queries. You can supply this named connection string instead of relying on theconnectionString parameter in the .config file when instantiating the ObjectContext class. The Metadataproperty in the connectionString parameter contains a list of locations for the EntityClient provider to search for EDM mapping and metadata files (the .ssdl.csdl, and .msl files).
Mapping and metadata files are often deployed in the same directory as the application executable file. These mapping files can also be included as an embedded resource in the application which will improve performance. In order to embed the EDM mapping files in an assembly, you need to use Visual Studio to do the following:
  1. Open the project that contains your Entity Framework project.
  2. Open the EDMX file in the designer.
  3. Click the background of the model to open the model's Properties window.
  4. Change the Metadata Artifact Processing property to: Embed in Output Assembly.
  5. Rebuild project- this will build a .dll file with the .ssdl.csdl, and .msl information.
Embedded resources are specified as follows: Metadata=res://<assemblyFullName>/<resourceName>. Note when you use wildcard for the assemblyFullName (*), the Entity Framework has to look through the calling, referenced, and side-by-side assemblies for resources with the correct name. To improve performance, always specify the assembly name instead of the wildcard. Below is an excerpt from a web.config file that contains the connectionString parameter. You can see the metadata property is specifying the assembly nameMyApp.MyService.BusinessEntities.dll:
  <connectionStrings>
    <add name="MyEntities" 
 connectionString="metadata=res://MyApp.ServiceRequest.BusinessEntities, 
 Version=1.0.0.0, Culture=neutral,
     PublicKeyToken=null/;provider=System.Data.SqlClient;
 provider connection string="Data Source=localhost;Initial Catalog=MyDatabase;
     Integrated Security=True;MultipleActiveResultSets=True"" 
     providerName="System.Data.EntityClient" />
  </connectionStrings>

Disable Change Tracking

Once the View Generation cost is eliminated, the most expensive operation is Object Materialization. This operation eats up 75% of your query time because it has to read from the DbDataReader object and create an object. When you are using the Entity Framework, you have objects that represent the tables in your database. These objects are created by an internal process called object materialization. This process takes the returned data and builds the relevant objects for you. The object can be EntityObject derived objects, anonymous types, or DbDataRecord DbDataRecord.
The ObjectContext object will create an ObjectStateEntry object to help track changes made to related entities. Objects are tracked when queried, added, or attached to the cached references inside this class. The tracking behavior is specified using the MergeOption enumeration. When updates to properties of the tracked objects occur, the properties are marked as modified and the original values are kept for performing updates back to the database. This enables users to write code against the objects themselves and call SaveChanges.
We can minimize the overhead of change tracking by using the MergeOption.NoTracking option. Doing so will increase the performance of your system in most situations. The loss of change tracking is irrelevant if you are sending your data across the network via a web service because this feature will not work in a "disconnected" mode. Even if you are not disconnected, you can use this option in a page where there are no updates to the database. Take a look at the code snippet below for one example of how to disable change tracking:
public List<ServiceRequest> GetBySubmissionDate(DateTime startDate, DateTime endDate)
{
     using (new Tracer("Trace"))
     {
           using (MyEntities db = new MyEntities())
           {
               ObjectQuery<ServiceRequest> query = 
  (ObjectQuery<ServiceRequest>)CompiledQueries.GetBySubmissionDate
  (db, startDate, endDate);
               // The .Execute call is using the NoTracking option
               List<ServiceRequest> serviceRequests = 
   query.Execute(MergeOption.NoTracking).ToList();    
               return serviceRequests;
     }
    }
}
It's unclear how much the MergeOption.NoTracking option helps performance because every query is different. In general, I would say it's certainly worth trying. Note however the following caveats exist when using the MergeOption.NoTracking option:
  • There is no identity resolution so, depending on your query, it's possible that you will get entities with the same primary key that are referentially distinct.
  • Foreign keys are only loaded if both entities are loaded. If the other end of the association is not included, then the foreign key will not be loaded either.
  • Tracked objects are cached, so subsequent calls for that object will not hit the database. If you useNoTracking and try to load the same object multiple times, the database will be queried each time.

Use Compiled Queries

Query Creation also takes up a good chunk of time, about 10% of your query after the EF is warmed up. Some parts of the query are cached so that subsequent queries are faster than the first. However not all parts of the query are cached leaving some parts needing to be rebuilt each time the query is executed (unless you are usingEntitySql). We can eliminate the need for rebuilding query plans by using Compiled Queries. To compile a query for later, you can use the CompiledQuery.Compile method which uses a delegate:
public static readonly Func<MyEntities, DateTime, 
 DateTime, IQueryable<ServiceRequest>> GetBySubmissionDate =
    CompiledQuery.Compile<MyEntities, DateTime, DateTime, IQueryable<ServiceRequest>>(
       (db, startDate, endDate) => (from s in db.ServiceRequest
                                        .Include("ServiceRequestType")
                                        .Include("ServiceRequestStatus")
                                    where s.SubmissionDate >= startDate
                                        && s.SubmissionDate <= endDate
                                    orderby s.SubmissionDate ascending
                                    select s);
Note the following caveats exist when using the CompiledQuery.Compile option:
  • You cannot use CompiledQueries with parametrized Includes- so you have to use EntitySQL instead.
  • Compiling a query for reuse takes at least double the time of simply executing it without caching.

Be Careful With Includes

You can direct the framework to do eager loading of relationships by using an .Include statement. With an eager load, the framework will construct a join query and the relationship data will be fetched along with the original entity data. The .Include statement can result in a large amount of data being brought back, it can also result in complex queries because of the need to use many Join statements at the data store.
public List<ServiceRequest> GetBySubmissionDate(DateTime startDate, DateTime endDate)
{
    using (new Tracer("Trace"))
    {
        using (MyEntities db = new MyEntities())
        {
             // The compiled query uses .Include to eager 
     // load ServiceRequestType and ServiceRequestStatus
            ObjectQuery<ServiceRequest> query = (ObjectQuery<ServiceRequest>)
  CompiledQueries.GetBySubmissionDate(db, startDate, endDate);
            List<ServiceRequest> serviceRequests = query.Execute
     (MergeOption.NoTracking).ToList();
            return serviceRequests;
        }
    }
}
This can be avoided by using an .Load statement to lazy load the relationship. With lazy loading, an additional query is constructed and run for each call to load to fetch the relationship information. If you want to lazy load only certain relationships, you may choose instead to have code like that shown below:
public List<ServiceRequest> GetBySubmissionDate(DateTime startDate, DateTime endDate)
{
    using (new Tracer("Trace"))
    {
         using (MyEntities db = new MyEntities())
         {
              ObjectQuery<ServiceRequest> query = 
  (ObjectQuery<ServiceRequest>)CompiledQueries.GetBySubmissionDate
  (db, startDate, endDate);
              List<ServiceRequest> serviceRequests = 
   query.Execute(MergeOption.NoTracking).ToList();
              // Use the .Load statement to lazy load the ServiceRequestType
              foreach (ServiceRequest item in serviceRequests)
              {
                   if (!item.ServiceRequestTypeReference.IsLoaded)
                        item.ServiceRequestTypeReference.Load(MergeOption.NoTracking);
              }
              return serviceRequests;
          }
     }
}
Note that in certain instances, eager loading is better while in others lazy loading is a better approach. In the code below, every table that has a relationship to the specified entity parameter is lazy loaded:
public static void LoadRelated(EntityObject entity, MergeOption mergeOption)
{
    System.Reflection.PropertyInfo[] properties = entity.GetType().GetProperties();

    foreach (System.Reflection.PropertyInfo propInfo in properties)
    {
        if (IsEntityReference(propInfo))
        {
            EntityReference er = (EntityReference)propInfo.GetValue(entity, null);
            if (!er.IsLoaded)
                er.Load(mergeOption);
        }

        if (IsEntityCollection(propInfo))
        {
            //The actual stored value of the EntityCollection is a RelatedEnd object.
            System.Data.Objects.DataClasses.RelatedEnd end = 
     (System.Data.Objects.DataClasses.RelatedEnd)propInfo.GetValue(entity, null);

            if (!end.IsLoaded)
            {
                end.Load(mergeOption);

                //Get the enumerator off the RelatedEnd object so we can cycle 
        //through items in EntityCollection without knowing the type
                System.Collections.IEnumerator enumerator = end.GetEnumerator();

                //Cycle through items in EntityCollection and add them to the list.
                while (enumerator.MoveNext())
                {
                    LoadChildren(enumerator.Current as EntityObject);
                }
            }
        }
    }
}
You may want to take a look at the series of articles on Transparent Lazy Loading for Entity Framework for a more readable and simple version of lazy loading using the EFLazyLoading library.

Points of Interest

There are several things to keep in mind with regard to performance when you work with the Entity Framework:
  • Initial creation of the ObjectContext includes the cost of loading and validating the metadata.
  • Initial execution of any query includes the costs of building up a query cache to enable faster execution of subsequent queries.
  • Compiled LINQ queries are faster than non-compiled LINQ queries.
  • Queries executed with a the NoTracking merge option works well when changes and relationships do not need to be tracked, such as data sent across the network.
  • You may want to check out the EdmGen2.exe tool which can be used as a replacement for the originalEdmGen.exe tool and is capable of reading and writing EDMX files.
  • If you try to navigate a many-to-one or one-to-one relationship that is not loaded, you will get aNullReferenceException.

Saturday, 20 September 2014

How to improve the performance of ASP.NET MVC web applications

Today I stumbled upon a nice presentation that Rudi Benkovic gave last week at the Slovenian DotNet User Group, about ASP.NET MVC Performance.

The Big Picture

It is an in depth analysis of a Digg-like site and how it went from serving (on a test machine) 6 req/sec to 390 req/sec.
The biggest gain, 74 req/sec to 390 req/sec happened when he introduced data caching and another 25 req/sec where gained when he introduced the compilation of LINQ queries.

Data caching is always the key

Splitting the gains among the various components:
  • 29 req/sec optimizing the usage of ASP.NET MVC (I’ll come to this later)
  • 14 req/sec caching route resolution
  • 340 req/sec caching the data access layer
This proves that, no matter what you do to optimize your code, the biggest performance hit is data retrieval, and the first thing you have to optimize is always this.
[UPDATE: I wrote another post with a better analysis of data]
The original presentation also have some nice graphs, so I recommend you go and watch it.

Can ASP.NET MVC be still optimized a bit?

But apart from this obvious outcome, I just want to take out from this presentation the 3 point that are really specific to ASP.NET MVC.

Route resolution

9 request per second are gained optimizing the route resolution. There are a lot of ways to do route resolution (aka creating a link given the action/controller you want to link to), but they can be summarized with these 3:
  • expression tree-based ActionLink
  • string-based ActionLink
  • RouteLink specifying the RouteName
  • (there is also the 4th one, the hard-coded one, but I’d rather not take this into account)
From the presentation it comes out that the first way, the expression tree one, is 30 times slower than the string-based version, which takes twice the time of specifying directly the RouteName.
So, not only the expression tree-based ActionLink is “deprecated” as it doesn’t work for action whose name has been changed through the ActionName attribute, but it’s also slower. We are talking about 1.95 ms versus 0.06 ms, and this can be considered as premature optimization (a 2ms improvement in a request that takes 200ms), but if your views have hundreds of these expression tree-based link, this can become a performance problem, as it is for the sample application analyzed which has more than hundreds of ActionLinks in the page.
Also consider that this is the first optimization he did, and with this he passed from 6 to 15 requests per second, which is a more than 150% gain. So, a pretty big gain here. You can read more about how this method is a problem on the follow up post: The performance implications of the expression tree-based ActionLink helper

Caching Route Resolution

Routes are resolved lots of time during the application lifetime, so caching them could be a nice solution: in the performance test Rudi said that this made him gain 15 req/sec. Again, not a big gain, but since implementing that kind of route resolution caching should not be a difficult task, probably it can be worth writing a small UrlHelper that caches the routes already resolved. Actually, this could be something Microsoft could add to routing engine itself.

Optimize the usage of PartialViews

In the benchmark application, the code does a loop over a list of items, and for each item it calls a RenderPartial to display the detail of each item of the list. In his benchmark the same partial was called 41 times per request.
So he decided to place the for-each loop inside the Partial View, and so have kind of the same encapsulation of markup, but gaining another 10 req/sec. This way you cannot see at a first glace that there is for-loop going on inside the partial, so probably a better solution could have been an Html Helper. Or something that the pre-compiler could have done was to “inline” the loop.
With this I don’t to say that you have to inline everything, but just remember that every RenderPartial you call has a performance hit.

Path to PartialViews

Finally he said he gained another 10 req/sec optimizing how the path to the partial views is specified. You can either specify the view path as only its name (and so the view engine will go and look for it in the current folder or in the shared folder) or you can specify the full path. But if I’m not wrong, the resolution of the real path given the name of the view is cached, so the gain is only achieved in the really first call to the method, and would have probably been averaged out if the benchmark was run for a longer time.
UPDATE: Rudi forgot to set the debug flag to false, thus disabling the view resolution caching. And when running in production you always have to set debug to false. So this is not a performance issue. Read more about this on my follow-up post: Stopping the panic: how to improve HtmlHelper.RenderPartial performances. Don’t run in debug mode

Key takeaways

What do we have to learn from this performance analysis?
First and foremost, that data caching is the easiest and most effective way to improve the performance of your applications: without this, every other optimization is a “micro-optimization”.
If then we really want to get some other rules to apply to ASP.NET MVC applications here they are:
  1. Consider using the RouteName to organize your routes and then use it to generate your links, and try not to use the expression tree based ActionLink method.
  2. Consider implementing a route resolution caching strategy (and waiting for MS to include something similar in a future version of System.Web.Routing)
  3. Use your common sense when you put RenderPartials on your views page: if you end up calling the same partial 300 times in the same view, probably there is something wrong with that.
But, again, before fine-tuning these aspects of ASP.NET MVC, remember that your data access has to be cached in some way. If you don’t do to that, everything else is just a waste of time.
I ask Rudi if he could first apply the caching of data only, and then apply all the other optimizations, and see which is the impact of the ASP.NET MVC specific optimizations.
What are your ideas on this? Do you think that there are other ways of optimizing ASP.NET MVC that are not micro-optimizations? Please share your thoughts leaving a comment.
kick it on DotNetKicks.com
posted on Friday, April 17, 2009 3:49 PM

Friday, 19 September 2014

Servlet and JSP performance tips



The following detailed tips have been extracted from the raw tips page
http://www.ddjembedded.com/resources/articles/2001/0112g/0112g.htm
Balancing Network Load with Priority Queues (Page last updated December 2001, Added 2002-02-22, Author Frank Fabian, Publisher Dr. Dobb's). Tips:
  • Web hits should cater for handling peak hit rate, not the average rate.
  • You can model hit rates using gaussian distribution to determine the average hit rate per time unit (e.g. per second) at peak usage, then a poisson probability gives the probability of a given number of users simulatneously hitting the server within that time unit. [Article gives an example with gaussian fitted to peak traffic of 4000 users with a standard deviation of 20 minutes resulting in an average of 1.33 users per second at the peak, which in turn gives the probabilities that 0, 1, 2, 3, 4, 5, 6 users hitting the server within one second as 26%, 35%, 23%, 10%, 3%, 1%, 0.2%. Service time was 53 milliseconds, which means that the server can service 19 hits per second without the service rate requiring requests being queued.]
  • System throughput is the arrival rate divided by the service rate. If the ratio becomes greater than one, requests exceed the system capability and will be lost or need to be queued.
  • If requests are queued because capacity is exceeded, the throughput must drop sufficiently to handle the queued requests or the system will fail (the service rate must increase or arrival rate decrease). If the average throughput exceeds 1, then the system will fail.
  • [Note that Java application servers often do not show a constant service time. Instead the service time often increases with higher concurrency due to non-linear effects of garbage collection].

http://www.javareport.com/html/from_pages/article.asp?id=252
Detailed article on load testing systems (Page last updated January 2001, Added 2001-01-19, Author Himanshu Bhatt, Publisher Java Report). Tips:
  • Internet systems should be load-tested throughout development.
  • Load testing can provide the basis for: Comparing varying architectural approaches; Performance tuning; Capacity planning.
  • Initially you should identify the probable performance and scalability based on the requirements. You should be asking about: numbers of users/components; component interactions; throughput and transaction rates; performance requirements.
  • Factor in batch requirements and performance characteristics of dependent (sub)systems. Note that additional layers, like security, add overheads to performance.
  • Logging and stateful EJB can degrade performance.
  • After the initial identification phase, the target should be for a model architecture that can be load-tested to feedback information.
  • Scalability hotspots are more likely to exist in the tiers that are shared across multiple client sessions.
  • Performance measurements should be from presentation start to presentation completion, i.e. user clicks button (start) and information is displayed (completion).
  • Use load-test suites and frameworks to perform repeatable load testing.

http://www.sys-con.com/java/article.cfm?id=671
J2EE Application server performance (Page last updated April 2001, Added 2001-04-20, Author Misha Davidson, Publisher Java Developers Journal). Tips:
  • Avoid using the SingleThreadModel interface for servlets: write thread-safe code instead.
  • ServletRequest.getRemoteHost() is very inefficient, and can take seconds to complete the reverse DNS lookup it performs.
  • OutputStream can be faster than PrintWriter. JSPs are only generally slower than servlets when returning binary data, since JSPs always use a PrintWriter, whereas servlets can take advantage of a faster OutputStream.
  • Excessive use of custom tags may create unnecessary processing overhead.
  • Using multiple levels of BodyTags combined with iteration will likely slow down the processing of the page significantly.
  • For read-only queries involving large amounts of data, avoid EJB objects and use JavaBeans as an intermediary to access manipulate and store the data for JSP access.

http://www-4.ibm.com/software/webservers/appserv/ws_bestpractices.pdf
Paper detailing the "Best Practices for Developing High Performance Web and Enterprise Applications" using IBM's WebSphere. All the tips are generally applicable to servlet/EJB development, as well as other types of server development. (Page last updated September 2000, Added 2001-01-19, Author Harvey W. Gunther, Publisher IBM). Tips:
  • Do not store large object graphs in javax.servlet.http.HttpSession. Servlets may need to serialize and deserialize HttpSession objects for persistent sessions, and making them large produces a large serialization overhead.
  • Use the tag "<%@ page session="false"%>" to avoid creating HttpSessions in JSPs.
  • Minimize synchronization in Servlets to avoid multiple execution threads becoming effectively single-threaded.
  • Do not use javax.servlet.SingleThreadModel.
  • Use the HttpServlet Init method to perform expensive operations that need only be done once.
  • Minimize use of System.out.println.
  • Access entity beans from session beans, not from client or servlet code.

http://www.sys-con.com/java/article.cfm?id=1171
J2EE Performance tuning (Page last updated October 2001, Added 2001-10-22, Author James McGovern, Publisher Java Developers Journal). Tips:
  • Call HttpSession.invalidate() to clean up a session when you no longer need to use it.
  • For Web pages that don't require session tracking, save resources by turning off automatic session creation using: <%@ page session="false"%>
  • Implement the HttpSessionBindingListener for all beans that are scoped as session interface and explicitly release resources implementing the method valueUnbound().
  • Timeout sessions more quickly by setting the timeout or using session.setMaxInactiveInterval().
  • Keep-Alive may be extra overhead for dynamic sites.
  • Use the include directive <%@ include file="copyleft.html" %> where possible, as this is a compile-time directive (include action <jsp:include page="copyleft.jsp" /> is a runtime directive).
  • Use cache tagging where possible.

http://win-www.uia.ac.be/~s985218/professional/thesis/archief/documenten/Marktoverzicht.doc
Overview of common application servers. (Announced at http://www.theserverside.com/home/thread.jsp?thread_id=9581). I've extracted the performance related features (Page last updated October 2001, Added 2001-10-22, Author Pieter Van Gorp, Publisher Van Gorp). Tips:
  • Optimized subsystems (RMI, JMS, JDBC drivers, JSP tags & cacheable page fragments).

http://intranetjournal.com/articles/200110/gb_10_24_01a.html
Website performance. (Page last updated October 2001, Added 2001-11-27, Author Gordon Benett, Publisher Intranet Journal). Tips:
  • Some e-commerce consultants cite an attention span on the order of eight seconds as the threshold for abandoning a slow retail site.
  • Where broadband connections are the norm, pages that don't appear instantly stand a good chance of never being seen: slow pages might as well be no pages.
  • Systems can only be designed to meet performance goals if those goals have been identified. Determine what range of response times will be acceptable.
  • Try to understand the performance impacts of your design decisions. However the performance of some design choices can be hard to predict and may remain unclear before testing.
  • Test the system under conditions that simulate real patterns of use.
  • Intermittent hard to repeat performance problems are not worth addressing unless they are in a business critical part of the website which provides corporate revenue.
  • Use a rapid, iterative development process in combination with frequent performance testing.
  • Try to plan up-front rather than have to rely on late-phase tuning.

http://www.fawcette.com/javapro/2002_01/magazine/columns/weblication/
Database performance (Page last updated December 2001, Added 2001-12-26, Author Peter Varhol, Publisher JavaPro). Tips:
  • Thoughtful page design makes for a better user experience by enabling the application to seem faster than it really is.

http://www.precisejava.com/javaperf/j2ee/EJB.htm
EJB performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla, Publisher PreciseJava). Tips:
  • Use the HttpSession object rather than a Stateful session bean to maintain client state.

http://www.precisejava.com/javaperf/j2ee/Servlets.htm
Servlet performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla, Publisher PreciseJava). Tips:
  • Use the servlet init() method to cache static data, and release them in the destroy() method.
  • Use StringBuffer rather than using + operator when you concatenate multiple strings.
  • Use the print() method rather than the println() method.
  • Use a ServletOutputStream rather than a PrintWriter to send binary data.
  • Initialize the PrintWriter with the optimal size for pages you write.
  • Flush the data in sections so that the user can see partial pages more quickly.
  • Minimize the synchronized block in the service method.
  • Implement the getLastModified() method to use the browser cache and the server cache.
  • Use the application server's caching facility.
  • Session mechanisms from fastest to slowest are: HttpSession, Hidden fields, Cookies, URL rewriting, the persistency mechanism.
  • Remove HttpSession objects explicitly in your program whenever you finish the session.
  • Set the session time-out value as low as possible.
  • Use transient variables to reduce serialization overheads.
  • Disable the servlet auto reloading feature.
  • Tune the thread pool size.

http://www.onjava.com/pub/a/onjava/2002/07/17/web.html
High load web servlets (Page last updated July 2002, Added 2002-07-24, Author Pier Fumagalli, Publisher OnJava). Tips:
  • Hand off requests for static resources directly to the web server by specifying the URL, not by redirecting from the servlet.
  • Use separate webservers to deliver static and dynamic content.
  • Cache as much as possible. Make sure you know exactly how much RAM you can spare for caches, and have the right tools for measuring memory.
  • Load balance the Java application using multiple JVMs.
  • Use ulimit to monitor the number of file descriptors available to the processes. Make sure this is high enough.
  • Logging is more important than the performance saved by not logging.
  • Monitor resources and prepare for spikes.

http://www.precisejava.com/javaperf/j2ee/JSP.htm
JSP performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla, Publisher PreciseJava). Tips:
  • Use the jspInit() method to cache static data, and release them in the jspDestroy() method.
  • Use the jspInit() method to cache static data.
  • Use StringBuffer rather than using + operator when you concatenate multiple strings.
  • Use the print() method rather than the println() method.
  • Use a ServletOutputStream rather than a PrintWriter to send binary data.
  • Initialize the PrintWriter with the optimal size for pages you write.
  • Flush the data in sections so that the user can see partial pages more quickly.
  • Minimize the synchronized block in the service method.
  • Avoid creating a session object with the directive <%@ page session="false" %>
  • Increase the buffer size of System.out with the directive <%@ page buffer="12kb" %>
  • Use the include directive instead of the include action when you want to include another page.
  • Minimize the scope of the 'useBean' action.
  • Custom tags incur a performance overhead. Use as few as possible.
  • Use the application server's caching facility, and the session and application objects (using getAttribute()/setAttribute()). There are also third-party caching tags available.
  • Session mechanisms from fastest to slowest are: session, Hidden fields, Cookies, URL rewriting, the persistency mechanism.
  • Remove 'session' objects explicitly in your program whenever you finish the session.
  • Reduce the session time-out as low as possible.
  • Use 'transient' variables to reduce serialization overheads.
  • Disable the JSP auto reloading feature.
  • Tune the thread pool size.

http://www.onjava.com/pub/a/onjava/2002/07/10/jboss.html
Clustering with JBoss (Page last updated July 2002, Added 2002-07-24, Authors Bill Burke, Sacha Labourey, Publisher OnJava). Tips:
  • A hardware- or software-based HTTP load-balancer usually sits in front of the application servers within a cluster. The load balancer can decrypt HTTPS requests and distribute load.
  • HTTP session replication is expensive for a J2EE application server. If you can live with forcing a user to log in again after a server failure, then an HTTP load-balancer probably provides all of the fail-over and load-balancing functionality you need.
  • If you are storing things other than EJB Home references in your JNDI tree, then you may need clustered JNDI.

http://java.ittoolbox.com/pub/SC071902/httprevealer_servlets_itx.htm
Speeding web page downloads using compression (Page last updated July 2002, Added 2002-07-24, Author Steven Chau, Publication HttpRevealer.com, Publisher HttpRevealer.com). Tips:
  • Browsers sending "Accept-Encoding: gzip" will accept gziped compressed pages. Return the page compressed with "Content-Encoding: gzip" using GZIPOutputStream.
  • Use a servlet filter to transparently compress pages to browsers that accept compressed pages.

http://www.stqemagazine.com/featured.asp?id=10
Web application scalability. (Page last updated June 2000, Added 2001-05-21, Author Billie Shea, Publisher STQE Magazine). Tips:
  • Web application scalability is the ability to sustain the required number of simultaneous users and/or transactions, while maintaining adequate response times to end users.
  • The first solution built with new skills and new technologies will always have room for improvement.
  • Avoid deploying an application server that will cause embarrassment, or that could weaken customer confidence and business reputation [because of bad response times or lack of calability].
  • Consider application performance throughout each phase of development and into production.
  • Performance testing must be an integral part of designing, building, and maintaining Web applications.
  • There appears to be a strong correlation between the use of performance testing tools and the likelihood that a site would scale as required.
  • Automated performance tests must be planned for and iteratively implemented to identify and remove bottlenecks.
  • Validate the architecture: decide on the maximum scaling requirements and then performance test to validate the necessary performance is achievable. This testing should be done on the prototype, before the application is built.
  • Have a clear understanding of how easily your configurations of Web, application, and/or database servers can be expanded.
  • Factor in load-balancing software and/or hardware in order to efficiently route requests to the least busy resource.
  • Consider the effects security will have on performance: adding a security layer to transactions will impact response times. Dedicate specific server(s) to handle secure transactions.
  • Select performance benchmarks and use them to quantify the scalability and determine performance targets and future performance improvements or degradations. Include all user types such as "information-gathering" visitors or "transaction" visitors in your benchmarks.
  • Perform "Performance Regression Testing": continuously re-test and measure against the established benchmark tests to ensure that application performance hasn?t been degraded because of the changes you?ve made.
  • Performance testing must continue even after the application is deployed. For applications expected to perform 24/7 inconsequential issues like database logging can degrade performance. Continuous monitoring is key to spotting even the slightest abnormality: set performance capacity thresholds and monitor them.
  • When application transaction volumes reach 40% of maximum expected volumes, it is time to start executing plans to expand the system

http://www.stqemagazine.com/featured.asp?id=15
Web Load Test Planning (Page last updated April 2001, Added 2001-05-21, Author Alberto Savoia, Publisher STQE Magazine). Tips:
  • The only reliable way to determine a system?s scalability is to perform a load test in which the volume and characteristics of the anticipated traffic are simulated as realistically as possible.
  • It is hard to design and develop load tests that come close to matching real loads.
  • Characterize the anticipated load as objectively and systematically as possible: use existing log files where possible; characterize user sessions (pages viewed - number and types; duration of session; etc). Determine the range and distribution of variations in sessions. Don't use averages, use representative profiles.
  • Estimate target load and peak levels: estimate overall and peak loads for the server and expected growth rates.
  • Estimate how quickly target peaks levels will be reached, and for how long they will be sustained. The duration of the peak is important and the server must be designed to handle it.
  • The key elements of a load test design are: test objective (e.g. can the server handle N sessions/hr peak load level?); pass/fail criteria (e.g. pass if response times stay within define values); script description (e.g. user1: page1, page2, ...; user2: page1, page3, start transaction1, etc); scenario description (which scripts at which frequency, and how load increases).

http://www.theserverside.com/resources/articles/JSP-Performance/ProJsp.html
Performance chapter (chapter 20) from "Professional JSP 2nd Edition" (Page last updated August 2001, Added 2001-10-22, Author Simon Brown, Robert Burdick, Darko Cokor, Jayson Falkner, Ben Galbraith, RodJohnson, Larry Kim, Casey Kochmer, Thor Kristmundsson, Sing Li, Dan Malks, Mark Nelson, Grant Palmer, Bob Sullivan, Geoff Taylor, John Timney, Sameer Tyagi, Geert Van Damme, Steve Wilkinson, Publisher The Server Side). Tips:
  • The user's view of the response time for a page view in his browser depends on download speed and on the complexity of the page. e.g. the number of graphics. A poorly-designed highly graphical dynamic website could be seen as 'slow' even if the web downloads are individually quite fast.
  • No web application can handle an unlimited number of requests; the trick in optimization is to anticipate the likely user demand and ensure that the web site can gracefully scale up to the demand while maintaining acceptable levels of speed.
  • Profile the server to identify the bottlenecks. Note that profiling can be done by instrumenting the code with measurement calls if a profiler is unavailable.
  • One stress test methodology is: determine the maximum acceptable response time for getting a page; estimate the maximum number of simultaneous users; simulate user requests, gradually adding simulated users until the web application response delay becomes greater than the acceptable response time; optimize until you reach the desired number of users.
  • Pay special attention to refused connections during your stress test: these indicate the servlet is overwhelmed.
  • There is little performance penalty to using an MVC architecture.
  • Use resource pools for expensive resources (like database connections).
  • Static pages are much faster than dynamic pages, where the web server handles static pages separately.
  • Servlet filtering has a performance cost. Test to see if it is an acceptable cost.
  • Ensure that the webserver is configured to handle the expected number of user for example: enough ready sockets; enough disk space; enough CPU.
  • Use the fastest JVM you have access to.

http://theserverside.com/home/thread.jsp?thread_id=3276
Some performance tips (Page last updated January 2001, Added 2001-01-19, Author Shyam Lingegowda, Publisher The Server Side). Tips:
  • Factor out constant computations from loops. For Servlets, push one time computations into the init() method.

http://www.onjava.com/pub/a/onjava/2002/01/09/dataexp1.html
Expiring cached data (Page last updated January 2001, Added 2002-01-25, Author William Grosso, Publisher OnJava). Tips:
  • Servlet sessions expire after a settable timeout, but screens that automatically refresh can keep a session alive indefinitely, even when the screen is no longer in use.

http://www.aceshardware.com/read.jsp?id=45000251
Report of how Ace's Hardware made their SPECmine tool blazingly fast (Page last updated December 2001, Added 2002-02-22, Author Chris Rijk, Publisher Ace's Hardware). Tips:
  • Tranform your data to minimize the costs of searching it.
  • If your dataset is small enough, read it all into memory or use an in-memory database (keeping the primary copy on disk for recovery).
  • An in-memory datavase avoids the following overheads: no need to pass data in from a separate process; less memory allocation by avoiding all the data copies as it's passed between processes and layers; no need for data conversion; fine-tuned sorting and filtering possible; other optimizations become simpler.
  • Pre-calculation makes some results faster by making the database data more efficient to access (by ordering it in advance for example), or by setting up extra data in advance, generated from the main data, to make calculating the results for a query simpler.
  • Pre-determine possible data values in queries, and use boolean arrays to access the chosen values.
  • Pre-calculate all formatting that is invariant for generated HTML pages. Cache all reused HTML fragments.
  • Caching many strings may consume too much memory. IF memory is limited, it may be more effective to generate strings as needed.
  • Write out strings individually, rather than concatenating them and writing the result.
  • Extract common strings into an identical string object.
  • Compress generated html pages to send to the user, if their browser supports compressed html. This is a heavier load on the server, but produces a significantly faster transfer for limited bandwidth clients.
  • Some pages are temporarily static. Cache these pages, and only re-generate them when they change.
  • Caching can significantly improve the responsiveness of a website.

http://www-106.ibm.com/developerworks/webservices/library/ws-testsoap/
Scaling SOAP-based web services. (Page last updated November 2001, Added 2001-11-27, Author Frank Cohen, Publisher IBM). Tips:
  • Use simple SOAP data types (String, Int, Float, NegativeInteger).
  • Each new data type introduces a serializer to convert from the XML value into a Java value and back again, which may cause performance problems.
  • SOAP messages move much more data than the average HTTP GET or POST call, adversely impacting network performance.

http://www.sys-con.com/java/article.cfm?id=712
J2EE challenges (Page last updated June 2001, Added 2001-07-20, Author Chris Kampmeier, Publisher Java Developers Journal). Tips:
  • To ensure good performance use experienced J2EE builders and use proven design patterns.
  • Consider the impact of session size on performance.
  • Avoid the following common mistakes: Failure to close JDBC result sets, statements, and connections; Failure to remove unused stateful session beans; Failure to invalidate HttpSession.
  • Performance requirements include: the required response times for end users; the perceived steady state and peak user loads; the average and peak amount of data transferred per Web request; the expected growth in user load over the next 12 months.
  • Note that peak user loads are the number of concurrent sessions being managed by the application server, not the number of possible users using the system.
  • Applications that perform very little work can typically handle many users for a given amount of hardware, but can scale poorly as they spend a large percentage of time waiting for shared resources.

http://www.sys-con.com/java/article.cfm?id=673
J2EE Application servers (Page last updated April 2001, Added 2001-04-20, Authors Christopher G. Chelliah and Sudhakar Ramakrishnan, Publisher Java Developers Journal). Tips:
  • Application server caching should include web-page caches and data access caches. Other caches include caching servers which "guard" the application server, intercepting requests and either returning those that do not need to go to the server, or rejecting or delaying those that may overload the app server.

http://java.oreilly.com/news/jsptips_1100.html
Hans Bergsten's top ten JSP tips (Page last updated November 2000, Added 2001-01-19, Author Hans Bergsten, Publisher O'Reilly). Tips:
  • The include directive (<%@ include file="filename.inc" %>) is faster than the include action (<jsp:include page="pagename.jsp" flush="true"/>).
  • redirects are slower than forwards because the browser has to make a new request.
  • Database access is typically very expensive in terms of server resources. Use a connection pool to share database connections efficiently between all requests, but don't use the JDBC ResultSet object itself as the cache object.

http://www.onjava.com/pub/a/onjava/2001/03/01/pseudo_sessions.html
Pseudo Sessions for JSP, Servlets and HTTP (Page last updated March 2001, Added 2001-03-21, Author Budi Kurniawan, Publisher OnJava). Tips:
  • Use pseudo sessions rather than HttpSessions to improve web server scalability.
  • Pseudo sessions reside on file instead of in memory, thus both decreasing memory and allowing sessions to be distributed across multiple servers.
  • Pseudo sessions do not use cookies, instead they alter URLs to encode the session, and so reduce the generation of session objects by cookie-declining browsers.

http://www.javaworld.com/javaworld/jw-02-2001/jw-0223-extremescale.html
Clustering for J2EE and Java application servers. Looks at Bluestone Total-e-server, Sybase Enterprise Application Server, SilverStream Application Server, and WebLogic Application Server. (Page last updated February 2001, Added 2001-03-21, Author Abraham Kang, Publisher JavaWorld). Tips:
  • Database and filesystem session persistence can limit scalability when storing large or numerous objects in the HttpSession.
  • To scale the static portions of your Website, add Web servers; to scale the dynamic portions of your site, add application servers.

http://forums.itworld.com/webx?14@@.ee6bdcf/598!skip=542
Avoiding memory leaks in EJBs (Page last updated April 2001, Added 2001-05-21, Author Govind Seshadri, Publisher IT World). Tips:
  • Make sure that any beans which have session scope implement the HttpSessionBindingListener interface
  • Explicitly release the user's session by invoking invalidate() when they log out.
  • Try setting the session invalidation interval to a smaller value than the default 30 minutes.
  • Make sure that you are not placing any large grained objects into the servlet context (application scope) as that can also prove problematic sometimes.

http://www.java-pro.com/upload/free/features/Javapro/2001/07jul01/ah0107/ah0107-1.asp
Experiences building a servlet (Page last updated June 2001, Added 2001-06-18, Author Asif Habibullah, Jimmy Xu, Publisher Java Pro). Tips:
  • Keep the size of the client tier small so that downloads are fast.
  • Use the servlet init() and destroy() methods to start and stop limited and expensive resources, such as database connections.
  • Make the servlets thread-safe and use connection pooling.
  • Use PreparedStatements rather than plain Statement objects.
  • Use database stored procedures.

http://www.devx.com/upload/free/Features/Javapro/2002/02feb02/bk0202/bk0202-1.asp
Servlet 2.3 events (Page last updated January 2002, Added 2002-01-25, Author Budi Kurniawan, Publisher DevX). Tips:
  • The Servlet 2.3 specification adds application and session events. [Event driven applications can often be scaled more easily than process driven applications].

http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-filters.html
Servlet Filters (Page last updated June 2001, Added 2001-07-20, Author Jason Hunter, Publisher JavaWorld). Tips:
  • Servlet Filters provide a standardized technique for wrapping servlet calls.
  • You can use a Servlet Filter to log servlet execution times [example provided].
  • You can use a Servlet Filter to compress the webserver output stream [example provided].

http://www.onjava.com/pub/a/onjava/2001/09/18/jboss.html
Implementing clustering on a J2EE web server (JBoss+Jetty) (Page last updated September 2001, Added 2001-10-22, Author Bill Burke, Publisher OnJava). Tips:
  • Hardware load balancers are a simple and fast solution to distributing HTTP requests to clustered servers.

http://developer.java.sun.com/developer/qow/archive/153/index.jsp
Minimizing space taken by HTTP downloads (Page last updated October 2001, Added 2001-10-22, Authors Gary Adams and Eric Giguere, Publisher Sun). Tips:
  • Use HttpConnection.getLength() to determine the number of bytes needed to to hold the data from a download.
  • Use a ByteArrayOutputStream to accumulate results if the content length is indeterminate.
  • The best performance is obtained from a 1.1 compliant webserver using persistent connections.

http://www.javaworld.com/javaworld/jw-05-2001/jw-0504-cache.html
Faster JSP with caching (Page last updated May 2001, Added 2001-05-21, Author Serge Knystautas, Publisher JavaWorld). Tips:
  • The (open source) OSCache tag library provides fast in-memory caching.
  • Cache pages or page sections for a set length of time, rather than update the page (section) with each request.
  • Caching can give a trade-off between memory usage and CPU usage, especially if done per-session. This trade-off must be balanced correctly for optimal performance.

http://www.javareport.com/html/from_pages/article.asp?id=4702&mon=9&yr=2001
Architecting and Designing Scalable, Multitier Systems (Page last updated August 2001, Added 2001-10-22, Author Michael Minh Nguyen, Publisher Java Report). Tips:
  • Separate the UI controller logic from the servlet business logic, and let the controllers be mobile so they can execute on the client if possible.
  • Validate data as close to the data entry point as possible, preferably on the client. This reduces the network and server load. Business workflow rules should be on the server (or further back than the front-end).
  • You can use invisible applets in a browser to validate data on the client.

http://www.sys-con.com/java/article.cfm?id=1081
Optimizing dynamic web pages (Page last updated July 2001, Added 2001-07-20, Author Helen Thomas, Publisher Java Developers Journal). Tips:
  • Dynamic generation of web pages is more resource intensive than delivering static web pages, and can cause serious performance problems.
  • Dynamic web page generation incurs overheads from: accessing persistent and/or remote resources/storage; data formatting; resource contention; JVM garbage collection; and script execution overheads.
  • Dynamic content caching tries to mitigate Dynamic web page generation overheads by reusing content that has already been generated to service a request.
  • JSP cache tagging solutions allow page and fragment level JSP output to be automatically cached.
  • On highly personalized sites page-level caching results in low cache hit rates since each page instance is unique to a user.
  • Component-level caching applies more extensively when components are reused in many pages, but requires manual identification of bottleneck components.

http://www.sys-con.com/weblogic/article.cfm?id=102
Precompiling JSPs (Page last updated July 2002, Added 2002-07-24, Author Steve Mueller, Scot Weber, Publisher Weblogic Developers Journal). Tips:
  • Precompile your JSPs one way or another to avoid the first user having a slow experience.

http://www.theserverside.com/resources/article.jsp?l=Is-EJB-Appropriate
Deciding whether EJB is appropriate. (Page last updated September 2001, Added 2001-10-22, Author Ed Roman, Publisher The Server Side). Tips:
  • An HTTP layer is not always necessary. Connecting directly to EJBs is faster and provides automatic load balancing.

http://www.aikido.ozactivity.com.au/doc/en/administration/server_tune_procs.html
Tuning tips intended for Sun's "Web Server" product, but actually generally applicable. (Page last updated 1999, Added 2000-10-23, Author ? - a Sun document, Publisher Aikido). Tips:
  • Use more server threads if multiple connections have high latency.
  • Use keep-alive sockets for higher throughput.
  • Increase server listen queues for high load or high latency servers.
  • Avoid or reduce logging.
  • Buffer logging output: use less than one real output per log.
  • Avoid reverse DNS lookups.
  • Write time stamps rather than formatted date-times.
  • Separate paging and application files.
  • A high VM heap size may result in paging, but could avoid some garbage collections.
  • Occasional very long GCs makes the VM hang for that time, leading to variability in service quality.
  • Doing GC fairly often and avoiding paging is more efficient.
  • Security checks consume CPU resources. You will get better performance if you can turn security checking off.

http://m5.peakin.com/html/body_performance.html
Various tips. For web servers? (Page last updated 2000, Added 2000-10-23, Author ?, Publisher ?). Tips:
  • Compression uses significant system resources. Don't use it on a server unless necessary.

http://docs.iplanet.com/docs/manuals/fasttrak/41/servlets/1-using.htm#17322
iPlanet Web Server guide to servlets, with a section at the end on "Maximizing Servlet Performance". (Page last updated July 2000, Added 2001-02-21, Author ?, Publisher Sun). Tips:
  • Try to optimize the servlet loading mechanism, e.g. by listing the servlet first in loading configurations.

http://developer.java.sun.com/developer/community/chat/JavaLive/2001/jl1113.html
Sun community chat on iPlanet (Page last updated November 2001, Added 2001-12-26, Author Edward Ort, Publisher Sun). Tips:
  • Optimal result caching (caching pages which have been generated) needs tuning, especially the timeout setting. Make sure the timeout is not too short.

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...