SlideShare a Scribd company logo
Performance + Optimization 
Thomas Alisi, Solution Architect 
@grudelsud @stinkdigital 
EpicFEL Oct2014, Sadler’s Wells, London 
photo courtesy of https://www.flickr.com/photos/8064990@N08/
Stinkdigital is an interactive production company, 
working with clients and advertising agencies 
worldwide. 
! 
Our services include creative concepting, design 
and high-end execution. We create everything from 
live-action films and websites, through to mobile 
apps and installations. 
See our 2013 showreel
Project Google Title 
+ The Barbican 
BDreavnadrt 
Body A new platform creative text coders goes here. 
from Google and the Barbican that aims to reward and inspire 
everywhere. 
VIEW SITE
Revolutions in Sound 
Red Bull 
We teamed up with Google+ & Red Bull Music Academy to create a living 
archive of UK club culture. 
VIEW SITE 
ABOUT THE TECHNOLOGY
Does this number look familiar to you? 86,400
Does this number look familiar to you? 86,400 
= 60’’ x 60’ x 24h [number of seconds in 1 day]
What about this one? 31,536,000
What about this one? 31,536,000 
= 86,400’’ x 365d [number of seconds in 1 year]
OK, now try and guess the last one 252,000,000
OK, now try and guess the last one 252,000,000 
= 31.5M’’ x 8y [number of seconds in 8 years]
but also… 252,000,000 
= 36M x 7’’ [7 seconds saved for each of the 36M visits 
we had during the first 6 months on DevArt]
How did we do it? 
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
- Grunt, Gulp, Browserify, Webpack… AAARGH! 
! - we like vanilla JS and have been fan of Gulp 
(at least over the past 10 minutes…) 
! - we (I) tend to use a super simple Gulp-Browserify- 
AngularJS boilerplate 
https://github.com/grudelsud/angularjs-gulp-browserify-boilerplate 
! - but there are other good examples too 
e.g. https://github.com/unit9/coffee-bone 
! 
! 
divide et impera
- GAE is not opinionated (which is good) 
! - don’t use Django on GAE unless you really want to 
(e.g. use legacy modules or deploy something really 
quick) 
! - Flask is OK and does not have preferences for a specific 
ORM (which is great) 
! - webapp2 is really super simple (a bit too simple…)
bespoke REST micro-framework 
class Jsonifiable(ndb.Model): 
def from_dict(cls, dict): 
pass 
! 
def to_dict(self, async=False): 
pass 
! 
def resolve_future_blobs(cls, async_blobs): 
pass 
!! 
class JsonRestHandler(webapp2.RequestHandler): 
JSON_MIMETYPE = "application/json" 
! 
def write(self, data): 
self.response.out.write(data) 
! 
extend ndb.Model 
extend webapp2.RequestHandler 
basic permission check (skipped here) 
def send_success(self, obj=None, cache_expiry=None): 
asynchronous conversion 
self.response.headers["Content-Type"] = self.JSON_MIMETYPE 
! 
self.write(json.dumps(obj, cls=JsonifiableEncoder)) 
bespoke encoder
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
this always seems a good way to start
abstraction 
class ClubNight(BaseModel): 
name = ndb.StringProperty() 
content = ContentProperty(ndb.TextProperty) 
blob_key_logo = ContentProperty(ndb.BlobKeyProperty) 
genre = ndb.KeyProperty(kind=’Genre’) 
website = ContentProperty(ndb.StringProperty) 
address = ContentProperty(ndb.TextProperty) 
location = ContentProperty(ndb.GeoPtProperty) 
! 
class Connection(ndb.Model): 
from_key = ndb.KeyProperty() 
to_key = ndb.KeyProperty()
reality 
class ClubNight(BaseModel): 
name = ndb.StringProperty() 
content = ContentProperty(ndb.TextProperty) 
blob_key_logo = ContentProperty(ndb.BlobKeyProperty) 
genre = ndb.KeyProperty(kind=’Genre’) 
website = ContentProperty(ndb.StringProperty) 
address = ContentProperty(ndb.TextProperty) 
location = ContentProperty(ndb.GeoPtProperty) 
! 
class Connection(ndb.Model): 
from_key = ndb.KeyProperty() 
to_key = ndb.KeyProperty() 
to_name = ndb.StringProperty() 
to_kind = ndb.StringProperty() 
to_slug = ndb.StringProperty() 
to_genre_colour = ndb.StringProperty() 
to_image = ndb.BlobKeyProperty() 
to_popularity = ndb.IntegerProperty() 
is_published = ndb.BooleanProperty() 
is_public = ndb.BooleanProperty(default=False) 
is_featured = ndb.BooleanProperty(default=False)
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
- Frontend caching: most of the API requests are fired when 
initialising the view 
! - Only request data that will be used/visible 
! - Remove the tap delay on mobile 
! - Request images in the size they will be actually displayed 
! - Rendering optimizations, be aware of DOM structure and 
calls to RenderObject https://speakerdeck.com/ 
jaffathecake/rendering-without-lumps 
! - Create a custom font with all icons used (glyphs) https:// 
icomoon.io/
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
The get_serving_url() method allows you to generate a stable, 
dedicated URL for serving web-suitable image thumbnails. 
! 
You simply store a single copy of your original image in Blobstore, 
and then request a high-performance per-image URL. 
[https://cloud.google.com/appengine/docs/python/images/] 
! 
ex. 
! 
// Resize the image to 32 pixels (aspect-ratio preserved) 
http://your_app_id.appspot.com/randomStringImageId=s32 
! 
// Crop the image to 32 pixels 
http://your_app_id.appspot.com/randomStringImageId=s32-c
=s500 
=s100
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
GAE docs are rubbish! :) i.e. read it, then forget it: 
https://cloud.google.com/appengine/articles/load_test 
! 
3rd party services are OK, but run your own if you can 
! 
create a meaningful simulation of users’ behaviour 
! 
hit it as hard as you can, but don’t forget your wallet!
locust 
class ApiNav(TaskSet): 
@task(1) 
def api_global(self): 
self.client.get('/api/global?locale=%s' % langs[random.randint(0, len(langs)-1)], **kwargs) 
! 
@task(1) 
def api_user(self): 
self.client.get('/api/user', **kwargs) 
! 
@task(4) 
def api_gallery(self): 
self.client.get('/api/gallery?i=0&l=15', **kwargs) 
! 
@task(8) 
def api_search(self): 
self.client.get('/api/gallery?i=0&l=15&q=%s' % terms[random.randint(0, len(terms)-1)], **kwargs) 
! 
@task(6) 
def api_feeling_lucky(self): 
self.client.get('/api/page/feeling_lucky', **kwargs) 
! 
@task(2) 
def api_big_gallery(self): 
self.client.get('/api/gallery?i=0&l=30', **kwargs) 
! 
@task(2) 
def api_featured(self): 
self.client.get('/api/gallery?i=0&l=15&t=featured', **kwargs) 
! 
class MyLocust(HttpLocust): 
host = 'https://sd-goog-devart.appspot.com' 
task_set = ApiNav 
min_wait = 5000 
max_wait = 15000 
init data 
gallery 
random search 
random project page 
categorized views
- approximately 5000 concurrent user hitting the backend 
API with a "casual navigation" simulation from different 
location (London, New York, AWS data centre in Ireland) 
! - 85 running instances (class F2) at peak 
! - no errors reported other than random https sockets 
timeout 
! - average response times - < 2s for gallery content navigation - < 1s for singe project page navitation - < 3s for static contend (loaded just once)
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
1. Google App Engine (GAE) and AngularJS 
2. data structures 
3. views optimisations 
4. image management 
5. load testing 
6. GAE benchmarking tool and task inspector 
7. GAE asynchronous API
get_serving_url_async 
@classmethod 
def fix_dict(cls, dict, async=False): 
! 
async_blobs = [] 
! 
def _fix_dict(k, v): 
! 
# blob 
if isinstance(v, blobstore.BlobKey): 
try: 
# create futures and put them apart, we'll resolve these later 
output = {'key': str(v), 'url': '', 'rpc': images.get_serving_url_async(v, secure_url=True)} 
async_blobs.append(output) 
return output 
except BaseException as e: 
# logging.warn('error while fetching serving url for [%s] maybe using corrupted image?' % (v,)) 
return None 
! 
for k, v in dict.iteritems(): 
dict[k] = _fix_dict(k, v) 
! 
if async is True: 
return dict, async_blobs 
else: 
cls.resolve_future_blobs(async_blobs) 
return dict 
! 
@classmethod 
def resolve_future_blobs(cls, async_blobs): 
# resolve futures 
for blob in async_blobs: 
try: 
blob['url'] = blob['rpc'].get_result() 
except BaseException: 
blob['url'] = '' 
del(blob['rpc']) 
1. get async url 
2. resolve future blobs 
3. get real url
Thanks! 
uh, just two notes: 
! 
1. we are hiring! send us your CV - careers@stinkdigital.com 
2. we organise a Meetup with UNIT9 and B-Reel, get in touch! 
tomalisi@stinkdigital.com

