Javascript, API, and Server
Side - Learn my secrets of
success
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: [email protected]; State: CA; Dept: IT
8235 Email: [email protected]; State: TX; Dept: Sales
2234 Email: [email protected]; State: AL; Dept: IT
1671 Email: [email protected]; 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
Top Related