Javascript, API, and Server Side - Learn my secrets...

Post on 20-May-2020

78 views 0 download

Transcript of Javascript, API, and Server Side - Learn my secrets...

Javascript, API, and Server

Side - Learn my secrets of

success

JAVASCRIPT

Chander Dhall

Twitter @csdhall

Me@ChanderDhall.com

JAVASCRIPT

About me• Microsoft MVP

• Asp.NET Insider

• Web API Advisor

• Lynda.com Author (LinkedIn Learning)

• Founder – MVPMIX.com

• CTO – Cazton.com

• Principal – Chander Dhall, Inc.

JAVASCRIPT

Questions

• Do you really need a Single Page App?

• Which is the best framework for your

company?

• What’s a futuristic strategy for Javascript?

• How does my company qualify for FREE one-

hour consulting?

BACKEND

JAVASCRIPT

Why?

• Amazon claim – Just an extra 1/10th of

a second on their response times will

cost them 1% in sales.

• Google – ½ a second increase in

latency caused traffic to drop by a

fifth.

JAVASCRIPT

Step 1 Appserver & DBServer

Database ServerApp Server

JAVASCRIPT

Awesome Solution?

Load BalancerLoad

Balancer

DB

DB

DB

DB Cluster

Has

h Ma

p

DB

DB

DB

DB Cluster

Load BalancerLoad

Balancer

DB

DB

DB

DB Cluster

Has

h Ma

p

DB

DB

DB

DB Cluster

Set 1-10 Million Users Set 11-20 Million Users

Global Redirector

Global

Look up Hash

Map

JAVASCRIPT

May be close to an awesome solution?Load

BalancerLoad

Balancer

DB

DB

DB

DB Cluster

Hash

Map

DB

DB

DB

DB Cluster

Master

Slave Slave

SANNo Sql

Master

Slave Slave

Search Db

CachingOffline

Processing

JAVASCRIPT

Agenda

• Why is it important to scale?

• Creating a scalable solution (in incremental steps)

– Propose an Architecture

– Identify Failures and Bottlenecks

– Identify Downtime

– Apply a better solution

– Repeat until we solve (in 10 steps)

– Then some bonus stuff (a better solution)

JAVASCRIPT

Unfortunate Solution

Load Balancer

S SSSS Services

JAVASCRIPT

Gilbert and Lynch white paper

A{

“name” : ”Chander”,

“gender” : ”m”

}

B{

“name” : ”Chander”,

“gender” : ”m”

}Write

Algorithm

Read

Algorithm

Network 2Network 1

JAVASCRIPT

Happy path scenario

A{

“name” : ”Dhall”,

“gender” : ”m”

}

B

Write

Algorithm

Read

Algorithm

Network 2Network 1

{

“name” : ”Chander”,

“gender” : ”m”

}

Update

Message

JAVASCRIPT

Happy path scenario

A{

“name” : ”Dhall”,

“gender” : ”m”

}

B

Write

Algorithm

Read

Algorithm

Network 2Network 1

{

“name” : ”Dhall”,

“gender” : ”m”

}

JAVASCRIPT

Network partitions

A{

“name” : ”Dhall”,

“gender” : ”m”

}

B

Write

Algorithm

Read

Algorithm

Network 2Network 1

Update

Message

{

“name” : ”Chander”,

“gender” : ”m”

}

JAVASCRIPT

CAP Theorem

Consistency Availability

Partitioning

JAVASCRIPT

Brewer’s CAP Theorem

• Consistency (or more appropriately Atomic)

• Availability

• Partition Tolerance

– “No set of failures less than total network

failure is allowed to cause the system to

respond incorrectly” – Gilbert & Lynch

JAVASCRIPT

Just FYI

• Consistency

(in CAP theorem)

• Atomicity

(in ACID)

• Consistency(in ACID)

● Means any transaction will bring the

database from one valid state to

another.

JAVASCRIPT

Fallacies of Distributed Computing

• Network is reliable.

• Latency is zero.

• Bandwidth is infinite.

• Network is secure.

• Topology doesn’t change.

• There is one administrator.

JAVASCRIPT

Fallacies of Distributed

Computing

• Transport cost is zero.

• Network is homogenous.

JAVASCRIPT

The Variables• Scalability - Number of users / sessions /

transactions / operations the entire system can handle

• Performance – Optimal utilization of resources

• Responsiveness – Time taken per operation

• Availability – Probability of the application being

available at any given point in time

• Downtime Impact - The impact of a

downtime of a server/service/resource - number of

users, type of impact etc

JAVASCRIPT

Major Factors• Platform selection

• Hardware

• Application Design

• Database/Datastore Structure and Architecture

• Caching strategy

• Asynchronous processing

• Deployment Process and Architecture

• Monitoring mechanisms

• … and more

JAVASCRIPT

23

Step 1

Appserver &

DBServer

Database ServerApp Server

JAVASCRIPT

