Tuesday, August 12, 2014

Web page performance - Myth and solution...

At different points in my journey in software industry, I got engaged in discussions/exercises, which are aimed towards improving the performance of the product (For now, let’s constrain it to only to web based products). I have learnt a lot from all such engagements, but at the same time, I feel that there is a lot of gap, the way people see performance and aspire to improve it. Let’s dig a little deep and understand the objective and how to achieve it.

Define the performance GOAL
Performance improvement is something, which at no point of time you can say with 100% confidence that you have achieved it completely. It can be an endless exercise and you do it endlessly only when you have INFINITE people and time to do it. But the reality is different. So, it boils down to the fact that you should come up with a smart GOAL for performance to ensure smart ROI.  

How to define GOAL
Defining the goal for your web page performance can be a tedious exercise. Most of the time, I have encountered people having random goals (page load time less than 2 secs.) without doing enough homework. IMO, before stating the goal, one should first analyse following parameters - 
  • Consumer: It sounds reasonable and obvious to first figure out the consumer for whom you are improving the performance. For majority of the cases, I find two main categories here.
    • The real end user
    •  Search engine crawlers
In case you are not worried much about SEO then you can consider yourself in the luckier lot who do not need to think about the later.
  • Platform: Performance numbers vary significantly based on the platform e.g. if your web page is only for mobile then the perf. score target can be significantly different from a web page which is only serving on desktop browser. 
  • Page budget: There have been numerous discussions on the obesity of internet. This obesity comes with a cost to performance. Hence we must define the page budget upfront and performance goal should be in accordance with the page budget. The idea behind the page budget is to define amount of content (text, video, image etc…), dynamism, 3rd party assets you want to load on the page. Due to the nature of business, if you provide a very high budget to your page, then you should compromise your performance goals accordingly.
  • Performance metric: Now it boils down to which metric is the best to track the performance of the page? There are so many metrics related to page performance. Traditionally page load time has been the de facto metrics, which I have found everyone emphasizing on while talking about page load performance. I am not sure about the reason but the reason can be as basic as “it is easy to understand” compared to other more technical metrics. IMO, correct metric definition is very important part of the overall optimisation strategy
    • Speed Index: For end user what matters most is how quickly he/she can start consume the content on the page. How does it matter if one ajax call on the page is taking 10 secs in the background but most of the content is loaded for consumption for the end user fairly quickly. Although the page load time for such pages will not be very healthy but user is not restricted from consuming the content of the page unless page load event is not fired for the page. So, it reasonably intuitive that if you device a metric which gives score around how quickly the content is rendering for a given page and optimizing that will yield better end user satisfaction.  I find Speed Index from Webpagetest.org to be an apt metric for the same.
    •  TTFB for search engines: People have been experimenting with various page performance metrics to understand its impact on SEO. Moz guys did a thorough analysis around it to understand the relation between a given performance metric and SEO rank. And the results are not counter-intuitive. As per the result the time-to-first-byte (TTFB) has a correlation with the search rankings.

Lower TTFB leading to higher search rank position.

No correlation between page load time and search rank position.

For more detailed report access Moz report here
  • Competitive analysis:  At the beginning when you are building the product first time, it becomes really complex to come up with target numbers for performance metrics. In such cases, you can get a lot of clue from competitive landscape. This analysis can help you both in terms of setting up the goal for performance metrics and page budget.

Defining the right goal is almost half the battle won. All of above can help you in terms of coming up with the right performance GOAL for your pages. Now it all boils down to how to achieve the goal and maintain/improve on a regular basis.  There are many technology write-ups about tweaking performance at DB level, server end and UI level. But IMO, the most important piece is to inject right hooks in development process so that everyone remains sensitive about performance.  Below items which can provide you some clue on these lines:

Performance in product design  
A large part of performance goal can be achieved by right design of product. I am firm believer that the sensitivity about performance should start from the product inception stage. Brad frost has described it beautifully over here. The requirement document should clearly mention about performance goals for pages considering the above-mentioned parameters.

Performance measurement tools integration with Continuous integration system
During regular development cycle, it is very important to raise alarms at the very early stage in case there is degradation in performance score for a given page. It is almost impossible to achieve this in a manual way hence one should integrate tools, which provide the relevant scores with each build and raise an alarm in case of degradation. You can use tools like Google PageSpeed Insight score for such purpose.