More Related Content

Similar to Performance and Optmization - a technical talk at Frontend London

Art & music vs Google App Engine
Art & music vs Google App EngineArt & music vs Google App Engine
Art & music vs Google App Engine
thomas alisi
 
Intro To Django
Intro To DjangoIntro To Django
Intro To Django
Udi Bauman
 
Testing Angular 2 Applications - Rich Web 2016
Testing Angular 2 Applications - Rich Web 2016Testing Angular 2 Applications - Rich Web 2016
Testing Angular 2 Applications - Rich Web 2016
Matt Raible
 
Testing Angular Applications - Jfokus 2017
Testing Angular Applications - Jfokus 2017Testing Angular Applications - Jfokus 2017
Testing Angular Applications - Jfokus 2017
Matt Raible
 
I've (probably) been using Google App Engine for a week longer than you have
I've (probably) been using Google App Engine for a week longer than you haveI've (probably) been using Google App Engine for a week longer than you have
I've (probably) been using Google App Engine for a week longer than you have
Simon Willison
 
Introduction to SPA with AngularJS
Introduction to SPA with AngularJSIntroduction to SPA with AngularJS
Introduction to SPA with AngularJS
Riki Pribadi
 
From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)
Bramus Van Damme
 
Angular - Beginner
Angular - BeginnerAngular - Beginner
Angular - Beginner
Riccardo Masetti
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Matt Raible
 