Step 2 – Vertical Scaling Appserver &

DBServer

Database ServerApp Server

Throw more RAM and CPU ☺

JAVASCRIPT

Step 3 – Vertical Partitioning (Services)

• Introduction– Deploying each service on a separate node

• Advantages– Increases Availability (per app)

– Easy to tune and optimize

– Reduces context switching

– Simple to implement

App Server

Db Server

JAVASCRIPT

Step 4 – Horizontal ScalingLoad Balancer

DB Server

JAVASCRIPT

Sticky Sessions

• Subsequent requests from a user are sent to the original server

• Asymmetrical load distribution

• Downtime Impact – Loss of session data

Load Balancer

User 1

JAVASCRIPT

Central Session Store

• Session store is a single point of failure

• Session reads and writes generate Disk + Network I/O

Load Balancer

Session Store

A

p

p

S

E

R

V

E

R

JAVASCRIPT

Clustered Session Management

–No Single point of failure

–Session reads are instantaneous

–Session writes generate Network I/O

–Increase in number of nodes

increases Network I/O exponentially

–What happens when?

• User request arrives before intra-node communication finished

• Intra-node communication fails

Clustered Session

ManagementLoad Balancer

JAVASCRIPT

Load Balanced App Server Cluster

Active-Active assumes that each LB is independently able to take up the load of the other Load Balancer

Users

Load Balancer

JAVASCRIPT

Step 5 – Vertical Partitioning (Hardware)

Load Balancer Load Balancer

DB Server SAN

JAVASCRIPT

Step 5 – Vertical Partitioning (Hardware)• Advantages

▪ Allows “Scaling Up” the DB Server

▪ Boosts Performance of DB Server

• Disadvantages

▪ Increases Cost

JAVASCRIPT

Step 6 – Horizontal Scaling (DB)

• Introduction▪ Increasing the number of DB nodes

▪ Referred to as “Scaling out” the DB Server

• Options

▪ Shared nothing Cluster

▪ Real Application Cluster (or Shared Storage Cluster)

JAVASCRIPT

Step 6 – Horizontal Scaling (DB)

Load Balancer Load Balancer

DB Server SAN

JAVASCRIPT

Step 6 – Horizontal Scaling (DB)Load Balancer Load Balancer

DB ServerSAN

DB Server DB Server

DB Replica

JAVASCRIPT

Step 7 – Vertical / Horizontal Partitioning (DB)

• Introduction▪ Increasing the number of DB Clusters by dividing the data

• Options

▪ Vertical Partitioning - Dividing tables / columns

▪ Horizontal Partitioning - Dividing by rows (value)

JAVASCRIPT

Step 7 – Vertical / Horizontal Partitioning (DB)

Load Balancer Load Balancer

DB ServerSAN

DB Server DB Server

DB Cluster

JAVASCRIPT

Step 7 – Vertical / Horizontal Partitioning (DB)

App Cluster

Db Cluster 1 Db Cluster 2

Twitter Table

Facebook Table

Users Table

Products Table

Vertical Partitioning

JAVASCRIPT

Step 7 – Vertical / Horizontal Partitioning (DB)

App Cluster

Db Cluster 1 Db Cluster 2

Twitter Table

Facebook Table

Twitter Table

Facebook Table

Horizontal Partitioning

1st Million Users 2nd Million Users

JAVASCRIPT

Step 7 – Vertical / Horizontal Partitioning (DB)

Load Balancer Load Balancer

DB

DB Cluster

DB DB DB DB DB

DB Cluster

Hash

Map

SAN

JAVASCRIPT

Step 8 – Separating Sets

Load Balancer Load Balancer

DB DB DB

DB Cluster

Hash

Map

DB DB DB

DB Cluster

Load Balancer Load Balancer

DB DB DB

DB Cluster

Hash

Map

DB DB DB

DB Cluster

Set 1-10 Million Users Set 11-20 Million Users

Global Redirector

Global

Look up

Hash Map

JAVASCRIPT

Step 9 – Caching• Add caches within App Server

▪ Object Cache

▪ Session Cache

▪ API cache

▪ Page cache

• Software

▪ Memcached

▪ Redis

▪ Azure Cache (App Fabric)

JAVASCRIPT

Step 10 – HTTP Accelerator• A good HTTP Accelerator / Reverse proxy performs the following –

▪ Redirect static content requests to a lighter HTTP server (lighttpd)

▪ Cache content based on rules

▪ Use Async Non blocking IO

▪ Maintain a limited pool of Keep-alive connections to the App Server

▪ Intelligent load balancing

• Solutions

▪ Nginx (HTTP / IMAP)

▪ Perlbal

▪ Hardware accelerators plus LBs

JAVASCRIPT

More Important Stuff• CDNs

• IP Anycasting

• Async Nonblocking IO (for all Network Servers)

• If possible - Async Nonblocking IO for disk

• Incorporate multi-layer caching strategy where required

