From 5b9105ff0c7fe0db575d0d601a090d124b6bd6b3 Mon Sep 17 00:00:00 2001 From: Vikram Rangnekar Date: Thu, 22 Aug 2019 09:03:49 -0400 Subject: [PATCH] Add GoTO Aug, 19 presentation --- slides/highperf.slide | 203 ++++++++++++++++++++++++++++++++++++++++ slides/overview.slide | 2 +- slides/whygraphql.slide | 2 +- 3 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 slides/highperf.slide diff --git a/slides/highperf.slide b/slides/highperf.slide new file mode 100644 index 0000000..87077e0 --- /dev/null +++ b/slides/highperf.slide @@ -0,0 +1,203 @@ +High Performance Code in GO +GoTO, August 2019 +Tags: GraphQL, API, GoLang, Postgres + +Vikram Rangnekar +https://twitter.com/dosco + +* About me + +Co-founder of *movremote.com* a platform to connect developers with Silicon Valley +companies hiring remote. + +Previously worked on Platform, Frontend and Ads @ Linkedin building the distributed targeting and serving infrastructure behind Linkedin Ads. + +Also currently building Super Graph an open source instant GraphQL engine for Postgres and Rails. Written in GO + +MOV Remote +.link https://movremote.com + +Super Graph +.link https://supergraph.dev + +* Why does it matter? + +- Computer are not getting dramatically faster +- Our software is getting slower +- Demands on our software are increasing +- Scale of internet poducts is accelerating +- Faster = More money (For you) + +* What does high performance mean? + +- Code that runs fast (relative) +- Minimizes I/O latency +- Efficient in terms of GC + + + "Premature optimization is the root of all evil (or at least most of it) in programming." + -- Donald Knuth + + "Measure twice cut once" + -- Someone + +* Code that runs fast + +1. Algorithm choices +2. Rewrite in GO +3. Reuse Memory +4. Parallelize I/O +4. Keep it simple + +* Benchmarking + +* $ benchcmp bench.1 bench.2 + +.image https://pbs.twimg.com/media/D8_uRFWU0AUdWkM?format=jpg&name=large _ 970 + +* Howto benchmark + +Single threaded + + func BenchmarkYourFunc(b *testing.B) { + for n := 0; n < b.N; n++ { + _, err := yourFunction(data) + ... + } + } + +Parallel + + func BenchmarkYourFuncP(b *testing.B) { + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _, err := yourFunction(data) + ... + } + }) + } + +* Profileing Your Code + + go test -bench=. -benchmem -memprofile mem.out -run=XXX + go tool pprof -cum mem.out + +Get a nice command line + + pkg: github.com/dosco/super-graph/psql + BenchmarkCompile-8 100000 15138 ns/op 3553 B/op 35 allocs/op + BenchmarkCompileParallel-8 300000 4760 ns/op 3583 B/op 35 allocs/op + PASS + ok github.com/dosco/super-graph/psql 3.174s + Type: alloc_space + Time: Aug 21, 2019 at 11:56am (EDT) + Entering interactive mode (type "help" for commands, "o" for options) + (pprof) + +Powerful commands + +top, web, png, pdf, ... and more + +* Top - Shows you the top allocating functions + + (pprof) top + Showing nodes accounting for 1.07GB, 77.92% of 1.37GB total + Showing top 10 nodes out of 34 + flat flat% sum% cum cum% + 0.01GB 0.89% 0.89% 1.11GB 80.77% github.com/[...]/qcode.(*Compiler).Compile + 0 0% 0.89% 1.02GB 74.22% github.com/dosco/super-graph/ + 0.52GB 37.74% 38.63% 0.94GB 68.50% github.com/[...]/qcode.(*Compiler).compileQuery + 0.54GB 39.29% 77.92% 0.54GB 39.29% github.com/dosco/super-graph/util.NewStack + +Digging deeper + + (pprof) top .compileQuery + focus=.compileQuery + Showing nodes accounting for 1006.59MB, 69.36% of 1451.18MB total + Showing top 10 nodes out of 26 + flat flat% sum% cum cum% + 0 0% 0% 1006.05MB 69.33% github.com/[...]/qcode.(*Compiler).Compile + 579.44MB 39.93% 39.93% 1006.05MB 69.33% github.com/[...]/qcode.(*Compiler).compileQuery + +* Cool Graphs + +.image https://matoski.com/article/golang-profiling-flamegraphs/cpu-profile-graph-001.png 500 _ + +* Reducing Allocations - Part 1 + +Pre-allocate + + m := make(map[string]someStruct{}, len(whatever)) + mp := &m[i] + +Work with bytes if possible + + inlineToLower(&value) instead of bytes.ToLower(value) + +Reuse Memory + + var nodePool = sync.Pool{ + New: func() interface{} { return new(Node) }, + } + +Use Builders + + var b strings.Builder + b.WriteString("hello "); + b.WriteString("world") + +* Reducing Allocations - Part 2 + +Use streaming (io.Reader and io.Writer) + + r := strings.NewReader("some io.Reader stream to be read\n") + + _, err := io.Copy(os.Stdout, r); + +Allocate Together + + type Node struct { + Children []Child + childA [5]Child + } + n := Node{} + n.Children = n.childA[:0] + +Use 'Append' functions + + strconv.AppendInt(b10, 42, 10) instead of strconv.FormatInt(42, 10) + +* Reducing Allocations - Part 3 + +Use 'unsafe' if you know what you're doing + + func bytesToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) + } + +* Squeezing out more performance + +Avoid reflection use generators + +Inlined Assembly (Crazy) + + // add.go + package main + + import "fmt" + + func add(x, y int64) int64 + + func main() { + fmt.Println(add(2, 3)) + } + + // add_amd64.s + TEXT ·add(SB),NOSPLIT,$0 + MOVQ x+0(FP), BX + MOVQ y+8(FP), BP + ADDQ BP, BX + MOVQ BX, ret+16(FP) + RET + diff --git a/slides/overview.slide b/slides/overview.slide index 91ca45a..7888781 100644 --- a/slides/overview.slide +++ b/slides/overview.slide @@ -3,7 +3,7 @@ Instant GraphQL API for Rails. Zero Code. Tags: GraphQL, API, GoLang, Postgres Vikram Rangnekar -https://twitter.com/@dosco +https://twitter.com/dosco * Motivation diff --git a/slides/whygraphql.slide b/slides/whygraphql.slide index 5a2e3d1..7e0a1ed 100644 --- a/slides/whygraphql.slide +++ b/slides/whygraphql.slide @@ -3,7 +3,7 @@ GraphQL is the future of APIs Tags: GraphQL, API, GoLang, Postgres Vikram Rangnekar -https://twitter.com/@dosco +https://twitter.com/dosco * Trends, Why APIs are Important