Application Performance Series- Part 6- Find ways to avoid redirects

This is part 6 of a multiple part series on web performance improvements. The first Introductory blog can be found here. In previous part we discussed benefits of cookie-free domains. In this part we will discuss the negative impact of redirects in web application performance.

Redirect is a phenomenon where user as routed from one URL to another. There can be various reasons for URL redirect, including web site redesign, tracking traffic flow, counting ad impressions, and creating URLs that are easier for users to remember.

There are different kinds of redirects.

  • 300: Multiple Choices (based on Content-Type)
  • 301: Moved Permanently
  • 302: Moved Temporarily (a.k.a. Found)
  • 303: See Other (clarification of 302)
  • 304: Not Modified- It is not really a redirect—it’s used in response to conditional GET requests to avoid downloading data that is already cached by the browser
  • 305: Use Proxy
  • 306: No longer used
  • 307: Temporary Redirect (clarification of 302)

Out of these 301 and 302 are the most popular. Redirects are usually done for HTML documents, but they may also be used when requesting components in the page (images, scripts, etc). Beside considering, the need to of redirect and their uses, biggest disadvantage of redirects is it makes your pages slower. Sometimes this can be total performance killer.

For example, suppose user request for a URL and receives following response from server then there will be a page redirect.

HTTP/1.1 301 Moved Permanently

Location: http://abc2xyz.com/newuri

Content-Type: text/html

In case of redirects the browser automatically takes the user to the URL specified in the Location field. All the information necessary for a redirect is present in the headers, as shown in above example. The body of the response is typically empty. Despite their names, neither a 301 nor a 302 response is cached in practice unless additional headers, such as Expires or Cache-Control, indicate that it should be.

If the head of the HTML document includes meta refresh tag a page redirect will happen after the number of seconds specified in the content attribute:

meta http-equiv=”refresh” content=”0; url=http://abc2xyz.com/newuri”

Another way to perform redirects is by setting the document.location to the desired URL using JavaScript. If there is no other option then to perform a redirect, the preferred technique is to use the standard 3xx HTTP status codes. This makes sure that the Back button works correctly.

How Redirects Hurt Performance

Below is an image is a snapshot of a browser request response, using Yslow. It shows how redirects slow down the user experience.

09201-redirectimage1
Sample Request Response

The first HTTP request is the redirect. Redirects delay the delivery of entire HTML document. Nothing is presented to the user until redirect and HTML document requests are completed. Nothing in the page can be rendered and no components can be downloaded until the HTML document has arrived. Inserting a redirect between the user and the HTML document delays everything in the page. The style-sheets are very much important for the page rendering. But due to redirect they are further delayed. In case of no redirect this html request could have been served to user much early.

Redirects are typically used with requests for the HTML document, but sometimes they are used for components in the page. Such redirects further delay the page output. Below figure shows the HTTP requests for Google Toolbar. It contains four redirects.

Avoiding Redirects

There can be various reasons (good ones) for URL redirect like

  • Web site redesign
  • Tracking traffic flow
  • Counting ad impressions
  • Creating URLs that are easier for users to remember

Though redirect can fix a number of issues as given above for business it may introduce a lot of issues for the end user. If business demands we cannot avoid many of the above mention situations too. So we need to find some alternative solutions which achieve our intended goal at the same time do not cost us on performance front.

So what options we have…

The following sections discuss some of the typical situations in which redirects are used, and alternatives that we can implement to make the user experience better.

Missing Trailing Slash

This kind of redirect happens when a trailing slash (/) is missing from a URL that should otherwise have one. For example,

when we type http://shine.yahoo.com/horoscope in browser it results in a 301 response containing a redirect to http://shine.yahoo.com/horoscope/. The only difference is the addition of a trailing slash (/).

bbcf2-tralingslashimage

A redirect does not happen if the trailing slash is missing after the hostname. For example, http://www.google.co.in does not generate a redirect. However, the resultant URL seen in your browser does contain the trailing slash: http://www.google.co.in/. The automatic appearance of the trailing slash is caused because the browser must specify some path when it makes the GET request. If there is no path, as in http://www.google.co.in, then it uses simply the document root (/):
GET / HTTP/1.1

Sending a redirect when a trailing slash is missing is the default behaviour for many web servers, including Apache. The Alias directive is an easy workaround. Another alternative is to use the mod_rewrite module, but Alias is simpler. The problem with the Horoscope site could be resolved by adding the following to the Apache configuration:

Alias /horoscope /usr/local/apache/htdocs/horoscope/index.html

Handler in Apache 2.0 provides cleaner solution in the form of DirectorySlash directive. Assuming there is a handler named horoscopehandler, the use of DirectorySlash would look as follows:

Moving between Web Sites/ pages

Consider a situation where

  • The website is under re-engineering process. This may happen due changes in technology or any other reason. The URL’s in new system may be different than the existing system. An easy way to transition users from the old URLs to the new ones is to use redirects.
  • Due to certain condition redirect is happening within parts of a web site (type of browser, type of user account, etc.).