▪ L1 cache – in-process with App Server

▪ L2 cache – across network boundary

▪ L3 cache – on disk

• Grid computing

JAVASCRIPT

NoSql Vs Relational

Depth of Functionality Sc

ala

bili

ty a

nd

Pe

rfo

rma

nc

e

JAVASCRIPT

NoSql vs Relational

• No Joins

– Do you need them though?

• Transactions

– RDBMS great for concurrency, integrity or

data type validity.

JAVASCRIPT

Relational -> NoSql

• Ever increasing users. Scalability needs.

• Highly structured data to structured, semi-

structured and unstructured data.

• Advent of high speed data networking.

• Distributed computing.

• Cheap and plenty memory.

JAVASCRIPT

Relational -> NoSql

http://www.couchbase.com/why-nosql/nosql-database

JAVASCRIPT

Scaling RDBMS

• RDBMS sharding

– Highly disruptive to re-shard.

– Lose benefits of relational model.

– Create and maintain schema on every

server.

JAVASCRIPT

Scaling RDBMS

• Denormalizing

– Why use a RDBMS? ☺

JAVASCRIPT

Relational -> NoSql

• Schemaless.

• Auto-sharding.

• Distributed querying.

• Integrated caching.

JAVASCRIPT

No SQL Types• Key Value

• Ordered key value

• Wide Column Store

• Document Store/Full Text Search

• Graph DBs

• Object DBs

JAVASCRIPT

Key-Value Store

• Pros

– Simple. Programmer friendly.

– Powerful. Fast.

• Cons

– Key range support not good.

– Aggregation support lacking.

Value Key

Value Key

Value Key

Value Key

Value Key

JAVASCRIPT

Ordered Key-Value Store

• Pros

– Processes key ranges.

– More powerful.

• Cons

– No framework for value modeling.

Value Key

Value Key

Value Key

Value Key

Value Key

JAVASCRIPT

Big Table

• Pros

– Model values as maps of maps

of maps.

• Cons

– Not appropriate for schemes

arbitrary complexity.

Value Key

Value Key

Value Key

Value Key

Value Key

JAVASCRIPT

Big Table

• Pros

– Model values as maps of maps

of maps.

• Cons

– Not appropriate for schemes

arbitrary complexity.

JAVASCRIPT

Big table

Key

Column

family

Key

Column

family

JAVASCRIPT

Document/Full-Text

• Pros

– Collection of documents which contain key-

value collections.

– Natural data modeling.

– Programmer friendly.

– Web based. Mostly REST/Json friendly.

JAVASCRIPT

Document/Full text search

databases

Key Val

Key Val

Key Val

“Person”: {

“name”: “Chander Dhall”,

“address”: {

“city”:”los angeles”,

“state”: “CA”,

“zip”: “90069”

}

}

JAVASCRIPT

Graph databasesKey

Key

Key

Key

JAVASCRIPT

Step 12- Finalizing

Load Balancer Load Balancer

DB DB DB

DB Cluster

Hash

Map

DB DB DB

DB Cluster

Master

Slave Slave

SANNo Sql

Master

Slave Slave

Search Db

CachingOffline

Processing

JAVASCRIPT

NoSql Paradigm - Atomic Aggregates

Account

Id

Account No.

Checking

Id

Min bal

Savings

Id

Interest rate

Account

{

“Type”: “Checking”,

“Id”: “chk123”,

“Min Bal”:”10000”,

}

Account

{

“Type”: “Savings”,

“Id”: “sav123”,

“Interest Rate”:”5%”,

}

JAVASCRIPT

No sql paradigm – Index tableEmploye

e Id

Details

1234 Email: a@a.com; State: CA; Dept: IT

8235 Email: b@b.com; State: TX; Dept: Sales

2234 Email: c@c.com; State: AL; Dept: IT

1671 Email: c@d.com; State: WA; Dept:

Sales

State Employee Id

CA 1234, 1235, 1236, 1244

TX 8000, 8100, 8235, 8266

AL 2212, 2221, 2234, 2256

Dept Employee Id

IT 1234, 1235, 1236, 1244

Sales 8000, 8100, 8235, 8266

Acc 2212, 2221, 2234, 2256

JAVASCRIPT

No sql paradigm – Tree IndexCountry - USA

State - CA

City - LA

Properties

Facilities

{

“property”:

[{ “facilityName”: abc”,

“facilityId”:”111”},

{“facilityName”:”xyz” ,

“facilityId”:”222”}]

}

JAVASCRIPT

Composite Key

Dept= IT:* or

Dept= Sales:Online:*

IT: Software: 1123 EmpName: John; Address: Los Angeles

IT: Software: 2323 EmpName: Kevin; Address: Dallas, TX

IT: Hardware: 6767 EmpName: Matt; Address: San Francisco

Sales: Online: 832 EmpName: Katie: Address: Austin, Tx

