Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 1 | package benchmark |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 2 | |
| 3 | import ( |
| 4 | "bytes" |
| 5 | "fmt" |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 6 | "testing" |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 7 | "time" |
| 8 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 9 | "v.io/core/veyron/lib/testutil/benchmark" |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 10 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 11 | "v.io/core/veyron2/context" |
| 12 | "v.io/core/veyron2/vlog" |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 13 | ) |
| 14 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 15 | // CallEcho calls 'Echo' method 'iterations' times with the given payload size. |
| 16 | func CallEcho(b *testing.B, ctx *context.T, address string, iterations, payloadSize int, stats *benchmark.Stats) { |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 17 | stub := BenchmarkClient(address) |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 18 | payload := make([]byte, payloadSize) |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 19 | for i := range payload { |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 20 | payload[i] = byte(i & 0xff) |
| 21 | } |
| 22 | |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 23 | b.SetBytes(int64(payloadSize) * 2) // 2 for round trip of each payload. |
| 24 | b.ResetTimer() // Exclude setup time from measurement. |
| 25 | |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 26 | for i := 0; i < iterations; i++ { |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 27 | b.StartTimer() |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 28 | start := time.Now() |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 29 | |
| 30 | r, err := stub.Echo(ctx, payload) |
| 31 | |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 32 | elapsed := time.Since(start) |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 33 | b.StopTimer() |
| 34 | |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 35 | if err != nil { |
| 36 | vlog.Fatalf("Echo failed: %v", err) |
| 37 | } |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 38 | if !bytes.Equal(r, payload) { |
| 39 | vlog.Fatalf("Echo returned %v, but expected %v", r, payload) |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 40 | } |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 41 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 42 | stats.Add(elapsed) |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 43 | } |
| 44 | } |
| 45 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 46 | // CallEchoStream calls 'EchoStream' method 'iterations' times. Each iteration sends |
| 47 | // 'chunkCnt' chunks on the stream and receives the same number of chunks back. Each |
| 48 | // chunk has the given payload size. |
| 49 | func CallEchoStream(b *testing.B, ctx *context.T, address string, iterations, chunkCnt, payloadSize int, stats *benchmark.Stats) { |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 50 | done, _ := StartEchoStream(b, ctx, address, iterations, chunkCnt, payloadSize, stats) |
| 51 | <-done |
| 52 | } |
| 53 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 54 | // StartEchoStream starts to call 'EchoStream' method 'iterations' times. This does |
| 55 | // not block, and returns a channel that will receive the number of iterations when |
| 56 | // it's done. It also returns a callback function to stop the streaming. Each iteration |
| 57 | // requests 'chunkCnt' chunks on the stream and receives that number of chunks back. |
| 58 | // Each chunk has the given payload size. Zero 'iterations' means unlimited. |
| 59 | func StartEchoStream(b *testing.B, ctx *context.T, address string, iterations, chunkCnt, payloadSize int, stats *benchmark.Stats) (<-chan int, func()) { |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 60 | stub := BenchmarkClient(address) |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 61 | payload := make([]byte, payloadSize) |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 62 | for i := range payload { |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 63 | payload[i] = byte(i & 0xff) |
| 64 | } |
| 65 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 66 | stop := make(chan struct{}) |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 67 | stopped := func() bool { |
| 68 | select { |
| 69 | case <-stop: |
| 70 | return true |
| 71 | default: |
| 72 | return false |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 73 | } |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 74 | } |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 75 | done := make(chan int, 1) |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 76 | |
| 77 | if b.N > 0 { |
| 78 | // 2 for round trip of each payload. |
| 79 | b.SetBytes(int64((iterations*chunkCnt/b.N)*payloadSize) * 2) |
| 80 | } |
| 81 | b.ResetTimer() // Exclude setup time from measurement. |
| 82 | |
| 83 | go func() { |
| 84 | defer close(done) |
| 85 | |
| 86 | n := 0 |
| 87 | for ; !stopped() && (iterations == 0 || n < iterations); n++ { |
| 88 | b.StartTimer() |
| 89 | start := time.Now() |
| 90 | |
| 91 | stream, err := stub.EchoStream(ctx) |
| 92 | if err != nil { |
| 93 | vlog.Fatalf("EchoStream failed: %v", err) |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 94 | } |
Shyam Jayaraman | c4aed6e | 2014-07-22 14:25:06 -0700 | [diff] [blame] | 95 | |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 96 | rDone := make(chan error, 1) |
| 97 | go func() { |
| 98 | defer close(rDone) |
| 99 | |
| 100 | rStream := stream.RecvStream() |
| 101 | i := 0 |
| 102 | for ; rStream.Advance(); i++ { |
| 103 | r := rStream.Value() |
| 104 | if !bytes.Equal(r, payload) { |
| 105 | rDone <- fmt.Errorf("EchoStream returned %v, but expected %v", r, payload) |
| 106 | return |
| 107 | } |
| 108 | } |
| 109 | if i != chunkCnt { |
Jungho Ahn | b2657b2 | 2015-02-04 09:10:04 -0800 | [diff] [blame] | 110 | rDone <- fmt.Errorf("EchoStream returned %d chunks, but expected %d", i, chunkCnt) |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 111 | return |
| 112 | } |
| 113 | rDone <- rStream.Err() |
| 114 | }() |
| 115 | |
| 116 | sStream := stream.SendStream() |
| 117 | for i := 0; i < chunkCnt; i++ { |
| 118 | if err = sStream.Send(payload); err != nil { |
| 119 | vlog.Fatalf("EchoStream Send failed: %v", err) |
| 120 | } |
| 121 | } |
| 122 | if err = sStream.Close(); err != nil { |
| 123 | vlog.Fatalf("EchoStream Send failed: %v", err) |
| 124 | } |
| 125 | |
| 126 | if err = <-rDone; err != nil { |
| 127 | vlog.Fatalf("%v", err) |
| 128 | } |
| 129 | |
| 130 | if err = stream.Finish(); err != nil { |
| 131 | vlog.Fatalf("Finish failed: %v", err) |
| 132 | } |
| 133 | |
| 134 | elapsed := time.Since(start) |
| 135 | b.StopTimer() |
| 136 | |
Jungho Ahn | fa7a31f | 2015-01-07 17:34:12 -0800 | [diff] [blame] | 137 | stats.Add(elapsed) |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 138 | } |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 139 | |
Jungho Ahn | bc6ffa2 | 2014-12-10 17:55:35 -0800 | [diff] [blame] | 140 | done <- n |
| 141 | }() |
| 142 | |
| 143 | return done, func() { |
| 144 | close(stop) |
| 145 | <-done |
Robin Thellend | cafaa49 | 2014-06-24 13:58:25 -0700 | [diff] [blame] | 146 | } |
| 147 | } |