SlideShare a Scribd company logo
Practical Google App Engine
   Applications in Python

        上官林傑 (ericsk)
         COSCUP 2009



              http://tinyurl.com/coscup-appengine
Outline

 Effective Datastore API
 Data Manipulation Efficiency
 Effective Memcache
 Zip Import & Zip Serve
 Conclusion
Quota Limit on App Engine




      from: http://www.flickr.com/photos/kevin814/3587610731/
What's Datastore

 Datastore is a kind of key-value database built on GFS.
    scalable
    Kind-based data entities. (not table-based)
    add/remove properties dynamically




    Relational DB Table




                                             Datastore
Avoid Heavily-Indexing

 Datastore will create index on each property.
    If there're many properties in your data, indexing will
    downgrade performance.
    If a property is not used for filtering nor ordering, add
    indexed=False to the data model declaration.

    class Foo(db.Model):
        name = db.StringProperty(required=True)
        bar = db.StringProperty(indexed=False)
Minimize Datastore API Calls

 CRUD data entities by keys:
   Ineffective Way:
    keys = [key1, key2, key3, ..., keyN]
    products = []
    for key in keys:
        products.append(db.get(key))
    ...
    Effective Way:
    keys = [key1, key2, key3, ..., keyN]
    products = db.get(keys)
    Same as db.put(), db.delete().