Sales : Online: 423 EmpName: Karen: Address: Irvine, CA

Sales : Store : 556 EmpName: Richard; Address: San Diego

IT

Employees

Sales

Employee

s

E

M

P

L

O

Y

E

E

S

JAVASCRIPT

No sql paradigm - Grouping

U123: O111 Product Ids: [“Surface”, “xbox”]

U124:O123 Product Ids: [“Win 8”, “xbox”]

U124:O234 Product Ids: [“Win phone”, “surface”]

U124:O999 Product Ids: [“office”, “azure sub”]

U125:O789 Product Ids: [“msdn”, “office”]

U125:O945 Product Ids: [“surface”, “xbox”]

Colocation of a users’ data.

JAVASCRIPT

Inverted search & direct aggregation

EmpId, dept, city, …….

Dept-IT: [111, 123, 234….]

Dept-Sales:[673, 343, 434….]

City: Dallas

City: LA

111: Dept-Sales, City: LA …

222: Dept-IT, City: Dallas ….

JAVASCRIPT

No sql paradigm – Materialized paths

Electronics

TV Phones Computers Cameras

Samsung Apple LG

LCD LED

JAVASCRIPT

No sql paradigm – Materialized paths

TV

Samsung Apple LG

LCD LED

{ “entity”: “TV”, “category”:”Electronics”}

{ “entity”: “Samsung”, “category”:”Electronics, TV”}

{ “entity”: “Samsung”, “category”:”Electronics, TV, LCD”}

JAVASCRIPT

No sql paradigm – Nested sets

Electronics

TV Phones

Samsung Sony Cell Landline1 2 3 4 5 6 7 8 9 10 11 12 13 14

JAVASCRIPT

No sql paradigm – Nested sets

1 2 3 4 5 6 7 8 9 10 11 12 13 14

Sony Samsung

TV

LandlineCell

Phone

Electronics

JAVASCRIPT

Flattening nested documents

Name: Chander

Hadoop: Expert

Nodejs: Expert

Spanish: Novice

{

“name”:”chander”,

“skills”:”hadoop, nodejs, Spanish”,

“level”:”expert, expert, novice”

}

Skills:hadoop AND

level:expert

JAVASCRIPT

Flattening nested documents

Name: Chander

Hadoop: Expert

Nodejs: Expert

Spanish: Novice

{

“name”:”chander”,

“skills_1”:”hadoop”,

“skills_2”: “nodejs”,

“skills_3”: “spanish”,

“level_1”:”expert”,

“level_2”: “expert”,

“level_3”: “novice”

}

JAVASCRIPT

References • http://www.couchbase.com/why-

nosql/nosql-database

• Highly scalable blog.

• www.10gen.com

• http://couchdb.apache.org/

• www.ravendb.net

JAVASCRIPT

References • http://redis.io/

• http://neo4j.org/

• http://Cassandra.apache.org

• http://elasticsearch.org

• http://memcached.org/

• Building Scalable Architecture

WEB API

SESSION TITLE

http://ChanderDhall.com/gettrainings

GET

http://ChanderDhall.com/trainings

Principle: Use HTTP

verbs 77

Nouns, No Verbs in the URL

SESSION TITLE

What about?• Responses that don’t involve

resources

• Use verbs

• Example:

http://ChanderDhall.com/transla

te?from=en&to=gn

SESSION TITLE

http://ChanderDhall.com/trainings

http://ChanderDhall.com/trainings/34

Principle: 2 base

URLs/resource

79

KISS (Keep it simple, stupid!)

SESSION TITLE

GET

http://ChanderDhall.com/trainings

Retrieves all trainings

GET http://ChanderDhall.com/trainings/23

Retrieves trainings with Id = 23

80

GET

SESSION TITLE

• HTTP Verbs

POST

http://ChanderDhall.com/trainings

Creates a new training(Strange?)

POST

http://ChanderDhall.com/trainings/23

Error – Why, so?

81

POST

SESSION TITLE

• HTTP Verbs

PUT

http://ChanderDhall.com/trainings

Bulk update trainings

PUT

http://ChanderDhall.com/trainings/23

If exists, update 23

Else ERROR

82

PUT

SESSION TITLE

• HTTP Verbs

DELETE

http://ChanderDhall.com/trainings

Delete all trainings

DELETE

http://ChanderDhall.com/trainings/23

If exists, Delete 23

Else Resource Not found Error

83

DELETE

SESSION TITLE

Associations

GET

/trainers/12/trainings/

144

84

SESSION TITLE

GET

/trainers/12/trainings?

zip=92618&tech=api

85

COMPLEXITY

SESSION TITLE

Error Format

• Error format 1

{

“code" : "401",

"message“ : "Authenticate",

}

86

SESSION TITLE

Error Format

• Error format 2

{

“type" : “OAuthException",

"message“ : “(#401: Request not authorized",

}

87

SESSION TITLE

Error Format