Knowledge sharing
I have seen many instances where in people act on performance improvements only when there is an alarm raised for it. I attribute it to lack of awareness, which can be reduced significantly by creating a knowledge-sharing environment. 

I could have covered the nitty-gritty details of perf. Optimization in a given technology but I believe that more important part is to have a smart approach. Rest I will leave it to you decide whether you want to jump on the problem in a reactive way or …

Sunday, March 24, 2013

Complexity in software design

During last many years of my career in software development, I came across many systems. Knowing about all those systems and their designs was really an enriching experience but somewhere in the back of my mind, this question remained unanswered: What is an appropriate design?

Till now, I have come across with many designers/architects/developers/testers in industry and have heard from them about their approaches on designing a system against a given requirement set. Fortunately/unfortunately, I mostly came across with people who were extremists in their approach towards design. For some of them, design is nothing but a sequence of method calls and for rest it was always making things as complex as possible (in the name of futuristic, scalable, generic etc…)

I can safely say that these two extreme approaches can be labeled as under-design and over-design respectively. Both of these approaches may seem to be opposite of each other, but as far as repercussions are concerned, most of the time they lead you to very similar situations (surprisingly) like dump the software, redesign, rewrite, refactor etc. What actually happens depends upon up to what level of extreme approach was taken.

The challenge is how do you avoid doing the same or, identify if you are already in this trap? There is no generic answer to this question but of course, some of the checks and balances can always be put to ensure that you are not leading in the same direction.
  • Make sure that product is not too complex for users to use: Everything starts from here, if the product itself is not simple and beautiful, then there is high probability that you will end up having a complex design to build it. This is very costly and frustrating situation to be in as in this case, even if you have rightly skilled people to do the software development, when the product goes to the market, no one likes it, as it was too complex to use.
  • Understand the right use cases before designing: This is a prerequisite of software design. Never jump for design, if you are not fully aware of the right and complete use cases of the system. Knowing the end user workflow might not be sufficient and hence it is important to understand the use cases relevant for different components of the software.
  • Design against the real requirements not against your own intellectual dreams: Many of the times under the shadow of beautiful words like generic, scalable, modular, futuristic, flexible, designers end up defining a small problem into something which is overly complex to build. This not only complicates things for engineers but also creates delays for time to market, which could be potential business risk in this fast moving competitive world.
  • Design/implement in such a way so that others can understand: Even though it sounds strange but the reality is that it is more difficult to make simple things. For the longevity of any system, it is very important that others also understand it properly. If the system is too complex to understand then it is very likely that either it a case of under/over design.  
  • Technology and product domain both are equally important: Involve the right set of people while designing the system. It is not only important that the person is knowledgeable enough of the technology world but also aware of the domain, product requirements etc. It is a common practice that we assume that a person who has good experience in industry will do justice and with that assumption, we end up giving the design problem to a new senior person without ensuring that he/she is fully clear about the product requirements etc… In such cases, the person tend to prove his knowledge and skills in the whole exercise and tries to push most of the things which he/she knows about, which results into unnecessarily complex system.
  • Little knowledge is very dangerous: Sometimes, the problem is in hands of those people who do not posses enough experience and for them implementation of any system is nothing but a set of program statements partitioned into various methods/functions. This leads to a non-maintainable system where in any change in the system leads to a rewrite of the system. Hence it is very-2 important that the problem is given to the right set of people. There are plenty of engineers in the industry who possess little knowledge of things and pose as experts. If you hand over the problem to such people, their first attempt is always to prove themselves and in doing so, they propose to use tools, technologies, patterns which they have used. The net result is very complex.
Enough of dos and don’ts, let us go through some concrete example to understand some of the about mentioned points.

  • The requirement is to write a small program to reverse a string and without knowing the context of program usage, the person in charge starts assuming cases like
    • What if the input string is too big to fit in the main memory of computer?
    • What if the string contains double byte characters?
    • What if there is more than one string to be reversed. Etc …
  • You were supposed to design an employee management system and the person in charge of design starts thinking about
    • Will the database which contains the Employee table be able to handle more than 10 billion rows.. Come on, are you assuming the company to hire its employees from Mars?
    • What if relational DBs become a bottleneck for scale, so why don’t we think about the big data storage technologies?
    • What if the no. of concurrent request to the system goes beyond a limit and our normal HTTP server will not be able to handle it? Etc…