JBUG 11 - Django-The Web Framework For Perfectionists With Deadlines
JBUG 11 - Django-The Web Framework For Perfectionists With DeadlinesJBUG 11 - Django-The Web Framework For Perfectionists With Deadlines
JBUG 11 - Django-The Web Framework For Perfectionists With Deadlines
Tikal Knowledge
 
Deep crawl the chaotic landscape of JavaScript
Deep crawl the chaotic landscape of JavaScript Deep crawl the chaotic landscape of JavaScript
Deep crawl the chaotic landscape of JavaScript
Onely
 
Intro to AngularJs
Intro to AngularJsIntro to AngularJs
Intro to AngularJs
SolTech, Inc.
 
AngularJS for Legacy Apps
AngularJS for Legacy AppsAngularJS for Legacy Apps
AngularJS for Legacy Apps
Peter Drinnan
 
Getting Started With AngularJS
Getting Started With AngularJSGetting Started With AngularJS
Getting Started With AngularJS
Omnia Helmi
 
Angularjs
AngularjsAngularjs
Angularjs
Ynon Perek
 
Play Framework on Google App Engine
Play Framework on Google App EnginePlay Framework on Google App Engine
Play Framework on Google App Engine
Fred Lin
 
How I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScriptHow I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScript
Kevin Read
 
Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8
Kevin Read
 
Dive into AngularJS and directives
Dive into AngularJS and directivesDive into AngularJS and directives
Dive into AngularJS and directives
Tricode (part of Dept)
 
Angular js slides
Angular js slidesAngular js slides
Angular js slides
Amr Abd El Latief
 

Similar to Performance and Optmization - a technical talk at Frontend London (20)