• Error format 3

{

"status" : "401",

"message“ : "Authenticate",

"code“ : 1234,

“details":

"http://www.chanderdhall.com/docs/errors/1234"

}

88

(Recommended!)

SESSION TITLE

Error Format• Google GData 200 201 304 400

401 403 404 409 410 500

• Netflix 200 201 304 400 401 403

404 412 500

• Digg 200 400 401 403 404 410

500 503

SESSION TITLE

Errors

• Only 3 cases

• Everything worked

• Client did something wrong

• API did something wrong

90

SESSION TITLE

Error Codes (Required)

• So minimum response codes

• 200 - OK

• 400 - Bad Request

• 500 - Internal Server Error

91

SESSION TITLE

Error Codes (Extended)

• 201 - Created

• 304 - Not Modified

• 404 – Not Found

• 401 - Unauthorized

• 403 - Forbidden

92

SESSION TITLE

Versioning

• /bankName/v2.0/accounts/checking

• /2013-09-10/bankName/accounts/checkingThis

• /bankName/accounts/checking?v=1

93

SESSION TITLE

Versioning

• Timestamp: Is the version based on the

date of launch or date of creation?

• Version in URL: Interface appears to

change sooner that it actually might.

• Version is optional: (Red Flag)

94

SESSION TITLE

Versioning

• Versioning is mandatory

• Make version the first field if you want

from the left (v1/trainings)

• How many versions to maintain?

• URLs or Headers?

95

SESSION TITLE

Versioning

• Accept-Datetime: Thu, 1 Oct 2013

20:35:00 GMT

• Cookie: $Version=1; Skin=new;

• ETag:

"737060cd8c284d8af7ad3082f209582d"

96

SESSION TITLE

Pagination

• http://chanderdhall.com/podcasts/pag

e=3&rpp=5

• http://chanderdhall.com/podcasts?start

=3&count=5

97

SESSION TITLE

Pagination

• http://chanderdhall.com/podcasts?offse

t=3&limit=5

• Don’t forget to include Default

Pagination

98

SESSION TITLE

Multiple Formats

• http://chanderdhall.com/podcasts?type=json

Or

http://chanderdhall.com/podcasts?type=xml

• http://chanderdhall.com/podcasts.json

Or http://chanderdhall.com/podcasts.xml

99

SESSION TITLE

• http://chanderdhall.com/podcasts

accept: application/json

Multiple Formats

100

SESSION TITLE

Responses

a. "Created_At": "2013-10-10T04:35:00Z"

b. "DateTime": "2013-10-10T04:35:00Z"

101

SESSION TITLE

Responses

var podcast = JSON.parse(response);

podcast.createdAt

102

SESSION TITLE

P

I

P

E

L

I

N

E

W

E

B

A

P

I

ASP.NET Hosting Self Hosting HttpControllerHandler

HttpServer HttpSelfHostServer

DelegatingHandler

HttpRoutingDispatcher

HttpControllerDispatcher

HttpRequestMessage HttpResponse

zMessage

If(Route.Handler) Yes Route.Handler

DelegatingHandler

HttpMessageHandler

No

1. Create API Controller

Message Handlers

SESSION TITLE

W

E

B

A

P

I

Action Filters

2. Select Controller ActionController

Can create an error response if request is not authorized3. Model Binding

Authorization Filters

Action filters are invoked

twice

4. Result Conversion

5. Invoke Action

OnActionExecuting OnActionExecuted

Controller Action

Exception Filters

P

I

P

E

L

I

N

E

SESSION TITLE3. Model Binding

HttpRequestMessage

URI Headers Body

IModelBinder

ModelBinderParameterBinding

IValueProvider

Simple Type Any Type

HttpParameterBinding

Complex Type

MediaTypeFormatter

FormatterParameterBinding

SESSION TITLE

4. Result Conversion

HttpResponseMessage

void

If(returnType== void)

return (204)

HttpResponseMessage

If(returnType == HttpResponseMessage)

Pass through

Other Types

IContentNegotiator

MediaTypeFormatter

SESSION TITLE

Enable Cross Origin Requestspublic static class WebApiConfig

{

public static void Register(HttpConfiguration config)

{

var cors = new

EnableCorsAttribute("www.example.com", "*", “*");

config.EnableCors(cors);

// ...

}

}

Behind the scenes

Access-Control-Allow-Origin: http://www.example.com

Access-Control-Allow-Headers: x-my-custom-header

Access-Control-Allow-Methods: PUT

SESSION TITLE

Enable CORS (Custom)public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider {

private CorsPolicy _policy;

public MyCorsPolicyAttribute(){

// Create a CORS policy._policy = new CorsPolicy{

AllowAnyMethod = true,AllowAnyHeader = true

};

// Add allowed origins._policy.Origins.Add("http://myclient.azurewebsites.net");_policy.Origins.Add("http://www.contoso.com");

}

public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request){

return Task.FromResult(_policy);}

}