Using a redirect to connect two web sites is simple and requires little additional coding. Although redirects reduce the complexity for developers, it degrades the user experience. There are alternatives for integrating two websites without degrading user experience:

  • If the two websites reside on the same server, it’s possible the code itself could be linked. For example, the older handler code could call the new handler code programmatically.
  • If the domain name changes, a DNS record that creates an alias pointing from one domain name to another (a CNAME) can be used to make both hostnames point to the same server.
  • Alias, mod_rewrite, and DirectorySlash are simple solutions to fix this issue.

User Friendly URLs

Redirects are used to make URLs prettier and easier to remember for end users. Suppose the actual URL of the page earlier was:

http://abc.com/xyz1234hjgjdh12333344

It is not easy for a user to type or remember this URL. But if the URL is converted to:

http://abc.com/MyPage

then this is a easy to remember for any user. But internally this URL is linked to the previous URL, which this causes a redirect.

The key is to find a way to have these simpler URLs without the redirects. Rather than forcing users to undergo an additional HTTP request, it would be better to avoid the redirect using Alias, mod_rewrite, DirectorySlash, and directly linking code.

Application Performance Series- Part 5- Use Cookie free Domains for Components

This is part 5 of a multiple part series on web performance improvements. The first Introductory blog can be found here. In previous part we discussed about CDN and how they improve the performance of the web application. In this part we will discuss the benefits of cookie-free domains.

When the browser makes a request for a static image it also sends cookies together with the request. The server doesn’t have any use for those cookies. So they only create network traffic for no good reason. We should make sure static components are requested with cookie-free requests.

To achieve this we should create a sub-domain and host all static components there. If the domain is www.example.org, we can host static components on static.example.org. However, if we have already set cookies on the top-level domain example.org as opposed to www.example.org, then all the requests to static.example.org will include those cookies. In this case, we can buy a whole new domain, host static components there, and keep this domain cookie-free.

Some of good examples are:
Yahoo! uses yimg.com
YouTube uses ytimg.com
Amazon uses images-amazon.com
Another benefit of hosting static components on a cookie-free domain is that some proxies might refuse to cache the components that are requested with cookies.
On a related note, if you wonder if you should use example.org or www.example.org for your home page, consider the cookie impact. Omitting www leaves you no choice but to write cookies to *.example.org, so for performance reasons it’s best to use the www sub-domain and write the cookies to that sub-domain.

Application Performance Series- Part 4- Use Content Delivery Network (CDN)

This is part 4 of a multiple part series on web performance improvements. The first Introductory blog can be found here. In previous part we discussed the pro and cons of DSN. In this part we will analyse how CDN’s can help us improve performance.
Whenever user types any URL in the browser, it sends the request to the server. The request travels all the way from client browser to the server. The server prepares the response and sends it back to the user browser.

The response time of request from browser-server and response back depends upon many factors such as:

  • Bandwidth
  • Network traffic
  • No of hubs in network path
  • Server load
  • Request/response data size
Consider two typical situations as in figure above. In First case the user and server, where website is hosted, are close to each other (in this example: same country, India). In Second case the two are in different countries (in this example: user is in India and server in USA).
So as distance between user and server increases the performance of the site for the user may decrease. As more and more factors, listed above, come into play the more they impact performance.
So what is CDN
According to http://www.webopedia.com content delivery network (CDN) is a system of distributed servers that deliver web-pages and other Web content to a user based on the geographic locations of the user, the origin of the webpage and a content delivery server. CDN is effective in speeding the delivery of content of websites with high traffic and websites that have global reach. The closer the CDN server is to the user geographically, the faster the content will be delivered to the user. CDN’s also provide protection from large surges in traffic.
Content delivery networks are used for B2B interactions and in serving content to consumers. Today, as more aspects of daily life move online, organizations use content delivery network to accelerate static content, dynamic content, mobile content, ecommerce transactions, video, voice, games and so on.
How CDN Works
Whenever a request is made servers nearest to the website visitor respond to the request. The CDN copies the pages of a website to a network of servers that are dispersed at geographically different locations, caching the contents of the page. When a user requests a webpage that is part of a content delivery network, the CDN will redirect the request from the originating site’s server to a server in the CDN that is closest to the user and deliver the cached content. The CDN will also communicate with the originating server to deliver any content that has not been previously cached.
The process of bouncing through a CDN is nearly transparent to the user. The only way a user would know if a CDN has been accessed is if the delivered URL is different than the URL that has been requested.
CDN Pros
The average user’s bandwidth increases every year, but a user’s proximity to your web server still has an impact on a page’s response time. Though the bandwidth is increasing so the content of the web pages. The web pages are not simple and light weight any more. They have lots of complex data of different types. So if the web servers are closer to the user, the response time of HTTP request is improved. Suppose the website is using multiple servers for hosting different components like images/assets, content etc. If these component web servers are closer to the user, the response times of all such components HTTP requests are improved. Due to these advantages it’s better to disperse the component web servers. This not only achieves a bigger reduction in response times, it’s also easier.
In addition to improved response times, CDNs bring other benefits. Their services include backups, extended storage capacity, and caching. A CDN can also help absorb spikes in traffic, for example, during times of peak weather or financial news, or during popular sporting or entertainment events.  
CDN Cons
In case of shared CDN hosting the web site response time can be affected by traffic from other web sites. A CDN service provider typically shares its web servers across all its clients. Another drawback is the occasional inconvenience of not having direct control of the content servers. For example, modifying HTTP response headers must be done through the service provider rather than directly by our own operations team. So, if CDN service provider’s performance degrades, so does our site’s.
Where can be used?
CDNs are used to deliver static content, such as images, scripts, style-sheets, and Flash. Serving dynamic HTML pages involves specialized hosting requirements: database connections, state management, authentication, hardware and OS optimizations, etc. These complexities are beyond what a CDN provides. Static files, on the other hand, are easy to host and have few dependencies. That is why a CDN is easily leveraged to improve the response times for a geographically dispersed user population.

