]> Cypherpunks repositories - gostls13.git/commitdiff
doc: add Google I/O talk and programs
authorRuss Cox <rsc@golang.org>
Tue, 8 Jun 2010 23:00:04 +0000 (16:00 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 8 Jun 2010 23:00:04 +0000 (16:00 -0700)
R=r
CC=golang-dev
https://golang.org/cl/1614041

doc/talks/io2010/balance.go [new file with mode: 0644]
doc/talks/io2010/decrypt.go [new file with mode: 0644]
doc/talks/io2010/encrypt.go [new file with mode: 0644]
doc/talks/io2010/eval1.go [new file with mode: 0644]
doc/talks/io2010/eval2.go [new file with mode: 0644]
doc/talks/io2010/talk.pdf [new file with mode: 0644]

diff --git a/doc/talks/io2010/balance.go b/doc/talks/io2010/balance.go
new file mode 100644 (file)
index 0000000..6a07138
--- /dev/null
@@ -0,0 +1,164 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "container/heap"
+       "fmt"
+       "rand"
+       "time"
+)
+
+const nRequester = 100
+const nWorker = 10
+
+// Simulation of some work: just sleep for a while and report how long.
+func op() int {
+       n := rand.Int63n(1e9)
+       time.Sleep(nWorker * n)
+       return int(n)
+}
+
+type Request struct {
+       fn func() int
+       c  chan int
+}
+
+func requester(work chan Request) {
+       c := make(chan int)
+       for {
+               time.Sleep(rand.Int63n(nWorker * 2e9))
+               work <- Request{op, c}
+               <-c
+       }
+}
+
+type Worker struct {
+       i        int
+       requests chan Request
+       pending  int
+}
+
+func (w *Worker) work(done chan *Worker) {
+       for {
+               req := <-w.requests
+               req.c <- req.fn()
+               done <- w
+       }
+}
+
+type Pool []*Worker
+
+func (p Pool) Len() int { return len(p) }
+
+func (p Pool) Less(i, j int) bool {
+       return p[i].pending < p[j].pending
+}
+
+func (p *Pool) Swap(i, j int) {
+       a := *p
+       a[i], a[j] = a[j], a[i]
+       a[i].i = i
+       a[j].i = j
+}
+
+func (p *Pool) Push(x interface{}) {
+       a := *p
+       n := len(a)
+       a = a[0 : n+1]
+       w := x.(*Worker)
+       a[n] = w
+       w.i = n
+       *p = a
+}
+
+func (p *Pool) Pop() interface{} {
+       a := *p
+       *p = a[0 : len(a)-1]
+       w := a[len(a)-1]
+       w.i = -1 // for safety
+       return w
+}
+
+type Balancer struct {
+       pool Pool
+       done chan *Worker
+       i    int
+}
+
+func NewBalancer() *Balancer {
+       done := make(chan *Worker, nWorker)
+       b := &Balancer{make(Pool, 0, nWorker), done, 0}
+       for i := 0; i < nWorker; i++ {
+               w := &Worker{requests: make(chan Request, nRequester)}
+               heap.Push(&b.pool, w)
+               go w.work(b.done)
+       }
+       return b
+}
+
+func (b *Balancer) balance(work chan Request) {
+       for {
+               select {
+               case req := <-work:
+                       b.dispatch(req)
+               case w := <-b.done:
+                       b.completed(w)
+               }
+               b.print()
+       }
+}
+
+func (b *Balancer) print() {
+       sum := 0
+       sumsq := 0
+       for _, w := range b.pool {
+               fmt.Printf("%d ", w.pending)
+               sum += w.pending
+               sumsq += w.pending * w.pending
+       }
+       avg := float64(sum) / float64(len(b.pool))
+       variance := float64(sumsq)/float64(len(b.pool)) - avg*avg
+       fmt.Printf(" %.2f %.2f\n", avg, variance)
+}
+
+func (b *Balancer) dispatch(req Request) {
+       if false {
+               w := b.pool[b.i]
+               w.requests <- req
+               w.pending++
+               b.i++
+               if b.i >= len(b.pool) {
+                       b.i = 0
+               }
+               return
+       }
+
+       w := heap.Pop(&b.pool).(*Worker)
+       w.requests <- req
+       w.pending++
+       //      fmt.Printf("started %p; now %d\n", w, w.pending)
+       heap.Push(&b.pool, w)
+}
+
+func (b *Balancer) completed(w *Worker) {
+       if false {
+               w.pending--
+               return
+       }
+
+       w.pending--
+       //      fmt.Printf("finished %p; now %d\n", w, w.pending)
+       heap.Remove(&b.pool, w.i)
+       heap.Push(&b.pool, w)
+}
+
+func main() {
+       work := make(chan Request)
+       for i := 0; i < nRequester; i++ {
+               go requester(work)
+       }
+       NewBalancer().balance(work)
+}
diff --git a/doc/talks/io2010/decrypt.go b/doc/talks/io2010/decrypt.go
new file mode 100644 (file)
index 0000000..3292c30
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "crypto/aes"
+       "crypto/block"
+       "compress/gzip"
+       "io"
+       "os"
+)
+
+func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) {
+       r, _ := os.Open(srcfile, os.O_RDONLY, 0)
+       var w io.Writer
+       w, _ = os.Open(dstfile, os.O_WRONLY|os.O_CREATE, 0666)
+       c, _ := aes.NewCipher(key)
+       w = block.NewOFBWriter(c, iv, w)
+       w2, _ := gzip.NewDeflater(w)
+       io.Copy(w2, r)
+       w2.Close()
+}
+
+func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) {
+       f, _ := os.Open(srcfile, os.O_RDONLY, 0)
+       defer f.Close()
+       c, _ := aes.NewCipher(key)
+       r := block.NewOFBReader(c, iv, f)
+       r, _ = gzip.NewInflater(r)
+       w, _ := os.Open(dstfile, os.O_WRONLY|os.O_CREATE, 0666)
+       defer w.Close()
+       io.Copy(w, r)
+}
+
+func main() {
+       EncryptAndGzip("/tmp/passwd.gz", "/etc/passwd", make([]byte, 16), make([]byte, 16))
+       DecryptAndGunzip("/dev/stdout", "/tmp/passwd.gz", make([]byte, 16), make([]byte, 16))
+}
diff --git a/doc/talks/io2010/encrypt.go b/doc/talks/io2010/encrypt.go
new file mode 100644 (file)
index 0000000..e5ab3fc
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "crypto/aes"
+       "crypto/block"
+       "compress/gzip"
+       "io"
+       "os"
+)
+
+func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) {
+       r, _ := os.Open(srcfile, os.O_RDONLY, 0)
+       var w io.WriteCloser
+       w, _ = os.Open(dstfile, os.O_WRONLY|os.O_CREATE, 0666)
+       defer w.Close()
+       w, _ = gzip.NewDeflater(w)
+       defer w.Close()
+       c, _ := aes.NewCipher(key)
+       io.Copy(block.NewCBCEncrypter(c, iv, w), r)
+}
+
+func main() {
+       EncryptAndGzip("/tmp/passwd.gz", "/etc/passwd", make([]byte, 16), make([]byte, 16))
+}
diff --git a/doc/talks/io2010/eval1.go b/doc/talks/io2010/eval1.go
new file mode 100644 (file)
index 0000000..2d7fc3b
--- /dev/null
@@ -0,0 +1,229 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bufio"
+       "fmt"
+       "os"
+       "strconv"
+       "strings"
+)
+
+// Generic expression parser/evaluator
+
+type Value interface {
+       String() string
+       BinaryOp(op string, y Value) Value
+}
+
+type Parser struct {
+       precTab map[string]int
+       newVal  func(string) Value
+       src     string
+       pos     int
+       tok     string
+}
+
+const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+
+func (p *Parser) stop(c uint8) bool {
+       switch {
+       case p.pos >= len(p.src):
+               return true
+       case c == '"':
+               if p.src[p.pos] == '"' {
+                       p.pos++
+                       return true
+               }
+               return false
+       case strings.IndexRune(alphanum, int(c)) >= 0:
+               return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
+       }
+       return true
+}
+
+func (p *Parser) next() {
+       // skip blanks
+       for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
+       }
+       if p.pos >= len(p.src) {
+               p.tok = ""
+               return
+       }
+       start := p.pos
+       c := p.src[p.pos]
+       for p.pos < len(p.src) {
+               p.pos++
+               if p.stop(c) {
+                       break
+               }
+       }
+       p.tok = p.src[start:p.pos]
+}
+
+func (p *Parser) binaryExpr(prec1 int) Value {
+       x := p.newVal(p.tok)
+       p.next()
+       for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
+               for p.precTab[p.tok] == prec {
+                       op := p.tok
+                       p.next()
+                       y := p.binaryExpr(prec + 1)
+                       x = x.BinaryOp(op, y)
+               }
+       }
+       return x
+}
+
+func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
+       var p Parser
+       p.precTab = precTab
+       p.newVal = newVal
+       p.src = src
+       p.next()
+       return p.binaryExpr(1)
+}
+
+// Command-line expression evaluator
+
+func main() {
+       r := bufio.NewReader(os.Stdin)
+       for {
+               fmt.Printf("> ")
+               line, err := r.ReadString('\n')
+               if err != nil {
+                       break
+               }
+               fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
+       }
+}
+
+
+// Custom grammar and values
+
+var precTab = map[string]int{
+       "&&": 1,
+       "||": 2,
+       "==": 3,
+       "!=": 3,
+       "<":  3,
+       "<=": 3,
+       ">":  3,
+       ">=": 3,
+       "+":  4,
+       "-":  4,
+       "*":  5,
+       "/":  5,
+       "%":  5,
+}
+
+func newVal(lit string) Value {
+       x, err := strconv.Atoi(lit)
+       if err == nil {
+               return Int(x)
+       }
+       b, err := strconv.Atob(lit)
+       if err == nil {
+               return Bool(b)
+       }
+       return Error(fmt.Sprintf("illegal literal '%s'", lit))
+}
+
+type Error string
+
+func (e Error) String() string                    { return string(e) }
+func (e Error) BinaryOp(op string, y Value) Value { return e }
+
+type Int int
+
+func (x Int) String() string { return strconv.Itoa(int(x)) }
+func (x Int) BinaryOp(op string, y Value) Value {
+       switch y := y.(type) {
+       case Error:
+               return y
+       case Int:
+               switch op {
+               case "+":
+                       return x + y
+               case "-":
+                       return x - y
+               case "*":
+                       return x * y
+               case "/":
+                       return x / y
+               case "%":
+                       return x % y
+               case "==":
+                       return Bool(x == y)
+               case "!=":
+                       return Bool(x != y)
+               case "<":
+                       return Bool(x < y)
+               case "<=":
+                       return Bool(x <= y)
+               case ">":
+                       return Bool(x > y)
+               case ">=":
+                       return Bool(x >= y)
+               }
+       }
+       return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
+}
+
+type Bool bool
+
+func (x Bool) String() string { return strconv.Btoa(bool(x)) }
+func (x Bool) BinaryOp(op string, y Value) Value {
+       switch y := y.(type) {
+       case Error:
+               return y
+       case Bool:
+               switch op {
+               case "&&":
+                       return Bool(x && y)
+               case "||":
+                       return Bool(x || y)
+               case "==":
+                       return Bool(x == y)
+               case "!=":
+                       return Bool(x != y)
+               }
+       }
+       return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
+}
+
+
+func trace(newVal func(string) Value) func(string) Value {
+       return func(s string) Value {
+               v := newVal(s)
+               fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
+               return &traceValue{v}
+       }
+}
+
+type traceValue struct {
+       Value
+}
+
+func (x *traceValue) BinaryOp(op string, y Value) Value {
+       z := x.Value.BinaryOp(op, y.(*traceValue).Value)
+       fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
+       return &traceValue{z}
+}
+
+func (x *traceValue) String() string {
+       s := x.Value.String()
+       fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
+       return s
+}
+
+func fmtv(v Value) string {
+       t := fmt.Sprintf("%T", v)
+       if i := strings.LastIndex(t, "."); i >= 0 { // strip package
+               t = t[i+1:]
+       }
+       return fmt.Sprintf("%s(%#v)", t, v)
+}
diff --git a/doc/talks/io2010/eval2.go b/doc/talks/io2010/eval2.go
new file mode 100644 (file)
index 0000000..5524c8b
--- /dev/null
@@ -0,0 +1,261 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bufio"
+       "fmt"
+       "os"
+       "strconv"
+       "strings"
+)
+
+// Generic expression parser/evaluator
+
+type Value interface {
+       String() string
+       BinaryOp(op string, y Value) Value
+}
+
+type Parser struct {
+       precTab map[string]int
+       newVal  func(string) Value
+       src     string
+       pos     int
+       tok     string
+}
+
+const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+
+func (p *Parser) stop(c uint8) bool {
+       switch {
+       case p.pos >= len(p.src):
+               return true
+       case c == '"':
+               if p.src[p.pos] == '"' {
+                       p.pos++
+                       return true
+               }
+               return false
+       case strings.IndexRune(alphanum, int(c)) >= 0:
+               return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
+       }
+       return true
+}
+
+func (p *Parser) next() {
+       // skip blanks
+       for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
+       }
+       if p.pos >= len(p.src) {
+               p.tok = ""
+               return
+       }
+       start := p.pos
+       c := p.src[p.pos]
+       for p.pos < len(p.src) {
+               p.pos++
+               if p.stop(c) {
+                       break
+               }
+       }
+       p.tok = p.src[start:p.pos]
+}
+
+func (p *Parser) binaryExpr(prec1 int) Value {
+       x := p.newVal(p.tok)
+       p.next()
+       for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
+               for p.precTab[p.tok] == prec {
+                       op := p.tok
+                       p.next()
+                       y := p.binaryExpr(prec + 1)
+                       x = x.BinaryOp(op, y)
+               }
+       }
+       return x
+}
+
+func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
+       var p Parser
+       p.precTab = precTab
+       p.newVal = newVal
+       p.src = src
+       p.next()
+       return p.binaryExpr(1)
+}
+
+// Command-line expression evaluator
+
+func main() {
+       r := bufio.NewReader(os.Stdin)
+       for {
+               fmt.Printf("> ")
+               line, err := r.ReadString('\n')
+               if err != nil {
+                       break
+               }
+               fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
+       }
+}
+
+
+// Custom grammar and values
+
+var precTab = map[string]int{
+       "&&": 1,
+       "||": 2,
+       "==": 3,
+       "!=": 3,
+       "<":  3,
+       "<=": 3,
+       ">":  3,
+       ">=": 3,
+       "+":  4,
+       "-":  4,
+       "*":  5,
+       "/":  5,
+       "%":  5,
+}
+
+func newVal(lit string) Value {
+       x, err := strconv.Atoi(lit)
+       if err == nil {
+               return Int(x)
+       }
+       b, err := strconv.Atob(lit)
+       if err == nil {
+               return Bool(b)
+       }
+       s, err := strconv.Unquote(lit)
+       if err == nil {
+               return String(s)
+       }
+       return Error(fmt.Sprintf("illegal literal '%s'", lit))
+}
+
+type Error string
+
+func (e Error) String() string                    { return string(e) }
+func (e Error) BinaryOp(op string, y Value) Value { return e }
+
+type Int int
+
+func (x Int) String() string { return strconv.Itoa(int(x)) }
+func (x Int) BinaryOp(op string, y Value) Value {
+       switch y := y.(type) {
+       case Error:
+               return y
+       case String:
+               switch op {
+               case "*":
+                       return String(strings.Repeat(string(y), int(x)))
+               }
+       case Int:
+               switch op {
+               case "+":
+                       return x + y
+               case "-":
+                       return x - y
+               case "*":
+                       return x * y
+               case "/":
+                       return x / y
+               case "%":
+                       return x % y
+               case "==":
+                       return Bool(x == y)
+               case "!=":
+                       return Bool(x != y)
+               case "<":
+                       return Bool(x < y)
+               case "<=":
+                       return Bool(x <= y)
+               case ">":
+                       return Bool(x > y)
+               case ">=":
+                       return Bool(x >= y)
+               }
+       }
+       return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
+}
+
+type Bool bool
+
+func (x Bool) String() string { return strconv.Btoa(bool(x)) }
+func (x Bool) BinaryOp(op string, y Value) Value {
+       switch y := y.(type) {
+       case Error:
+               return y
+       case Bool:
+               switch op {
+               case "&&":
+                       return Bool(x && y)
+               case "||":
+                       return Bool(x || y)
+               case "==":
+                       return Bool(x == y)
+               case "!=":
+                       return Bool(x != y)
+               }
+       }
+       return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
+}
+
+type String string
+
+func (x String) String() string { return strconv.Quote(string(x)) }
+func (x String) BinaryOp(op string, y Value) Value {
+       switch y := y.(type) {
+       case Error:
+               return y
+       case Int:
+               switch op {
+               case "*":
+                       return String(strings.Repeat(string(x), int(y)))
+               }
+       case String:
+               switch op {
+               case "+":
+                       return x + y
+               case "<":
+                       return Bool(x < y)
+               }
+       }
+       return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
+}
+
+
+func trace(newVal func(string) Value) func(string) Value {
+       return func(s string) Value {
+               v := newVal(s)
+               fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
+               return &traceValue{v}
+       }
+}
+
+type traceValue struct {
+       Value
+}
+
+func (x *traceValue) BinaryOp(op string, y Value) Value {
+       z := x.Value.BinaryOp(op, y.(*traceValue).Value)
+       fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
+       return &traceValue{z}
+}
+
+func (x *traceValue) String() string {
+       s := x.Value.String()
+       fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
+       return s
+}
+
+func fmtv(v Value) string {
+       t := fmt.Sprintf("%T", v)
+       if i := strings.LastIndex(t, "."); i >= 0 { // strip package
+               t = t[i+1:]
+       }
+       return fmt.Sprintf("%s(%#v)", t, v)
+}
diff --git a/doc/talks/io2010/talk.pdf b/doc/talks/io2010/talk.pdf
new file mode 100644 (file)
index 0000000..aff42c2
Binary files /dev/null and b/doc/talks/io2010/talk.pdf differ