Slide 1

Slide 1 text

Performance 
 Optimization 
 on Google AppEngine Go Conference 2018 Spring Seiji Takahashi @__timakin__

Slide 2

Slide 2 text

Who Am I • Seiji Takahashi • @__timakin__ • Gunosy • Application Dev: LUCRA • Serverside Engineering (Go) • iOS Client Side (Swift) • Engieering • Language: Go (Contributed), Swift • Platform: GAE, AWS

Slide 3

Slide 3 text

"CPVUUIJTUBML • We’ll not cover intro to AppEngine. • General guideline to speed up API performance on GAE.

Slide 4

Slide 4 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 5

Slide 5 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 6

Slide 6 text

Warming Up Building an endpoint of warmup, You can prepare before serving data for user’s request. For example, you retrieve the data from datastore and store it on memcache to respond faster.

Slide 7

Slide 7 text

BQQZBNM

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 10

Slide 10 text

Shortest Route 1. No custom domain If you send an internal request to a different service, you should not use custom domain to decrease name resolution cost.

Slide 11

Slide 11 text

Shortest Route 2. Turn off FollowRedirects Internal API should not return other than 200, 400, and 500 series statues. And you should exclude redirects with setting FollowRedirects to false.

Slide 12

Slide 12 text

Shortest Route 3. Single Project Networking between multi-projects will add latency, so if you purpose the best performance, merge services into one project.

Slide 13

Slide 13 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 14

Slide 14 text

Task Queue A heavy job should be scheduled with Task Queue, not user’s request. And it’ll be effective on cron job like crawling too.

Slide 15

Slide 15 text

ex) User’s request Client GAE GAE Job Job Job Job Push Queue Immediate Response

Slide 16

Slide 16 text

ex) Cron job GAE GAE Job Job Job Job Push Queue Bulk Insert Cron

Slide 17

Slide 17 text

RVFVFZBNM

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 20

Slide 20 text

Delayed Job delay package is also background job handling system. It depends on Task Queue. It simplify the asynchronous API of Task Queue, and it can receive arguments of struct.

Slide 21

Slide 21 text

Delayed Job delay package is also background job handling system. It depends on Task Queue. It simplify the asynchronous API of Task Queue, and it can receive arguments of struct. default Task Queue runs tasks through HTTP request and can pass only a string query parameter.

Slide 22

Slide 22 text

*Caution delay.Func will search an execution target with file name and task key, so if you change the file name, waiting tasks will drop because it can’t find the func. Additionally, it must be declared on init() or as a global variable. If it was declared inside of request handling, a receiver instance may fail because Func wasn’t initialized just after spinning-up.

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 25

Slide 25 text

Batching Executing Get/Put/Delete for multi resources in the loop will generate RPC calls. If you can get keys for the records, reduce them with GetMulti/PutMulti/DeleteMulti. And Task Queue also supports AddMulti for bulk insertion.

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Caching Storing/Fetching data from Memcache is better for performance. The cache will be shared among instances. Some third-party packages are good for using Datastore and Memcache simultaneously. • mjibson/goon • mercari/datastore

Slide 30

Slide 30 text

Caching Almost all of interfaces of these packages is same. But goon wins on the current reading benchmark.

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

"HFOEB • Warming up • Route between internal services • Task Queue • Delayed Job • Batching • Caching • Asynchronous requests with goroutine

Slide 33

Slide 33 text

Asynchronous requests with goroutine AppEngine environment forces GOMAXPROCS=1. But within I/O wait time, Go will schedule to other goroutine. Like Datastore/Search API call can be artificially asynchronous and it performs excellent latency.

Slide 34

Slide 34 text

Asynchronous requests with goroutine Basically GetMulti/PutMulti is effective. But when you cannot know the datastore.Key before fetching. For example, goroutine is better for query filtering.

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

goroutine in goroutine is sensitive technique from the aspect of error handling, but good for performance.

Slide 38

Slide 38 text

4VNNBSZ • AppEngine is tunable with routing, background job, goroutine, batch, cache, etc… • Async func is really attractive if your primary goal is performance. However, you must take care of error handling and initialization.

Slide 39

Slide 39 text

5IBOLZPV