Art & music vs Google App Engine
Art & music vs Google App EngineArt & music vs Google App Engine
Art & music vs Google App Engine
 
Intro To Django
Intro To DjangoIntro To Django
Intro To Django
 
Testing Angular 2 Applications - Rich Web 2016
Testing Angular 2 Applications - Rich Web 2016Testing Angular 2 Applications - Rich Web 2016
Testing Angular 2 Applications - Rich Web 2016
 
Testing Angular Applications - Jfokus 2017
Testing Angular Applications - Jfokus 2017Testing Angular Applications - Jfokus 2017
Testing Angular Applications - Jfokus 2017
 
I've (probably) been using Google App Engine for a week longer than you have
I've (probably) been using Google App Engine for a week longer than you haveI've (probably) been using Google App Engine for a week longer than you have
I've (probably) been using Google App Engine for a week longer than you have
 
Introduction to SPA with AngularJS
Introduction to SPA with AngularJSIntroduction to SPA with AngularJS
Introduction to SPA with AngularJS
 
From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)
 
Angular - Beginner
Angular - BeginnerAngular - Beginner
Angular - Beginner
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
 
JBUG 11 - Django-The Web Framework For Perfectionists With Deadlines
JBUG 11 - Django-The Web Framework For Perfectionists With DeadlinesJBUG 11 - Django-The Web Framework For Perfectionists With Deadlines
JBUG 11 - Django-The Web Framework For Perfectionists With Deadlines
 
Deep crawl the chaotic landscape of JavaScript
Deep crawl the chaotic landscape of JavaScript Deep crawl the chaotic landscape of JavaScript
Deep crawl the chaotic landscape of JavaScript
 
Intro to AngularJs
Intro to AngularJsIntro to AngularJs
Intro to AngularJs
 
AngularJS for Legacy Apps
AngularJS for Legacy AppsAngularJS for Legacy Apps
AngularJS for Legacy Apps
 
Getting Started With AngularJS
Getting Started With AngularJSGetting Started With AngularJS
Getting Started With AngularJS
 
Angularjs
AngularjsAngularjs
Angularjs
 
Play Framework on Google App Engine
Play Framework on Google App EnginePlay Framework on Google App Engine
Play Framework on Google App Engine
 
How I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScriptHow I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScript
 
Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8
 
Dive into AngularJS and directives
Dive into AngularJS and directivesDive into AngularJS and directives
Dive into AngularJS and directives
 
Angular js slides
Angular js slidesAngular js slides
Angular js slides
 

Recently uploaded

怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
rtunex8r
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
k4ncd0z
 
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
uehowe
 
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
3a0sd7z3
 
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
uehowe
 
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
ysasp1
 
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
uehowe
 
manuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal
manuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalmanuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal
manuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal
wolfsoftcompanyco
 
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
3a0sd7z3
 
Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
davidjhones387
 
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
fovkoyb
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
xjq03c34
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
Paul Walk
 
Ready to Unlock the Power of Blockchain!
Ready to Unlock the Power of Blockchain!Ready to Unlock the Power of Blockchain!
Ready to Unlock the Power of Blockchain!
Toptal Tech
 
HijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process HollowingHijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process Hollowing
Donato Onofri
 
Bengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal BrandingBengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal Branding
Tarandeep Singh
 

Recently uploaded (16)

怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
 
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
 
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
 
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
 
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
 
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
 
manuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal
manuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalmanuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal
manuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal
 
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
 
Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
 
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
 
Ready to Unlock the Power of Blockchain!
Ready to Unlock the Power of Blockchain!Ready to Unlock the Power of Blockchain!
Ready to Unlock the Power of Blockchain!
 
HijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process HollowingHijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process Hollowing
 
Bengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal BrandingBengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal Branding
 