SESSION TITLE

Attribute Routing

[RoutePrefix("api/books")]

public class BooksController : ApiController

{

// GET api/books

[Route("")]

public IEnumerable<Book> Get() { ... }

// GET api/books/5

[Route("{id:int}")]

public Book Get(int id) { ... }

// POST api/books

[Route("")]

public HttpResponseMessage Post(Book book) { ... }

}

SESSION TITLE

Attribute Routing

[RoutePrefix("api/books")]

public class BooksController : ApiController

{

// GET /api/authors/1/books

[Route("~/api/authors/{authorId:int}/books")]

public IEnumerable<Book> GetByAuthor(int authorId) {

... }

// ...

}

‘~’ Overrides the RoutePrefix

SESSION TITLE

Attribute Routing

[RoutePrefix("customers/{customerId}")]

public class OrdersController : ApiController

{

// GET customers/1/orders

[Route("orders")]

public IEnumerable<Order> Get(int customerId) { ... }

}

SESSION TITLE

Attribute Routing

[Route("users/{id:int}"]

public User GetUserById(int id) { ... }

[Route("users/{name}"]

public User GetUserByName(string name) { ... }

First route chosen if the id is an int.

Otherwise, second.

SESSION TITLEConstraint Description Example

alphaMatches uppercase or lowercase Latin

alphabet characters (a-z, A-Z){x:alpha}

bool Matches a Boolean value. {x:bool}

datetime Matches a DateTime value. {x:datetime}

decimal Matches a decimal value. {x:decimal}

double Matches a 64-bit floating-point value. {x:double}

float Matches a 32-bit floating-point value. {x:float}

guid Matches a GUID value. {x:guid}

int Matches a 32-bit integer value. {x:int}

lengthMatches a string with the specified length or

within a specified range of lengths.

{x:length(6)}

{x:length(1,20)}

long Matches a 64-bit integer value. {x:long}

max Matches an integer with a maximum value. {x:max(10)}

maxlength Matches a string with a maximum length. {x:maxlength(10)}

min Matches an integer with a minimum value. {x:min(10)}

minlength Matches a string with a minimum length. {x:minlength(10)}

range Matches an integer within a range of values. {x:range(10,50)}

regex Matches a regular expression. {x:(^\d{3}-\d{3}-\d{4}$)}

SESSION TITLE

Attribute Routing

[Route("users/{id:int:min(1), id:int:max(10)}")]

public User GetUserById(int id) { ... }

Multiple constraints can be applied separated

by a comma

UI

CAZTON

Javascript Tips• Array items and object members are accessed slower than

Literal values and local variables.

• Local variables are faster to access

(Eg: location.href is accessed faster than window.location.href)

• Avoid the with statement because it augments the execution

context scope chain.

• Avoid nested object members.

• Prototype (Inheritance chain) slows down method or property

access.

• Storing frequently used object members, array items, and out-

of-scope variables in local variables.

CAZTON

Our Top clients strive to achieve

Response Time - 250ms

CAZTON

Intentional Speed Delay

Source: FT.com

CAZTON

Impact

Source: FT.com

Mean Percentage Drop in Article Views

CAZTON

Impact

Source: FT.com

Mean Percentage Drop in Article Views

CAZTON

1 second 2 second 3 second 4 second

Performance vs Perception

CAZTON

1 second 2 second 3 second 4 second

Performance vs Perception

CAZTON

1 second 2 second 3 second

Performance vs Perception

CAZTON

1 second 2 second 3 second

Performance vs Perception

3.2 second

CAZTON

14 Rules of Web Performance

• Make Fewer HTTP Requests

• Use a Content Delivery Network

• Add an Expires Header

• Gzip Components

• Put Stylesheets at the Top

• Put Scripts at the Bottom

• Avoid CSS Expressions

Source: Steve SoudersBook: High Performance Web Sites

CAZTON

14 Rules of Web Performance

• Make JavaScript and CSS External

• Reduce DNS Lookups

• Minify JavaScript

• Avoid Redirects

• Remove Duplicate Scripts

• Configure ETags

• Make AJAX Cacheable

CAZTON

Time to reach the cwnd size of size N

Rwnd = 128KB

RTT = 42ms (San Francisco to New York)

128KB/1460B = 90 segments

log2(90/10) = 3.1699250014423126

So Time = 42ms * 3.169 = 160ms

Time to reach Receive Windows Limit

CAZTON

SYN

SYN ACK

ACK

Request

Processing

14600 bytes

10x ACK

29200 bytes

20x ACK

58400 bytes

21ms

42 ms

92 ms

113 ms

134 ms

155 ms

176 ms

40x ACK197 ms

29200 bytes218 ms

20x ACK

Cnwd: 116800 bytes239 ms

CAZTON

Optimizing TCP• Upgrade server kernel to latest version

• Increase Initial cwnd size

• Enable window scaling (Increases Rwnd size. Previous Limit

65,535 bytes. Current limit -1 gigabyte)

• Disable slow-start after idle

• Investigate enabling TCP Fast Open

• Eliminate redundant data transfers

• Compress transferred data

• Reduce roundtrip times

• Reuse TCP connections whenever possible

CAZTON

Fetching using 3G/4G

• Control Plane (3G) up to 2.5 seconds

CAZTON

Tips

• Reduce DNS lookups

• Avoid Redirects (Bad: example.com to m.example.com)

• Make Fewer HTTP Requests

• Gzip your text

• Use a CDN

• Optimize images per device

CAZTON

Tips

• Add ETags to avoid fetching duplicate

content

• Test on actual mobile devices

• Add an Expires Header

• Use Local Storage for js and css

CAZTON

Battery

Most energy intensive components

1. Screen

2. Radio

CAZTON

How to Save Battery

• Prefetch Data

• Minimize periodic data requests

CAZTON

HTTP 2

• New Binary Framing

• Interleaving requests and response messages

• Parallel Requests

• Header Compression

• Server Push

• Stream Prioritization (Weight and dependency)

CAZTON

Critical Rendering Path

• Time taken to get to the first render of the page

CAZTON

Critical Rendering PathNetwork

HTML CSS

DOM CSSOMJavascrip

t

Render Tree

Layout

Paint

CAZTON

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>NDC Web Performance</title>

<link rel="stylesheet" type="text/css" href="sample.css">

</head>

<body>

<div>Hello World</div>

<p style="display:none">

Hidden

</p>

</body>

</html>

Network

HTML

DOM

CAZTON

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>NDC Web Performance</title>

<link rel="stylesheet" type="text/css" href="sample.css">

</head>

<body>

<div>Hello World</div>

<p style="display:none">

Hidden

</p>

</body>

</html>

Network

HTML

DOM

CAZTON

body

div p

Hello World Hidden

CAZTON

#

Network

HTML CSS

DOM CSSOM

Render

Tree

CAZTON

body

div p

Hello World Hidden

body

div

Hello World

Hello World

DOM Tree + CSSOM Render Tree

display: none

=

font-size:medium

CAZTON

Tips

• Stream HTML

– Server Side Rendered HTML

– Progressive Rendering

• Get Critical CSS Inline

– Remember CSS blocks rendering

CAZTON

Critical Rendering PathNetwork

HTML CSS

DOMCSS Object

ModelJavascript

Render Tree

Layout

Paint

CAZTON

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>NDC Web Performance</title>

<script src="analytics.js" async></script>

<script src="sayhi.js" ></script>

<link rel="stylesheet" type="text/css" href="sample.css">

</head>

<body>

<div>Hello World</div>

<p style="display:none">

Lorem ipsum dolor sit amet

</p>

</body>

</html>#

Block parse and

execute

Execute when

ready

CAZTON

Older Browsers• External Scripts

(Blocks Download plus rendering)

– Download -> Parse -> Execute

External Script 1

External Script 2

CSS

Image

CAZTON

Improvements

• External Scripts (Blocks Download plus

rendering)

– Parallel

Download

– Parse

– Execute

External Script 1

External Script 2

CSS

ImageExternal Script 2

CAZTON

Gmail Mobile

<script type=‘text/javascript’>

/*

js code

*/

</script>

get script DOM element’s text

remove comments

eval() when invoked

Source: Steve Souders

CAZTON

Javascript Tips

• JS can block CSS

• JS can block DOM

• Use async

• Avoid document.write()

• Defer all, but critical, scripts towards the end of the

body tag

CAZTON

Critical Rendering PathNetwork

HTML CSS

DOMCSS Object

ModelJavascript

Render Tree

Layout

Paint

CAZTON

Performance (60fps)

60 frames = 1000ms

1 frame = 1000/60 = 16.67ms

(If it exceeds 16ms, frame is dropped)Frame

Code GC Layout Paint

CAZTON

Layout Update• Resizing

• Adding Nodes

• Removing Nodes

• Changing Styles

CAZTON

Lazy vs Synchronous Update

Frame

Code GC Layout Paint

Frame

Paint

Lazy – Recalculated once before paint Synchronous – Forced multiple times before paint

for(e in elements){e.style.left = e.offsetLeft + 1 + “px”;

}

CAZTON

Layout To Paint

• Apply visual styles

• Create the bitmap

• Pixelate the screen

Things to note

• Update the minimum area needed

• Note: Some styles are more expensive

CAZTON

Layout

var element = document.getElementById(’book');

element.style.borderLeft = '1px'; //Reflow

element.style.borderRight = ’1px'; //Reflow

element.style.padding = '5px'; //Reflow

CAZTON

Layout

var element = document.getElementById(‘book');

element.style.cssText += 'border-left: 1px; border-right: 1px; padding: 5px;';

CAZTON

Inefficient

myElement.style.left = 1 + myElement.offsetLeft + 'px';

myElement.style.top = 1 + myElement.offsetTop + 'px'; if

(myElement.offsetLeft >= 500) {

doSomething();

}

CAZTON

Efficient

var offsetLeft = myElement.offsetLeft ;

myElement.style.left = 1 + offsetLeft + 'px';

myElement.style.top = 1 + myElement.offsetTop + 'px';

if (offsetLeft >= 500) {

doSomething();

}

CAZTON

Paint• Most expensive part of the pixel pipeline

• Changing any property (except transforms or

opacity) always triggers paint.

• Triggering layout automatically triggers paint.

• Can trigger paint without layout (change

backgrounds, text colors, shadows)

• Tip: Reduce paint areas through layer promotion

and orchestration of animations.

CAZTON

Repaint/Reflow

• Repaint –

– Or Redraw

– Invisible Element made visible (or Vice Versa)

– Without altering the layout of the document

• Reflow (More Expensive)

– When DOM tree is manipulated

CAZTON

What causes a Reflow?

• Resizing the window

• Changing a font

• CSS pseudo classes like :hover

• Changing the class attribute

• Calculating offsetWidth and offsetHeight

• Modifying the style attribute of an element

CAZTON

Why is Reflow Expensive?

• All child nodes

• Element ancestors

• Elements following the element have their details

recalculated.

• Effectively the entire page is re-rendered.

CAZTON

Reflowsvar fragment =

document.createDocumentFragment();

var elem, contents;

for(var i = 0; i < textlist.length; i++) {

elem = document.createElement('p');

contents = document.createTextNode(textlist[i]);

elem.appendChild(contents);

fragment.appendChild(elem);

}

document.body.appendChild(fragment);#

DocumentTree Modification

CAZTON

Reducing Reflow Impactvar original = document.getElementById('container');

var cloned = original.cloneNode(true); //EFFICIENT

cloned.setAttribute('width', '50%');

var elem, contents;

for(var i = 0; i < textlist.length; i++) {

elem = document.createElement('p');

contents = document.createTextNode(textlist[i]);

elem.appendChild(contents);

cloned.appendChild(elem);

}

original.parentNode.replaceChild(cloned, original);#

CloningTheOriginal tree

CAZTON

Reducing Reflow Impact

var element= document.getElementById(id');

element.style.display = 'none';

element.appendChild(newNodes);

element.style.className = ’newClass';

element.style.display = 'block';

#

Hide

Change

Unhide

CAZTON

Thought Leaders to Follow• Steve Souders

• Ilya Grigorik

• Paul Irish

• Douglas Crockford (Ajax)

• Ben Gailbraith (Responsive)

• Tony Gentilcore (Gzip and beyond)

• Stoyan Stefanov (Image Optimization)

• Paul Lewis

• Chander Dhall ☺

CAZTON

Books

#

CAZTON

Cache locally

Inefficient

<script type="text/javascript">

for (var

i=0;i<car.images.length;i++)

car.images[i].src=”image.gif"

</script>

Efficient

<script type="text/javascript">

var images=car.images

for (var i=0;i<theimages.length;i++)

images[i].src=”image.gif"

</script>

#

CAZTON

Loops

Inefficient

for (var i=0, len<x.length;; i++) {

doSomething()

}

Efficient

for (var i=0, len=x.length; i<len; i++)

{

doSomething()

}

#

CAZTON

Reduce Inspection TimeInefficient

var all=

document.getElementsByTagName('*');

for(var i = 0; i < all.length; i++) {

if(all[i].hasAttribute(‘x')) {

doSomething();

}

}

Efficient

var all=

document.getElementById(’myId')

.getElementsByTagName('*');

for(var i = 0; i < all.length; i++) {

if(all[i].hasAttribute(x')) {

doSomething();

break;

}

}#

CAZTON

Use XPathInefficient

var allElements =

document.getElementsByTagName('*');

for(var i = 0; i < allElements.length; i++) {

if(allElements[i].tagName.match(/^

h[2-4]$/i)) {

// …

}

}

Efficient

var headings =

document.evaluate('//h2|//h3|//h4',

document, null,

XPathResult.ORDERED_NODE_ITERATOR

_TYPE, null);

var oneheading;

while(oneheading =

headings.iterateNext()) {

// …

}#devconnectionSource: https://dev.opera.com/articles/efficient-javascript/?page=4#docreferencess

CAZTON

Avoid keeping alive references

var remoteDoc = parent.frames['sideframe'].document;

var remoteContainer = remoteDoc.getElementById('content');

var newPara = remoteDoc.createElement('p');

newPara.appendChild(remoteDoc.createTextNode('new content'));

remoteContainer.appendChild(newPara);

// Remove references

remoteDoc = null;

remoteContainer = null;

newPara = null;

#dSource: https://dev.opera.com/articles/efficient-javascript/?page=4#docreferencesevconnections