Re-bind GqlQuery Object

 Use prepared GqlQuery data:
    Ineffective way:
    conds = [['abc', 'def'], ['123', '456'], ...]
    for cond in conds:
        query = db.GqlQuery('SELECT * FROM Foo WHERE first = :
    first, second = :second', first=cond[0], second=cond[1])
        ....
    Effective way:
    conds = [['abc', 'def'], ['123', '456'], ...]
    prepared_query = db.GqlQuery('SELECT * FROM Foo WHERE first
    = :first, second = :second')
    for cond in conds:
         query = prepared_query.bind(first=cond[0], second=cond
    [1])
         ....
Avoid Disjunctions

 IN or != operator generates more queries.
    SELECT * FROM Foo WHERE a IN ('x', 'y') and b != 3
    splits into 4 queries
        SELECT   *   FROM   Foo   WHERE   a   == 'x'
        SELECT   *   FROM   Foo   WHERE   a   == 'y'
        SELECT   *   FROM   Foo   WHERE   b   < 3
        SELECT   *   FROM   Foo   WHERE   b   > 3
 Fetches all data and filters them manually.
How to Fetch More Than 1000 Results

 Datastore API fetches no more than 1000 results once a call
 Fetches more than 1000 results (SLOW, may cause TLE)

 data = Foo.gql('ORDER BY __key__').fetch(1000)
 last_key = data[-1].key()
 results = data

 while len(data) == 1000:
     data = Foo.gql('WHERE __key__ > :1 ORDER BY __key__',
 last_key).fetch(1000)
     last_key = data[-1].key()
     results.extend(data)
Put Data into Entity Group
Put Data into Entity Group (cont.)

  Put data into an entity group:
  forum = Forum.get_by_key_name('HotForum')
  topic = Topic(key_name='Topic1',......, parent=forum).put()
  Load data from an entity group:
  topic = Topic.get_by_key_name('Topic1',
      parent=db.Key.from_path('Forum', 'HotForum'))
Sharding Data

 Write data in parallel
    avoiding write contention
 Sharding data with key_name:
 class Counter(db.Model):
     name = db.StringProperty()
     count = db.IntegerProperty()
 ...
 def incr_counter(counter_name):
     shard = random.randint(0, NUM_SHARDS - 1)
     counter = Counter.get_or_insert(shard, name=counter_name)
     counter.count += 1
     counter.put()
Effective Caching

 Caching page content
    Without caching
    ....
    self.response.out.write(
         template.render('index.html', {})
    )
    ...
    With Caching
    page_content = memcache.get('index_page_content')
    if page_content is None:
         page_content = template.render('index.html',{})
    self.response.out.write(page_content)
Effective Caching (cont.)

  Caching frequently fetched entities
     Without caching
     ....
     products = Product.gql('WHERE price < 100').fetch(1000)
     from django.utils import simplejson
     self.response.out.write(simplejson.dumps(products))
     With caching
     ...
     products = memcache.get('products_lt_100')
     if products is None:
         products = Product.gql('WHERE price < 100').fetch(1000)
     from django.utils import simplejson
     self.response.out.write(simplejson.dumps(products))
Zipimport & ZipServe

 ZipImport:
 Zip your library and then import modules within it.
 ZipServe:
 Zip your static/asset files, then serve them with zipserve.
 WHY?
 You can ONLY put 1000 files in your application.
Zipimport

 For example, you want to use Google Data client library in
 your application.
    You have to put gdata/ and atom/ packages into your
    application directory.
    With zipimport, you can zip them:
    application/
        app.yaml
        ....
        atom.zip
        gdata.zip
        ....
Zipimport (cont.)

    import gdata modules in your script:
    ...
    import sys

    sys.path.append('atom.zip')
    sys.path.append('gdata.zip')
    ....
    from gdata.doc import service
Zipserve

 For example, you want to use TinyMCE library
    You have to put TinyMCE library into your directory. However, it
    contains lots of files.
    With zipserve, you can zip the library, and configure the app.
    yaml:
    ...
    - url: /tinymce/.*
      script: $PYTHON_LIB/google/appengine/ext/zipserve

    The filename MUST be the same as the directory name. In this
    sample, the TinyMCE library should be zipped into tinymce.
    zip.
Conclusion - How to Write Better
GAE Apps?
 Read the Articles on Google App Engine site.
 Trace the source from SDK
    Maybe you will find the undocumented API.
 Read http://practicalappengine.blogspot.com/ (in Traditional
 Chinese)
 Develop apps!
台北, Taipei


http://taipei-gtug.org/

More Related Content

PDF
Mirage For Beginners
PDF
NestJS
PDF
How to instantiate any view controller for free
PDF
Rntb20200805
 
PPTX
Asynchronous Task Queues with Celery
PDF
How to send gzipped requests with boto3
PDF
Angular - injection tokens & Custom libraries
PDF
Tasks: you gotta know how to run them
Mirage For Beginners
NestJS
How to instantiate any view controller for free
Rntb20200805
 
Asynchronous Task Queues with Celery
How to send gzipped requests with boto3
Angular - injection tokens & Custom libraries
Tasks: you gotta know how to run them

What's hot (20)

PDF
Boost your angular app with web workers
PDF
[Quase] Tudo que você precisa saber sobre tarefas assíncronas
PPTX
Swift LA Meetup at eHarmony- What's New in Swift 2.0
PDF
Redux Sagas - React Alicante
PDF
Angular promises and http
PDF
Automation in angular js
PPTX
Firebase ng2 zurich
PPTX
Typescript barcelona
KEY
And the Greatest of These Is ... Rack Support
PPTX
Method and decorator
PPTX
Avoiding callback hell in Node js using promises
PDF
Présentation de HomeKit
PDF
Confident Refactoring - Ember SF Meetup
PDF
Callbacks and control flow in Node js
PDF
Tools for Solving Performance Issues
PDF
Containers & Dependency in Ember.js
PDF
AngularJS Tips&Tricks
PDF
How to Create a l10n Payroll Structure
PDF
How to build an AngularJS backend-ready app WITHOUT BACKEND
PPTX
Angular2 + rxjs
Boost your angular app with web workers
[Quase] Tudo que você precisa saber sobre tarefas assíncronas
Swift LA Meetup at eHarmony- What's New in Swift 2.0
Redux Sagas - React Alicante
Angular promises and http
Automation in angular js
Firebase ng2 zurich
Typescript barcelona
And the Greatest of These Is ... Rack Support
Method and decorator
Avoiding callback hell in Node js using promises
Présentation de HomeKit
Confident Refactoring - Ember SF Meetup
Callbacks and control flow in Node js
Tools for Solving Performance Issues
Containers & Dependency in Ember.js
AngularJS Tips&Tricks
How to Create a l10n Payroll Structure
How to build an AngularJS backend-ready app WITHOUT BACKEND
Angular2 + rxjs
Ad

Viewers also liked (9)

PPT
self introduction
PPT
Naples
PPT
www.Disconshopbd
PDF
The Google App Engine Oil Framework
PPT
Self Introduction
PPT
2005 baltimore-ravens-rex-ryan
PPT
Nokia Sales presentation 07 & 08 At Ctg
PPTX
Introducing .NET Core Open Source
self introduction
Naples
www.Disconshopbd
The Google App Engine Oil Framework
Self Introduction
2005 baltimore-ravens-rex-ryan
Nokia Sales presentation 07 & 08 At Ctg
Introducing .NET Core Open Source
Ad

Similar to Practical Google App Engine Applications In Py (20)

PDF
Optimization in django orm
PPTX
How to Bring Common UI Patterns to ADF
PDF
How te bring common UI patterns to ADF
PDF
Google App Engine in 40 minutes (the absolute essentials)
ODT
Eclipse Tricks
PDF
PPTX
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
PDF
Practical Celery
ODP
Pruebas unitarias con django
PDF
Django design-patterns
PDF
Datagrids with Symfony 2, Backbone and Backgrid
PDF
Datagrids with Symfony 2, Backbone and Backgrid
PDF
Apache Calcite Tutorial - BOSS 21
PPTX
Database connectivity in python
PDF
Automation with Ansible and Containers
KEY
Android workshop
PDF
Using Task Queues and D3.js to build an analytics product on App Engine
KEY
Inside PyMongo - MongoNYC
PPTX
Unsupervised Aspect Based Sentiment Analysis at Scale
PPT
Backbone.js
Optimization in django orm
How to Bring Common UI Patterns to ADF
How te bring common UI patterns to ADF
Google App Engine in 40 minutes (the absolute essentials)
Eclipse Tricks
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Practical Celery
Pruebas unitarias con django
Django design-patterns
Datagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and Backgrid
Apache Calcite Tutorial - BOSS 21
Database connectivity in python
Automation with Ansible and Containers
Android workshop
Using Task Queues and D3.js to build an analytics product on App Engine
Inside PyMongo - MongoNYC
Unsupervised Aspect Based Sentiment Analysis at Scale
Backbone.js

More from Eric ShangKuan (13)

PPTX
運用 Azure Custom Vision 輕鬆開發智慧視覺應用程式
PPTX
Azure machine learning overview
PPTX
Internet Explorer 10: 重新想像網站設計
PDF
透過 Windows Azure Mobile Services 開發各平台 Apps
PPTX
Metro Style Apps from C++ Developers' View
PPTX
Building Python Applications on Windows Azure
PPTX
Microsoft and jQuery
PDF
Tuning Web Performance
PDF
Intro To Google Maps
PDF
An Introduction to GAEO web framework
PDF
Intro. to JavaScript
PDF
Intro. to CSS
PDF
jQuery Tutorial
運用 Azure Custom Vision 輕鬆開發智慧視覺應用程式
Azure machine learning overview
Internet Explorer 10: 重新想像網站設計
透過 Windows Azure Mobile Services 開發各平台 Apps
Metro Style Apps from C++ Developers' View
Building Python Applications on Windows Azure
Microsoft and jQuery
Tuning Web Performance
Intro To Google Maps
An Introduction to GAEO web framework
Intro. to JavaScript
Intro. to CSS
jQuery Tutorial

Recently uploaded (20)

PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Programs and apps: productivity, graphics, security and other tools
PPT
Teaching material agriculture food technology
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Approach and Philosophy of On baking technology
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
KodekX | Application Modernization Development
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
cuic standard and advanced reporting.pdf
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Building Integrated photovoltaic BIPV_UPV.pdf
NewMind AI Weekly Chronicles - August'25 Week I
Programs and apps: productivity, graphics, security and other tools
Teaching material agriculture food technology
The AUB Centre for AI in Media Proposal.docx
MYSQL Presentation for SQL database connectivity
Approach and Philosophy of On baking technology
Spectral efficient network and resource selection model in 5G networks
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
KodekX | Application Modernization Development
20250228 LYD VKU AI Blended-Learning.pptx
Understanding_Digital_Forensics_Presentation.pptx
“AI and Expert System Decision Support & Business Intelligence Systems”
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Reach Out and Touch Someone: Haptics and Empathic Computing
cuic standard and advanced reporting.pdf
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy

Practical Google App Engine Applications In Py

  • 1. Practical Google App Engine Applications in Python 上官林傑 (ericsk) COSCUP 2009 http://tinyurl.com/coscup-appengine
  • 2. Outline Effective Datastore API Data Manipulation Efficiency Effective Memcache Zip Import & Zip Serve Conclusion
  • 3. Quota Limit on App Engine from: http://www.flickr.com/photos/kevin814/3587610731/
  • 4. What's Datastore Datastore is a kind of key-value database built on GFS. scalable Kind-based data entities. (not table-based) add/remove properties dynamically Relational DB Table Datastore
  • 5. Avoid Heavily-Indexing Datastore will create index on each property. If there're many properties in your data, indexing will downgrade performance. If a property is not used for filtering nor ordering, add indexed=False to the data model declaration. class Foo(db.Model): name = db.StringProperty(required=True) bar = db.StringProperty(indexed=False)
  • 6. Minimize Datastore API Calls CRUD data entities by keys: Ineffective Way: keys = [key1, key2, key3, ..., keyN] products = [] for key in keys: products.append(db.get(key)) ... Effective Way: keys = [key1, key2, key3, ..., keyN] products = db.get(keys) Same as db.put(), db.delete().
  • 7. Re-bind GqlQuery Object Use prepared GqlQuery data: Ineffective way: conds = [['abc', 'def'], ['123', '456'], ...] for cond in conds: query = db.GqlQuery('SELECT * FROM Foo WHERE first = : first, second = :second', first=cond[0], second=cond[1]) .... Effective way: conds = [['abc', 'def'], ['123', '456'], ...] prepared_query = db.GqlQuery('SELECT * FROM Foo WHERE first = :first, second = :second') for cond in conds: query = prepared_query.bind(first=cond[0], second=cond [1]) ....
  • 8. Avoid Disjunctions IN or != operator generates more queries. SELECT * FROM Foo WHERE a IN ('x', 'y') and b != 3 splits into 4 queries SELECT * FROM Foo WHERE a == 'x' SELECT * FROM Foo WHERE a == 'y' SELECT * FROM Foo WHERE b < 3 SELECT * FROM Foo WHERE b > 3 Fetches all data and filters them manually.
  • 9. How to Fetch More Than 1000 Results Datastore API fetches no more than 1000 results once a call Fetches more than 1000 results (SLOW, may cause TLE) data = Foo.gql('ORDER BY __key__').fetch(1000) last_key = data[-1].key() results = data while len(data) == 1000: data = Foo.gql('WHERE __key__ > :1 ORDER BY __key__', last_key).fetch(1000) last_key = data[-1].key() results.extend(data)
  • 10. Put Data into Entity Group
  • 11. Put Data into Entity Group (cont.) Put data into an entity group: forum = Forum.get_by_key_name('HotForum') topic = Topic(key_name='Topic1',......, parent=forum).put() Load data from an entity group: topic = Topic.get_by_key_name('Topic1', parent=db.Key.from_path('Forum', 'HotForum'))
  • 12. Sharding Data Write data in parallel avoiding write contention Sharding data with key_name: class Counter(db.Model): name = db.StringProperty() count = db.IntegerProperty() ... def incr_counter(counter_name): shard = random.randint(0, NUM_SHARDS - 1) counter = Counter.get_or_insert(shard, name=counter_name) counter.count += 1 counter.put()
  • 13. Effective Caching Caching page content Without caching .... self.response.out.write( template.render('index.html', {}) ) ... With Caching page_content = memcache.get('index_page_content') if page_content is None: page_content = template.render('index.html',{}) self.response.out.write(page_content)
  • 14. Effective Caching (cont.) Caching frequently fetched entities Without caching .... products = Product.gql('WHERE price < 100').fetch(1000) from django.utils import simplejson self.response.out.write(simplejson.dumps(products)) With caching ... products = memcache.get('products_lt_100') if products is None: products = Product.gql('WHERE price < 100').fetch(1000) from django.utils import simplejson self.response.out.write(simplejson.dumps(products))
  • 15. Zipimport & ZipServe ZipImport: Zip your library and then import modules within it. ZipServe: Zip your static/asset files, then serve them with zipserve. WHY? You can ONLY put 1000 files in your application.
  • 16. Zipimport For example, you want to use Google Data client library in your application. You have to put gdata/ and atom/ packages into your application directory. With zipimport, you can zip them: application/ app.yaml .... atom.zip gdata.zip ....
  • 17. Zipimport (cont.) import gdata modules in your script: ... import sys sys.path.append('atom.zip') sys.path.append('gdata.zip') .... from gdata.doc import service
  • 18. Zipserve For example, you want to use TinyMCE library You have to put TinyMCE library into your directory. However, it contains lots of files. With zipserve, you can zip the library, and configure the app. yaml: ... - url: /tinymce/.* script: $PYTHON_LIB/google/appengine/ext/zipserve The filename MUST be the same as the directory name. In this sample, the TinyMCE library should be zipped into tinymce. zip.
  • 19. Conclusion - How to Write Better GAE Apps? Read the Articles on Google App Engine site. Trace the source from SDK Maybe you will find the undocumented API. Read http://practicalappengine.blogspot.com/ (in Traditional Chinese) Develop apps!