Without the context of the requirement and use cases, some of these what ifs may sound like genuine ones but in the given situations they are nothing but over complications. It is very easy to get trapped with these questions and companies end up paying lots of cost for hypothetical (so called futuristic) requirements. There is a very thin line between proper design and over/under design. Of course one should make things flexible, configurable, scalable etc., but up to what extent is the question, you need to answer in your own context. While designing the system, it is equally important to keep in mind the following aspects:
  • Long-term maintainability of the system.
  • Easy traceability: In case of errors, one should be able to trace back the faulty component easily. The components can be debugged easily.
  • Simple to understand for others to use or, change.
  • In case of malfunctioning, the system should be able to provide the right alert notification about it.
To end with one should always check against the following statement:
"When your design actually makes things more complex instead of simplifying things, you’re over engineering."

Time to say bye for now. In case you are interested in reading more on this topic here are some relevant references:

This book covers some of the items related to this topic nicely. 

Sunday, June 24, 2012

Exciting developments in Spring for Apache Hadoop project

Few days back, Spring source community announced the second milestone of SHDP (Spring for Apache Hadoop) Project. The very first time I had come to know about this initiative from VMWare, I was almost sure that this is going to be a boon for Java spring development community interested in Big data. In the second milestone, they have made it a point to address the major challenges of developers by providing many of the Spring’s powerful concepts for Apache Hadoop development.

Gradually this project is evolving and rightly hitting the main challenges of developers who are working on the Hadoop and its peripheral technologies. The new milestone not only covers the core support for Hadoop based MR Jobs but also provides support for related technologies like HBase, Hive, Pig etc.

For the developers who are using HBase in their stack, this release is a wow moment. Spring has offered its powerful DAO (Data Access Object) concept for HBase. Developers can now use the powerful template for HBase crud without worrying about exception handling, writing boilerplate code or, handling resources and disposing them. This means that you don’t need to worry about tedious tasks like looking up a HBase table, running the query, building a scanner, cleaning up resources etc...

In case you really want to get a feel of how much headache it removes for a developer, here is a sample code snippet provided by Spring source to read each row from a HBase table.

// read each row from 'MyTable' List rows = template.find("MyTable", "SomeColumn", new RowMapper() {   @Override   public String mapRow(Result result, int rowNum) throws Exception {     return result.toString();   } }));

This definitely reduces a lot many lines of code. The other noticeable point is that all different types of exceptions being raised by the underlying HBase APIs are being converted into one DataAccessException which again eases the development for layers involved in CRUD operations with HBase. So the developers who are using HBase in their technology stack are destined to enjoy this release.

There is a lot of good news for the development community who is using Hive and Pig. Spring seems to have support of both clients (Thrift and JDBC) for Hive. For the Thrift client a dedicated namespace has been provided. In case you want to use the JDBC client, one can leverage the rich JDBC support in Spring which provides you facilities like Jdbc template, NamedParameterJdbcTemplate etc. For the pig developers, Spring provides easy configuration and instatiation of pig servers for registering and executing pig scripts either locally and remotely.

There is a lot more like cascading integration, security support for which I am excited to delve into details, but one thing is quite clear that the small elephant is definitely going to enjoy this spring :)

Here are some of the useful links in case you are interested to get into the details of all these developments:

Sunday, February 5, 2012

Hybrid Type Inference support in SpiderMonkey

Few days ago, Firefox prompted me with the pop up window to download and update itself with its recently released version 9.0. I got curious to know about what is new in this version and hence went to read the release notes from Mozilla.

In a very small duration of time, I got delighted with the fact that this release has JavaScript performance improvements as one of the major highlights. I got fascinated with performance improvement claims (~30%) in JavaScript execution. Upon further digging in, my curiosity kept on increasing, when I started reading about its “Hybrid Type Inference” support in its JavaScript engine “SpiderMonkey”.  After studying in detail, it became pretty clear that this is a very significant change in execution strategy for JavaScript and has the potential to set a new trend altogether.

JavaScript as a language has established itself as the de-facto language for client side programming in the world of web development. Its vast popularity across the globe has generated immense interest of global developer’s community and many corporates in this language. This has created a very healthy competition amongst different vendors who want to dominate in the browser war. Google’s Chrome was the first one, which actually introduced a lot many new radical changes in its V8 engine, which forked huge performance improvements in the language execution.

