(Presented by New Relic) Too often, developers think of a mobile app as simply code running on the device. A mobile app is much more than that. Every web API used by an app becomes as much a part of the app as the code running on the device. But while mobile developers have control over their code, they don't always have control over the APIs they use. Web APIs and their infrastructure impact app performance and ultimately the user experience.
This presentation covers some of the essential aspects of app performance management when web APIs are present, including:
-HTTP headers are your friend--stop ignoring all they have to tell you
-Control your network connections on the device—don't just leave things to the OS
-Configure all your caches and use them
-Whatever you do, measure early and often
The session includes a customer story from the CTO of Mirego, and demos of New Relic mobile app performance monitoring, where you see how to drill down into specific requests to see performance by response time, throughput, and data transfer size.
18. Declare using HTTP headers.
GET / HTTP/1.1
Host: flipbit.dev
If-Modified-Since: Thu, 10 Oct 2013 20:14:48 GMT
If-None-Match: "a1846ac92492d2347c6235b4d2611184"
HTTP/1.1 200 OK
Date: Thu, 17 Oct 2013 01:42:00 GMT
Last-Modified: Thu, 17 Oct 2013 01:38:57 GMT
ETag: "b79f914dde3ab5e3095372de46591b46"
Expires: Thu, 24 Oct 2013 01:38:57 GMT
Cache-Control: max-age=604800, private
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 42
Connection: keep-alive
19. Server controls the cache.
• ETag describes dynamic content where modification
date are impractical.
• Last-Modified for everything else.
• Cache-Control controls when the client should
revalidate.
• Expires is the easy way to dictate validation.
20. Client validates.
• If-None-Match to match against the object’s ETag in
cache.
• If-Modified to match against last version received.
22. Is it going to be cached on mobile?
GET /recurringvoid.PublicFiles/welcome.json HTTP/1.1
host: s3.amazonaws.com
HTTP/1.1 200 OK
x-amz-id-2: UleVE3wbOPZa2EW+RpWj834yy5OOMLNmi/w+JbnbBN8rhSg1Bw9682c7XuAgmI38
x-amz-request-id: 4ADBB2EBF80F5D46
Date: Thu, 17 Oct 2013 01:42:00 GMT
Last-Modified: Thu, 17 Oct 2013 01:38:57 GMT
ETag: "b79f914dde3ab5e3095372de46591b46"
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 23
Connection: keep-alive
Server: AmazonS3
23. It depends!
• There’s no cache-control or expires header so it’s left
to the client to decide.
• iOS most likely will cache between 6 hours and 1 day
and will always revalidate.
• Android it depends...
24. Don’t let the client decide. Specify!
PUT /bucket/flipbit.json HTTP/1.1
Host: s3.amazonaws.com
x-amz-meta-Cache-Control : max-age=604800, public
[...]
x-amz-meta-Cache-Control : max-age=<value in seconds>,
<public | private>,
<no-chache / no-store no-transform>,
<must-revalidate>
26. Rails is just an example.
• Ruby on Rails is easy and widespread.
• Setting it up on AWS Elastic Beanstalk is easy.
• There’s a free tier to test out and play with and it
grows if you like it.
• https://github.com/p-l/flipbit as my example code.
30. Trying to fix it:
class FlipsController < ApplicationController
# ...
def index
# ...
# Specify Last-Modified and ETag
flipbit_etag = Digest::MD5.digest(@flipbit.to_s).to_s
fresh_when last_modified: DateTime.now, etag: flipbit_etag
# Specify Cache-Control header
expires_in 3.days, public: true, must_revalidate: false
# ...
end
31. Now, will it be cached?
HTTP/1.1 200 OK
Cache-Control: max-age=86400, public
Content-Type: application/json; charset=utf-8
ETag: "7d4230001179d5852b567c238dbb8eb3"
Server: nginx/1.2.3 + Phusion Passenger 3.0.17 (mod_rails/mod_rack)
Set-Cookie: request_method=GET; path=/
Status: 200
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
X-Request-Id: 870dd748-ba39-4ea6-afc0-6d14c4ac36ed
X-Runtime: 0.005363
X-UA-Compatible: chrome=1
X-XSS-Protection: 1; mode=block
Content-Length: 144
32. It depends!
• There’s no cache-control or expires header so it’s left
to the client to decide.
• iOS will likely cache between 6 hours and 1 day and
will always revalidate.
• Android it depends...
37. iOS is just an example.
• iOS is widespread.
• Setting up a Mac with XCode is easy.
• There’s a couple of ways to do it. But they mostly
depend on the same base API.
38. Make sure your cache is big enough.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUInteger mb = 1024*1024;
// Configure NSURLCache with larget storage
[NSURLCache setSharedURLCache:
[[NSURLCache alloc] initWithMemoryCapacity:(50*mb)
diskCapacity:(100*mb)
diskPath:nil]
];
// ...
// ...
return YES;
}
39. iOS caching policies.
NSMutableURLRequest* getRequest = [NSMutableURLRequest requestWithURL:getURL];
[getRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy];
/*
Constant
Meaning
------------------------------------------------------------------------------UseProtocolCachePolicy
Default behavior. Respect what the server says.
ReloadIgnoringLocalCacheData
Don't use the cache at all.
ReturnCacheDataElseLoad
Use the cache no matter how much it’s out of
date. If there’s no cached response exists then
load from the network.
ReturnCacheDataDontLoad
Offline mode. Use the cache and never load from
the network.
*/
41. Yes.
• There’s no cache-control or expires header so it’s left
to the client to decide.
• iOS will likely cache between 6 hours and 1 day and
will always revalidate.
• Android it depends...
42. Do more with less network requests.
No need. I’ve got this
cached already