Performance and Optmization - a technical talk at Frontend London

  • 1. Performance + Optimization Thomas Alisi, Solution Architect @grudelsud @stinkdigital EpicFEL Oct2014, Sadler’s Wells, London photo courtesy of https://www.flickr.com/photos/8064990@N08/
  • 2. Stinkdigital is an interactive production company, working with clients and advertising agencies worldwide. ! Our services include creative concepting, design and high-end execution. We create everything from live-action films and websites, through to mobile apps and installations. See our 2013 showreel
  • 3. Project Google Title + The Barbican BDreavnadrt Body A new platform creative text coders goes here. from Google and the Barbican that aims to reward and inspire everywhere. VIEW SITE
  • 4. Revolutions in Sound Red Bull We teamed up with Google+ & Red Bull Music Academy to create a living archive of UK club culture. VIEW SITE ABOUT THE TECHNOLOGY
  • 5. Does this number look familiar to you? 86,400
  • 6. Does this number look familiar to you? 86,400 = 60’’ x 60’ x 24h [number of seconds in 1 day]
  • 7. What about this one? 31,536,000
  • 8. What about this one? 31,536,000 = 86,400’’ x 365d [number of seconds in 1 year]
  • 9. OK, now try and guess the last one 252,000,000
  • 10. OK, now try and guess the last one 252,000,000 = 31.5M’’ x 8y [number of seconds in 8 years]
  • 11. but also… 252,000,000 = 36M x 7’’ [7 seconds saved for each of the 36M visits we had during the first 6 months on DevArt]
  • 12. How did we do it? 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 13. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 14. - Grunt, Gulp, Browserify, Webpack… AAARGH! ! - we like vanilla JS and have been fan of Gulp (at least over the past 10 minutes…) ! - we (I) tend to use a super simple Gulp-Browserify- AngularJS boilerplate https://github.com/grudelsud/angularjs-gulp-browserify-boilerplate ! - but there are other good examples too e.g. https://github.com/unit9/coffee-bone ! ! divide et impera
  • 15. - GAE is not opinionated (which is good) ! - don’t use Django on GAE unless you really want to (e.g. use legacy modules or deploy something really quick) ! - Flask is OK and does not have preferences for a specific ORM (which is great) ! - webapp2 is really super simple (a bit too simple…)
  • 16. bespoke REST micro-framework class Jsonifiable(ndb.Model): def from_dict(cls, dict): pass ! def to_dict(self, async=False): pass ! def resolve_future_blobs(cls, async_blobs): pass !! class JsonRestHandler(webapp2.RequestHandler): JSON_MIMETYPE = "application/json" ! def write(self, data): self.response.out.write(data) ! extend ndb.Model extend webapp2.RequestHandler basic permission check (skipped here) def send_success(self, obj=None, cache_expiry=None): asynchronous conversion self.response.headers["Content-Type"] = self.JSON_MIMETYPE ! self.write(json.dumps(obj, cls=JsonifiableEncoder)) bespoke encoder
  • 17. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 18. this always seems a good way to start
  • 19.
  • 20. abstraction class ClubNight(BaseModel): name = ndb.StringProperty() content = ContentProperty(ndb.TextProperty) blob_key_logo = ContentProperty(ndb.BlobKeyProperty) genre = ndb.KeyProperty(kind=’Genre’) website = ContentProperty(ndb.StringProperty) address = ContentProperty(ndb.TextProperty) location = ContentProperty(ndb.GeoPtProperty) ! class Connection(ndb.Model): from_key = ndb.KeyProperty() to_key = ndb.KeyProperty()
  • 21. reality class ClubNight(BaseModel): name = ndb.StringProperty() content = ContentProperty(ndb.TextProperty) blob_key_logo = ContentProperty(ndb.BlobKeyProperty) genre = ndb.KeyProperty(kind=’Genre’) website = ContentProperty(ndb.StringProperty) address = ContentProperty(ndb.TextProperty) location = ContentProperty(ndb.GeoPtProperty) ! class Connection(ndb.Model): from_key = ndb.KeyProperty() to_key = ndb.KeyProperty() to_name = ndb.StringProperty() to_kind = ndb.StringProperty() to_slug = ndb.StringProperty() to_genre_colour = ndb.StringProperty() to_image = ndb.BlobKeyProperty() to_popularity = ndb.IntegerProperty() is_published = ndb.BooleanProperty() is_public = ndb.BooleanProperty(default=False) is_featured = ndb.BooleanProperty(default=False)
  • 22. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 23.
  • 24. - Frontend caching: most of the API requests are fired when initialising the view ! - Only request data that will be used/visible ! - Remove the tap delay on mobile ! - Request images in the size they will be actually displayed ! - Rendering optimizations, be aware of DOM structure and calls to RenderObject https://speakerdeck.com/ jaffathecake/rendering-without-lumps ! - Create a custom font with all icons used (glyphs) https:// icomoon.io/
  • 25. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 26. The get_serving_url() method allows you to generate a stable, dedicated URL for serving web-suitable image thumbnails. ! You simply store a single copy of your original image in Blobstore, and then request a high-performance per-image URL. [https://cloud.google.com/appengine/docs/python/images/] ! ex. ! // Resize the image to 32 pixels (aspect-ratio preserved) http://your_app_id.appspot.com/randomStringImageId=s32 ! // Crop the image to 32 pixels http://your_app_id.appspot.com/randomStringImageId=s32-c
  • 28. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 29. GAE docs are rubbish! :) i.e. read it, then forget it: https://cloud.google.com/appengine/articles/load_test ! 3rd party services are OK, but run your own if you can ! create a meaningful simulation of users’ behaviour ! hit it as hard as you can, but don’t forget your wallet!
  • 30. locust class ApiNav(TaskSet): @task(1) def api_global(self): self.client.get('/api/global?locale=%s' % langs[random.randint(0, len(langs)-1)], **kwargs) ! @task(1) def api_user(self): self.client.get('/api/user', **kwargs) ! @task(4) def api_gallery(self): self.client.get('/api/gallery?i=0&l=15', **kwargs) ! @task(8) def api_search(self): self.client.get('/api/gallery?i=0&l=15&q=%s' % terms[random.randint(0, len(terms)-1)], **kwargs) ! @task(6) def api_feeling_lucky(self): self.client.get('/api/page/feeling_lucky', **kwargs) ! @task(2) def api_big_gallery(self): self.client.get('/api/gallery?i=0&l=30', **kwargs) ! @task(2) def api_featured(self): self.client.get('/api/gallery?i=0&l=15&t=featured', **kwargs) ! class MyLocust(HttpLocust): host = 'https://sd-goog-devart.appspot.com' task_set = ApiNav min_wait = 5000 max_wait = 15000 init data gallery random search random project page categorized views
  • 31. - approximately 5000 concurrent user hitting the backend API with a "casual navigation" simulation from different location (London, New York, AWS data centre in Ireland) ! - 85 running instances (class F2) at peak ! - no errors reported other than random https sockets timeout ! - average response times - < 2s for gallery content navigation - < 1s for singe project page navitation - < 3s for static contend (loaded just once)
  • 32. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38. 1. Google App Engine (GAE) and AngularJS 2. data structures 3. views optimisations 4. image management 5. load testing 6. GAE benchmarking tool and task inspector 7. GAE asynchronous API
  • 39. get_serving_url_async @classmethod def fix_dict(cls, dict, async=False): ! async_blobs = [] ! def _fix_dict(k, v): ! # blob if isinstance(v, blobstore.BlobKey): try: # create futures and put them apart, we'll resolve these later output = {'key': str(v), 'url': '', 'rpc': images.get_serving_url_async(v, secure_url=True)} async_blobs.append(output) return output except BaseException as e: # logging.warn('error while fetching serving url for [%s] maybe using corrupted image?' % (v,)) return None ! for k, v in dict.iteritems(): dict[k] = _fix_dict(k, v) ! if async is True: return dict, async_blobs else: cls.resolve_future_blobs(async_blobs) return dict ! @classmethod def resolve_future_blobs(cls, async_blobs): # resolve futures for blob in async_blobs: try: blob['url'] = blob['rpc'].get_result() except BaseException: blob['url'] = '' del(blob['rpc']) 1. get async url 2. resolve future blobs 3. get real url
  • 40. Thanks! uh, just two notes: ! 1. we are hiring! send us your CV - careers@stinkdigital.com 2. we organise a Meetup with UNIT9 and B-Reel, get in touch! tomalisi@stinkdigital.com