One of the most important was the introduction of JIT compilation in JavaScript. Use of JIT compilation rather than interpretation has generated huge performance benefits. Still the language takes a back seat when you compare the performance of the language with some of the other established languages which use JIT compilation like Java, C# etc.

Where is the gap?
This gap is mostly because JavaScript provides a lot of freedom to its developers. Execution engine pays the cost of this freedom. What kind of freedom, we are talking about here? This freedom is primarily the freedom of developers to treat any variable as any type and the freedom of type extension at runtime.

Let’s get into the detail of the first type of freedom (Typeless nature of language): Languages like JavaScript don’t have the notion of static type, which becomes a bottleneck in generating a very efficient machine code. Let’s consider a very simple case of adding two integer variables and assign the sum to a third variable. If the compiler has to generate a code, where in it has no idea that it is a sum operation of integers then it will emit code which should be able to handle addition of any two types of variables be it int, float, string etc. But assume when the compiler has the knowledge of the types of the variables, which are going to be added then in such cases it become very easy and straightforward for the compiler to generate machine code, which can handle integer addition and the sum results into an integer.

Pure static analysis for Type inference a rescue?
It becomes quite clear that to achieve the performance of languages like Java, C#, generation of Type specific code is quite important. Unfortunately, for wild language like JavaScript, this is not a straightforward task. One way to achieve this is by performing purely static analysis of the code. But the challenge here is that because of the openness of the language, any pure static analysis for inferring Types becomes so computationally heavy that it does not pay for the performance improvements, which it brings in. Also, because the language is Type less and supports prototype for object extension at runtime, it becomes almost impossible for any static Type analyzer to emit out precise code with all type variants. And not generating code for all possible Types is like changing the expected behavior of the code, which by no means can be regarded as a sound strategy.

Here comes the very interesting strategy for type inference implemented in SpiderMonkey shipped with firefox version 9. It supports a hybrid approach to achieve Type inference. This strategy is an outcome of the acceptance of following facts explained earlier.
1. Compiled machine code, which does not have Type notion can’t be as efficient as the one, which gets generated after Type inference.
2. For any pure static analyzer for Type inference, it is quite impossible to do justice on all the fronts:
a. Sound code: The emitted code should be able to take care of all possible Types and object extension at runtime.
b. Cost of analysis: The analyzer should not be very computationally heavy, otherwise the static analysis offsets the performance benefits at the runtime.
3. If we also take into consideration the usage pattern of JavaScript code for many different websites, then it can be realized that many of the times, we end up loading huge amount of JavaScript code for the website but only end up using a small fraction of it.

The Hybrid approach is nothing but to account for only a subset of Types during static analysis and the ones, which are not accounted during the static Type inference analysis, there should be a way to catch those cases dynamically. This approach not only generates the optimized machine code for the most expected Types in the code by doing static Type inference, but also keeps a provision to catch dynamically at the run time for all those cases, which do not score very high as a candidate for possible Type during static analysis.

Of course this approach is not so simple in implementation as it has to provide the capability of dynamically catching the uncommon cases. If you combine the object’s Type extension capability in the language with the earlier challenge then it actually becomes quite complicated scenario. There are many things, which need to be considered while having such a flexible strategy.  

1. Precise and efficient static analyzer.
2. Capability to dynamically catch cases which are not handled through the static analyzer.
3. Dynamically catching the uncommon cases also comes with a cost, which  is not there in the Typed languages. To reduce this further, have provision of supplemental analysis like overflow scenario, definite properties inside objects etc.
4. Recompilation of the code at the runtime to handle the case where in a new Type is identified at the runtime, which was not taken into consideration by the static analyzer.
5. More complicated memory management: Type inference by static analyzer and capability to recompile the code while it is running also brings in additional overhead to memory management. The execution engine needs to ensure that it is only keeping the relevant compiled code in memory and the garbage collector is collecting the rest.

To handle these things, Firefox has not only changed its JavaScript engine (SpiderMonkey) but also had to made relevant changes in its JIT compiler (JaegerMonkey).  If you go into the details of the implementation there are so many things being introduced like sematic triggers, Type constraints, Type barriers etc… But yes these core changes have definitely justified the performance benefits, which it has created. I can’t even imaging, how many million man-hours are being saved by enhancing the performance of the most popular language for client side web development. Hats off to those engineers involved in this improvement.

Here are some of the relevant links related to this topic:

Signing off for this time with a request to provide your fruitful comments…