Application Performance Series- Part 3- Reduce DNS Lookups

This is part 3 of a multiple part series on web performance improvements. The first Introductory blog can be found here. In previous part we discussed about the performance measurement tools/plugins for a web application. In this part we will study what is DNS lookup and how it affects web application performance.

What is DNS?
Whenever we type any URL (host name of the web application/page) in browser which is connected to Internet, the request has to be converted to IP address. It’s quite difficult for user to remember the IP address of web site, but quite easy to remember the name. The IP address is necessary for the browser to make its request. Internet is based on finding servers through IP addresses. This is where Domain Name System (DNS) comes in picture. DNS maps hostnames to IP addresses, just as phonebooks map people’s names to their phone numbers. When we type www.abc.com into browser, a request will be made by browser to DNS resolver which returns that server’s IP address.
The biggest benefit of DNS is it adds a layer of indirection between URLs and the actual servers that host them. If due to any reason/s if the IP address of the server changes, DNS will allow users to use the same hostname to connect to the new server.
In case we want to improve performance of the website or increase availability of the site, we can host the application on multiple servers and DNS will help us in identifying the closest server. By adding multiple IP addresses to a hostname, we can achieve high degree of redundancy for a web site.
The biggest drawback of DNS is the time taken to look up the IP address for a given hostname, called DNS lookup. Ideally, this time ranges from 20-120 milliseconds. The browser can’t download anything from this hostname until the DNS lookup process is completed. This response time depends on the DNS resolver typically provided by ISP, the load of requests on it, proximity to it, and bandwidth speed.
DNS Caching
DNS lookups are cached for better performance at different places. This caching can occur on a special caching server maintained by the user’s ISP or local area network. As shown in figure below, after a user requests a hostname, the DNS information remains in the operating system’s DNS cache (“DNS Client service” on Microsoft Windows). Due to this caching any future request for that hostname will not require any DSN lookups, at least for a while.
Level 1
Most browsers have their own caches which is different than the operating system’s cache. As long as the browser keeps a DNS record in its own cache, it doesn’t bother the operating system with a request for the record.
Level 2
If the DSN entry is not found for requested host name at browser’s cache then a request is made to the operating system’s DNS for the same. If the operation system DNS has entry for the host name that is returned to the browser. Else request is forwarded to the remote server.
Level 3
If the DNS entry is not present at operating system DNS then the request is forwarded to remote server.
As the request forwarded from one level to another the impact on application performance will increase. The change in IP address complicates the situation. The cache consumes memory. Therefore, the DNS records have to be periodically flushed from the cache. There are many configuration settings which determine how often they are discarded.
What affects DNS caching
The DNS caching time is decided by the server with the help of time-to-live (TTL) value. The DNS record returned from lookup contains a TTL value. TTL tells client how long the record can be cached. The operating system caches always follow TTL. But the browsers caches often ignore it and set their own time limits. Furthermore, the Keep-Alive feature of the HTTP protocol can override both the TTL and the browser’s time limit.
Browsers put a limit on the number of DNS records cached, regardless of the time the records have been in the cache. If the user visits many different sites with different domain names in a short period of time, earlier DNS records are discarded and the domain must be looked up again. If the browser discards a DNS record, the operating system cache might still have it, and that saves the day because no query has to be sent over the network, thereby avoiding what could be noticeable delays.
How to reduce DNS Lookups
When the client’s DNS cache is empty (both browser and operating system), the number of DNS lookups is equal to the number of unique hostnames in the web page. This includes the hostnames used in the page’s URL, images, script files, style-sheets, Flash objects, etc. Reducing the number of unique hostnames reduces the number of DNS lookups. Perfect example is Google (http://www.google.com) with only one DNS lookup necessary for the page.
But Google page has minimum couple of downloads, so having a single host name is ideal. But most of websites in the internet world are not so lucky. Reducing the number of unique hostnames means reducing the amount of parallel downloading that takes place in the page. It means avoiding DNS lookups may cuts response times, but will reduce parallel downloads and may increase response times. Some amount of parallelization is always good to speed up things, even if it increases the number of hostnames.
If we take Google.com example, there are only two components in the page. Components are downloaded two per hostname in parallel. So in this case using one hostname minimizes the number of possible DNS lookups while maximizing parallel downloads.
Most pages in today’s world have a number of components. They are not lean as Google. So we can split these components across at least two to four hostnames. This results in a good compromise between reducing DNS lookups and allowing a high degree of parallel downloads. The advantage of using Keep-Alive is that it reuses an existing connection, thereby improving response times by avoiding TCP/IP overhead.

Application Performance Series- Part 1- Where to start

This is part 1 of a multiple part series on web performance improvements. The Introductory blog can be found hereIn introductory post we discussed importance of software development keeping performance performance at center. In this part we will discuss which part affect web application performance the most? Where we can start the performance improvement activity to get maximum output?
Any web application performance improvement activity is a series of calculated tasks. We need to first identify where we can achieve the greatest improvements. There are three main places to consider:

  • Frontend
  • Backend
  • Databases

Though we can group the backend and databases in same group but just for simplicity I have grouped them separately. In case of web applications the performance is always measured with respect to user response time. Whatever performance improvement tasks we do should result in improved user response time. If not then we should re-visit our performance improvement strategy again. Due to many reasons, some of them given below, it is clear that first place to focus is frontend to drastically improve the performance of the web application.

  • First and foremost, generally, the time and resources required to implement the frontend changes is less as compared to others. Improving the backend performance may require change in architecture, code, data retrieval logic etc. These tasks may take longer time than expected.
  • If we could cut the backend response time by 40-60%, this will reduce the overall end user response time by 10-20%. But if we could improve the frontend performance by 40-60% this could result in reduced end user response time upto 40-50%. Many sites likes Google, MSN, Yahoo, Ask etc has proved this point.
Points mentioned in this blog will help us reduce end user response time significantly. But sometimes we may have to take more drastic steps and may reengineer the architecture to achieve the ultimate goal.

Following figure is a snap-shot of Y-slow recordings for a page in a website.

Figure: indicating a page request response flow
As we can observe only 10-20% of user response time is spend in downloading HTML document. Rest of 80-90% is spent downloading other parts/ components of the page. Generally the same story is repeated on all pages in this website. The same is true for most of the sites on web. The point is if we want to reduce the response times of web pages, we have to focus on the 80–90% of the end user experience. Where that 80–90% is spent on? How can it be reduced? How much of this time can be reduced?

In coming blogs we will go through a series of steps that will help us understanding the performance pitfalls and how to improve them.

Application Performance Series- Introduction

Developing software applications is not just writing code, but it is much than that. It’s both science and Art when combined together can produce great quality applications. It is an art of writing efficiently working, fast and secure code. This is especially true when we are working on web applications. Developing a fast, scalable and secure application looks very simple at top. Writing an application which is works as per user expectations with speed and security is complex (but not impossible) to design. Many a time we need to find a middle path between security and performance based on a number of factors.

The design and construction of an application involve many-many decisions, each representing a trade-off. Many a time each alternative has significant positive and negative consequences. In such trading off, we hope to obtain a near-optimal good while minimizing the bad. It’s like “I want to go to heaven and meet god, but I don’t want to die”. Any application development there are three major factors that a project triangle.

 
Achieving all three in ideal circumstances is not possible. There are always tradeoffs and we need to make decision based on the priorities and situations. While developing applications we see time versus memory trade-offs while developing logic, time to market versus code quality. Such trade-offs always have a large impact on the effectiveness and success of the application.
 
But if we have to design and develop performance-oriented web applications then it is not only code that can improve your performance, but we need to pay attention to a lot of other factors too. In this article, I will focus on such areas. While preparing this article I read a lot of article and white papers. Many of these techniques are already used by top most sites in the world and even in my live projects. This is kind of a short summary of all that learning. I hope this will be a baselines guideline for you and will help you improving performance of your applications.

I will divide this article into following sections:

  • Front end or UI  Performance
  • Code behind
  • Database
  • Hardware

The “Front end or UI Performance” part will be generic and mostly not based on any technology (.NET, Java, PHP etc). But The “Code behind” part will specifically be related to .NET stake (ASP.NET, C# etc), because this is my core specialization. I am less familiar with Java or PHP, so sorry guys. In the “Database” part we can relate them to any SQL language but all the examples and code here will be based on SQL-Server.

Before starting next part/s  about performance improvements I will suggest going through my another blog HERE, which gives details of an overview of HTTP and how it can play an important part in performance improvement. 
The series parts are as follows:

HTTP Overview keeping performance in mind

Introduction

HTTP is how browsers and servers communicate with each other over the Internet. Whenever we are working on web application performance improvements, it is very important to understand the working and parts of HTTP that affect performance. HTTP is a client/server protocol made up of requests and responses. HTTP/1.1 is the most common version today, but some browsers and servers still use HTTP/1.0.

A browser sends an HTTP request for a specific URL, and a server hosting that URL sends back an HTTP response. Like many Internet services, the protocol uses a simple, plain-text format. The types of requests are GET, POST, HEAD, PUT, DELETE, OPTIONS, and TRACE. For this discussion we will focus on GET request, which is the most common.A GET request includes a URL followed by headers. The HTTP response contains a status code, headers, and a body. The following example shows the possible HTTP headers when requesting the script myScript.js.

HTTP Request
GET /abc.com/common/myScript.js
HTTP/1.1
Host: abc.com
User-Agent: Mozilla/5.0 (…) Gecko/20131206 Firefox/1.5.0.9
HTTP Response
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Wed, 22 Feb 2013 04:15:54 GMT
Content-Length: 355
var xyz=…

Compression

The output size can be reduced using compression if both the browser and server support it. Browsers let server know their support of compression using the Accept-Encoding header. Servers identify compressed responses using the Content-Encoding header.
HTTP Request
GET /abc.com/common/myScript.js
HTTP/1.1
Host: abc.com
User-Agent: Mozilla/5.0 (…) Gecko/20131206 Firefox/1.5.0.9
Accept-Encoding: gzip,deflate
HTTP Response
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Wed, 22 Feb 2013 04:15:54 GMT
Content-Length: 355
Content-Encoding: gzip
^_\213^H^@^@^@^@^@^@^Cl\217\315j\3030^P\204_E\361IJ…
Please note in above response how the body of the response is compressed.

How Compression Works

Starting with HTTP/1.1, web clients indicate support for compression with the Accept-Encoding header in the HTTP request.

           Accept-Encoding: gzip, deflate

If the web server sees this header in the request, it may compress the response using one of the methods listed by the client. The web server notifies the web client of this via the Content-Encoding header in the response.

          Content-Encoding: gzip

Gzip is currently the most popular, effective and free format compression method. The other compression format is deflate, but it’s slightly less effective and less popular. Browsers that support deflate also support gzip, but several browsers that support gzip do not support deflate, so gzip is the preferred method of compression.

What to Compress

Servers choose what to gzip based on file type. For example gzip can compress follwoing types by default.

1.    HTML documents
2.    Scripts and stylesheets
3.    Any text response including XML and JSON
Image and PDF files should not be gzipped. Trying to gzip them not only wastes CPU resources, it can also potentially increase file sizes. Ideally they should be compressed and optimised by UI developer before using.

Cost of compression

Gzipping takes additional CPU cycles on the server to carry out the compression and on the client to decompress the gzipped file. To determine whether the benefits outweigh the costs you would have to consider the size of the response, the connection bandwidth, and the Internet distance between the client and the server. Generally, it’s worth gzipping any file greater than 1 or 2K. The mod_gzip_minimum_file_size directive, which has a default value of 500 bytes, controls the minimum file size that we would like to compress.

Conditional GET Requests

To reduce the response time of a request browser uses their cache. Whenever a request is made the browser checks if it has a copy of the request in cache. If then it will serve the request. If the browser isn’t sure whether the cache copy still valid, a conditional GET request is made. If the cached copy is still valid, the browser uses the copy from its cache, resulting in a smaller response and a faster user experience.
Typically, the validity of the cached copy is derived from the date it was last modified. The browser knows when the component was last modified based on the Last-Modified header in the response. It uses the If-Modified-Since header to send the last modified date back to the server. Whenever browser makes any conditional request it asking server, “I have a version of this resource with the following last modified date. May I just use it?”
          HTTP Request
GET /abc.com/common/myScript.js
HTTP/1.1
Host: abc.com
User-Agent: Mozilla/5.0 (…) Gecko/20061206 Firefox/1.5.0.9
Accept-Encoding: gzip,deflate
If-Modified-Since: Wed, 22 Feb 2013 04:15:54 GMT
          HTTP Response
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Wed, 22 Feb 2013 04:15:54 GMT

If the component has not been modified since the specified date, the server returns a “304 Not Modified” status code and the body of the response is not sent. This results a smaller and faster response. In HTTP/1.1 the ETag and If-None-Match headers are another way to make conditional GET requests.

ETags (Entity Tags)

Entity tags (ETags) were introduced in HTTP/1.1. ETags are a mechanism that web servers and browsers use to validate cached components. It provides a way to determine whether the component in the browser’s cache and server are same or not. An ETag is a string that uniquely identifies a specific version of a component. The only format constraint is that the string must be inside quotes “”. The origin server specifies the component’s ETag using the ETag response header.
HTTP Request
GET /i/abc.gif HTTP/1.1
Host: abc.com
HTTP Response
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: “10c24bc-4ab-457e1c1f”
Content-Length: 1195
ETags were added to provide a more flexible mechanism for validating entities than the last-modified date. If, for example, an entity changes based on the User-Agent or Accept-Language headers, the state of the entity can be reflected in the ETag. Later, if the browser has to validate a component, it uses the If-None-Match header to pass the ETag back to the origin server. If the ETags match, a 304 status code is returned, reducing the response.
HTTP Request
GET /i/abc.gif HTTP/1.1
Host: abc.com
HTTP Response
            HTTP/1.1 304 Not Modified
The Problem with ETags
ETags are server based, they are typically constructed using attributes that make them unique to a specific server where the site is hosted. This is good when the site is hosted on a single server, which is not always the case. In case of multi server hosted site ETags won’t match when a browser gets the original component from one server and later makes a conditional GET request that goes to a different server. Due to this ETags generated by Apache and IIS for the exact same component won’t match from one server to another. If the ETags don’t match, instead of 304 response that ETags were designed for; they’ll get a normal 200 response along with all the data for the component. This degrades the performance of the web request. If there are n servers in cluster in round-robin rotation, the probability that the ETag in the user’s cache will match the server they land on next is 1/n. If you have 10 servers, the user has a 10% chance of getting the correct 304 response, leaving a 90% chance of getting a wasteful 200 response and full data download.
Expires
Conditional GET requests help loading a page faster, but this still requires roundtrip to server to perform the validity check which adds to response time. The Expires header eliminates the roundtrip to server for validation check by making it clear whether the browser can use its cached copy of a component or not?
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Wed, 22 Feb 2013 04:15:54 GMT
Expires: Wed, 05 Oct 2016 19:16:20 GMT

When the browser sees an Expires header in the response, it saves the expiration date with the component in its cache. As long as the component hasn’t expired, the browser uses the cached version and avoids making any HTTP requests.

Keep-Alive

HTTP is built on top of Transmission Control Protocol (TCP). In early implementations of HTTP, each HTTP request required opening a new socket connection, which results in delayed response because many HTTP requests in a web page go to the same server. For example, most requests for images in a web page all go to a common image server.

Persistent Connections, also known as Keep-Alive in HTTP/1.0, was introduced to solve the inefficiency of opening and closing multiple socket connections to the same server. It lets browsers make multiple requests over a single connection. Browsers and servers use the Connection header to indicate Keep-Alive support. The Connection header looks the same in the server’s response.

HTTP Request
GET /abc.com/common/myScript.js
HTTP/1.1
Host: abc.com
User-Agent: Mozilla/5.0 (…) Gecko/20061206 Firefox/1.5.0.9
Accept-Encoding: gzip,deflate
Connection: keep-alive
HTTP Response
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Wed, 22 Feb 2013 04:15:54 GMT
Connection: keep-alive
The browser or server can close the connection by sending a Connection: close header. Technically, the Connection: keep-alive header is not required in HTTP/1.1, but most browsers and servers still include it.

Pipelining

Pipelining, defined in HTTP/1.1, allows for sending multiple requests over a single socket without waiting for a response. Pipelining has better performance than persistent connections. Unfortunately, pipelining is supported in Internet Explorer after version 7. It is turned off by default in Firefox through version 2. Until pipelining is more widely adopted, Keep-Alive is the way browsers and servers can more efficiently use socket connections for HTTP. This is even more important for HTTPS because establishing new secure socket connections is more time consuming.

SQL Server Functions

Introduction

Functions are kind of reusable components/objects in SQL-Server. It is a set of SQL statements that accepts only input parameters, perform actions and return the result. Function can return only single value or a table value. We can’t use function to Insert, Update, Delete records in the database tables.

SQL Server’s functions are a valuable addition when used wisely. A function, in any programming environment, lets you encapsulate reusable logic and build software of pieces that can be reused and put together in a number of different ways to meet the needs of the users. Functions hide the steps and the complexity from other code. Functions can hide complexity from users and turn a complex piece of code into a re-usable commodity.
SQL Server functions adhere closely to the mathematic definition of a function i.e. a mapping of inputs to outputs, without have side effects. A function with inputs x and y cannot both return x + y and modify the original value of y. As a matter of fact, that function couldn’t even modify y:  it is only able to return a new value.
 

Some highlights of Functions

  • Function must return a value.
  • Functions can have only input parameters for it.
  • Function allows only SELECT statement in it.
  • Function can be embedded in a SELECT statement.
  • Functions can be used in the SQL statements anywhere in the WHERE/ HAVING/ SELECT section.
  • Functions that return tables can be treated as another row-set. This can be used in JOINs with other tables.
  • Inline Function can be thought of as views that take parameters and can be used in JOINs and other Rowset operations.
  • Try-catch block cannot be used in a Function.
  • Transactions are not allowed in Functions.
  • Function should have at least one input parameter.
  • Functions can be called from Procedure.
  • User Defined Function can call only Extended Stored Procedure.
  • Like Stored Procedure, Function can be nested up to 32 levels.
  • User Defined Function can have upto 1023 input parameters while a Stored Procedure can have upto 21000 input parameters.
  • User Defined Function can’t returns XML Data Type.
  • User Defined Function doesn’t support set options like set ROWCOUNT etc.
 

Where we can use a Function?

Functions are an incredibly powerful part of SQL Server. We can use a function almost anywhere we would use a table or column. We can use a function anywhere that we can use a scalar value or a table. Functions can be used in constraints, computed columns,  JOINs, WHERE clauses, in other functions or even in Stored Procedures.

 

Functions can be Deterministic or Nondeterministic

A deterministic function will return the same result when it is called with the same set of input parameters. Adding two numbers together is an example of a deterministic function.
A nondeterministic function, on the other hand, may return different results every time they are called with the same set of input values. Even if the state of the data in the database is the same, the results of the function might be different. The GETDATEfunction, for example, is nondeterministic.
When we create a function, SQL Server will analyze the code we’ve created and evaluate whether the function is deterministic. If our function makes calls to any nondeterministic functions, it will, itself, be marked as nondeterministic. SQL Server relies on the author of a SQL CLR function to declare the function as deterministic using an attribute. Deterministic functions can be used in indexed views and computed columns whereas nondeterministic functions cannot.

Keeping things safe: functions can be schema-bound

If we make changes to database schema after function creation, it may break the function. To prevent Functions from breaking due to schema changes we can create schema bound functions. Attempts to alter objects that are referenced by a schema bound function will fail thereafter. What does this buy us, though? Well, schema binding a function makes it more difficult to make changes to the underlying data structures that would break the functions. To create a schema-bound function we simply specify schema binding as an option during function creation, as shown below.
–Create function to get emp full name
Create functionfnGetEmployeeFullName
(
 @FirstName varchar(50),
 @LastName varchar(50)
)
returns varchar(101)
– this statement is used to make the function schema bound
WITH SCHEMABINDING
As
Begin return (Select @FirstName + ‘ ‘+ @LastName);
End

Behavior if case of NULL

Whenever our function receives NULLinput values, SQL Server will go ahead and run the code in the function and evaluate all of the parameters passed in, even if one of those parameters is a NULL value, and so the output of the function is NULL. This is a waste of processor cycles and we need to avoid this unnecessary work. We could check every parameter that is passed into a function, but that is a lot of code to maintain. If you’re thinking, “there has to be a better way” then you’re absolutely right. When we create the function we can use the RETURNS NULL ON NULL INPUT option, which will cause SQL Server to immediately return NULL if any parameters in the function are NULL-valued. Users of SQL Server 2000 and earlier are out of luck, though, as this feature was introduced in SQL Server 2005.

Types of Function


System Defined Function


SQL Server has many built in Functions which can be used for carrying out variety of operations and calculations. We have two types of system defined function in Sql Server.
  • Scalar Function

Scalar functions operate on a single value and returns a single value. Some examples of useful SQL Server Scalar Functions are:
Scalar Function
Description
abs(-10.67)
This returns absolute number of the given number means 10.67.
rand(10)
This will generate random number of 10 characters.
round(17.56719,3)
This will round off the given number to 3 places of decimal means 17.567
upper(‘dotnet’)
This will returns upper case of given string means ‘DOTNET’
lower(‘DOTNET’)
This will returns lower case of given string means ‘dotnet’
ltrim(‘ dotnet’)
This will remove the spaces from left hand side of ‘dotnet’ string.
convert(int, 15.56)
This will convert the given float value to integer means 15.
  • Aggregate Function

Aggregate functions operate on a collection of values and return a single value. Some examples of useful SQL Server Aggregate Functions are:
Aggregate Function
Description
max()
This returns maximum value from a collection of values.
min()
This returns minimum value from a collection of values.
avg()
This returns average of all values in a collection.
count()
This returns no of counts from a collection of values.

     User Defined Functions

These functions are created by user in database. There are three types of user defined functions.
  • Scalar Function

Scalar functions return a single value. We can use a scalar function “anywhere that a scalar expression of the same data type is allowed in T-SQL statements“. All data types in SQL Server are scalar data types, with the exception of TEXT, NTEXT, ROWVERSION, and IMAGE.
Let’s go through following example:
–Create a table
CREATE TABLE Employee
(
                                                EmpID intPRIMARY KEY,
                                                FirstName varchar(50) NULL,
                                                LastName varchar(50)NULL,
                                                Salary intNULL,
)
 –Insert Data
                     Insert into Employee(EmpID, FirstName, LastName, Salary)  
                               Values (1,‘Balvvant’,‘Bist’, 10000);
                     Insert into Employee(EmpID, FirstName, LastName, Salary)  
                               Values (2,‘Gerard’,‘Dsouza’,20000);
 Insert into Employee(EmpID, FirstName, LastName, Salary)  
           Values (3,‘Amit’,‘Pathak’,30000);
                     –See created table
 Select * fromEmployee
 
                     –Create a scalar function to get emp full name
                     Create functionfnGetEmployeeFullName
                     (
                              @FirstName varchar(50),
                              @LastName varchar(50)
                     )
                     returns varchar(101)
                     As
                     Begin return (Select @FirstName + ‘ ‘+ @LastName);
                     end
                     –Call above created function
                Select dbo.fnGetEmployeeFullName(FirstName,LastName) as Name, Salary  fromEmployee
                     The output of the above SQL statement will be:
                     



  •       Table Valued Functions (TVFs)

Table-valued functions (TVFs) return a table instead of a single value. A table valued function can be used anywhere a table can be used – typically in the FROM clause of a query. TVFs make it possible to encapsulate complex logic in a query. For example, security permissions, business logic etc can be embedded in a TVF. Careful use of TVFs makes it easy to create re-usable code frameworks in the database.
Table-valued Functions (TVFs) differ from scalar functions in that TVFs return an entire table whereas scalar functions only return a single value. This makes them ideal for encapsulating more complex logic or functionality for easy re-use. TVFs have the additional advantage of being executed once to return a large number of rows as opposed to scalar functions which must be executed many times to return many values.
The body of a TVF can either contain just a single statement or multiple statements, but the two cases are handled very differently by the optimizer. If the function body contains just a single statement (often referred to as an “inline TVF”), then the optimizer treats it in a similar fashion to a view in that it will “decompose” it and simply reference the underlying objects and there will be no reference to the function in the resulting execution plan.
However, by contrast, multi-statement TVFs present an optimization problem for SQL Server; it doesn’t know what to do with them. It treats them rather like a table for which it has no available statistics – the optimizer assumes that it the TVF will always return one row. As a result, even a very simple multi-statement TVF can cause severe performance problems.
There are two different types of TVF functions in SQL-Server.

  • Inline Table-Valued Function

Inline table-valued function returns a table variable as a result of actions performed by the function. The value of table variable should be derived from a single SELECT statement.

–Create function to get employees
Create function fnGetEmployee()
returns Table
As
return (Select *from Employee)
–Now call the above created function
— now call the above created function
 
Select * fromfnGetEmployee()

  • Multi-Statement Table-Valued Function 

Multi-statement table-valued function returns a table variable as a result of actions performed by the function. It is an exceptional alternative to a view as the function can support multiple T-SQL statements to build the final result where the view is limited to a single SELECT statement. Also, the ability to pass parameters into a T-SQL select command or a group of them gives us the capability to in essence create a parameterized, non-updateable view of the data in the underlying tables.

Within the create function command you must define the table structure that is being returned. After creating this type of user-defined function, I can use it in the FROM clause of a T-SQL command unlike the behaviour found when using a stored procedure which can also return record sets. 

–Create function for EmpID,FirstName and Salary of Employee
ALTER functionfnGetUpdatedEmployeeSal()
returns @Emp Table
(
EmpID int,
FirstName varchar(50),
Salary int
)
As
begin
Insert @Emp Select e.EmpID,e.FirstName,e.Salary from Employee e;
–Now update salary of first employee
update @Emp set Salary= 30000 where EmpID= 1 OR EmpID= 3;
–It will update only in @Emp table not in Original Employee table
return
end
–Now call the above created function
Select * fromfnGetUpdatedEmployeeSal()
— Note that the salaries for the employee with ID =1 and 3 are changed to 30000.

–Now see the original table. This is not affected by above function update command
Select * fromEmployee

What are the benefits of User-Defined Functions?

The benefits to SQL Server User-Defined functions are numerous. First, we can use these functions in so many different places when compared to the SQL Server stored procedure. The ability for a function to act like a table (for Inline table and Multi-statement table functions) gives developers the ability to break out complex logic into shorter and shorter code blocks. This will generally give the additional benefit of making the code less complex and easier to write and maintain. In the case of a Scalar User-Defined Function, the ability to use this function anywhere you can use a scalar of the same data type is also a very powerful thing. Combining these advantages with the ability to pass parameters into these database objects makes the SQL Server User-Defined function a very powerful tool.
TVFs have the additional advantage of being executed once to return a large number of rows (as opposed to scalar functions which must be executed many times to return many values).
One of the problems with scalar functions is that they are executed once for every row in the result set. While this is not a problem for small result sets, it becomes a problem when our queries return a large number of rows. We can use TVFs to solve this problem.

Drawbacks of Functions

The biggest drawback of SQL Server functions is that they may not be automatically inlined. For a scalar function that operates on multiple rows, SQL Server will execute the function once for every row in the result set. This can have a huge performance impact. Fortunately, with TVFs (Table Value Functions), SQL Server will call them only once, regardless of the number of rows in the result set and it’s often possible, with a bit of ingenuity, to rewrite scalar functions into TVFs, and so avoid the row-by-row processing that is inherent with scalar functions. In some cases, it might be necessary to dispense with the TVF altogether, and simply “manually inline” the function logic into the main code. Of course this defeats the purpose of creating a function to encapsulate re-usable logic.
Scalar UDFs are a fairly straightforward feature but there are some drawbacks to them, the biggest one being that, as discussed earlier, SQL Server has no optimization whereby it can compile this function as inline code. Therefore, it will simply call it once for every row to be returned in the result set. Another drawback of scalar UDFs is that we won’t see the true cost of the function when we’re looking at execution plans. This makes it difficult to gauge just how much a UDF is hurting query performance.
The body of a TVF can either contain just a single statement or multiple statements, but the two cases are handled very differently by the optimizer. If the function body contains just a single statement (often referred to as an “inline TVF”), then the optimizer treats it in a similar fashion to a view in that it will “decompose” it and simply reference the underlying objects (there will be no reference to the function in the resulting execution plan). 
However, by contrast, multi-statement TVFs present an optimization problem for SQL Server; it doesn’t know what to do with them. It treats them rather like a table for which it has no available statistics – the optimizer assumes that it the TVF will always return one row. As a result, even a very simple multi-statement TVF can cause severe  performance problems.

Difference between SQL Server Functions and Stored Procedures

Sql Server has Stored procedures and Functions objects. They have their own limitations, advantages and disadvantages. Below is a list of differences between Functions and Stored Procedures in Sql Server.

Functions
Stored Procedures
Function must return a value.
Procedure can return zero or n values.
Functions can have only input parameters for it.
Procedures can have both input and output parameters in it.
Function allows only SELECT statement in it.
Procedure allows SELECT as well as DML(INSERT/UPDATE/DELETE) statement in it.
Function can be embedded in a SELECT statement.
Procedures cannot be utilized in a SELECT statement.
Functions can be used in the SQL statements anywhere in the WHERE/ HAVING/ SELECT section.
Stored Procedures cannot be used in the SQL statements anywhere in the WHERE/ HAVING/ SELECT section.
     Functions that return tables can be treated as another row-set. This can be used in JOINs with other tables.
Procedures cannot be used in a JOINs statement.
     Inline Function can be thought of as views that take parameters and can be used in JOINs and other Rowset operations.
Procedures cannot be used in a JOINs statement.
Try-catch block cannot be used in a Function.
Exception can be handled by try-catch block in a Procedure.
Transactions are not allowed in Functions.
We can handle Transactions in Procedure.
Function should have at least one input parameter.
Stored Procedure may take 0 to n input parameters.
Functions can be called from Procedure.
Procedures cannot be called from Function.