github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/examples/ping/ping.go (about) 1 /* 2 Copyright 2016 Stanislav Liberman 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "flag" 21 "fmt" 22 "io" 23 "os" 24 "runtime/pprof" 25 "time" 26 27 "github.com/HdrHistogram/hdrhistogram-go" 28 "github.com/lirm/aeron-go/aeron" 29 "github.com/lirm/aeron-go/aeron/atomic" 30 "github.com/lirm/aeron-go/aeron/logbuffer" 31 "github.com/lirm/aeron-go/aeron/logging" 32 "github.com/lirm/aeron-go/examples" 33 ) 34 35 var logger = logging.MustGetLogger("examples") 36 37 func main() { 38 39 flag.Parse() 40 41 if !*examples.ExamplesConfig.LoggingOn { 42 logging.SetLevel(logging.INFO, "aeron") 43 logging.SetLevel(logging.INFO, "memmap") 44 logging.SetLevel(logging.INFO, "driver") 45 logging.SetLevel(logging.INFO, "counters") 46 logging.SetLevel(logging.INFO, "logbuffers") 47 logging.SetLevel(logging.INFO, "buffer") 48 logging.SetLevel(logging.INFO, "examples") 49 } 50 51 to := time.Duration(time.Millisecond.Nanoseconds() * *examples.ExamplesConfig.DriverTo) 52 ctx := aeron.NewContext().AeronDir(*examples.ExamplesConfig.AeronPrefix).MediaDriverTimeout(to) 53 54 a, err := aeron.Connect(ctx) 55 if err != nil { 56 logger.Fatalf("Failed to connect to media driver: %s\n", err.Error()) 57 } 58 defer a.Close() 59 60 subscription, err := a.AddSubscription(*examples.PingPongConfig.PongChannel, int32(*examples.PingPongConfig.PongStreamID)) 61 if err != nil { 62 logger.Fatal(err) 63 } 64 defer subscription.Close() 65 logger.Infof("Subscription found %v", subscription) 66 67 publication, err := a.AddPublication(*examples.PingPongConfig.PingChannel, int32(*examples.PingPongConfig.PingStreamID)) 68 if err != nil { 69 logger.Fatal(err) 70 } 71 defer publication.Close() 72 logger.Infof("Publication found %v", publication) 73 74 for !publication.IsConnected() { 75 logger.Debug("Publication isn't connected") 76 time.Sleep(time.Millisecond * 300) 77 } 78 logger.Info("Publication connected") 79 80 if *examples.ExamplesConfig.ProfilerEnabled { 81 fname := fmt.Sprintf("ping-%d.pprof", time.Now().Unix()) 82 logger.Infof("Profiling enabled. Will use: %s", fname) 83 f, err := os.Create(fname) 84 if err == nil { 85 pprof.StartCPUProfile(f) 86 defer pprof.StopCPUProfile() 87 } else { 88 logger.Errorf("Failed to create profile file with %v", err) 89 } 90 } 91 92 hist := hdrhistogram.New(1, 1000000000, 3) 93 94 handler := func(buffer *atomic.Buffer, offset int32, length int32, header *logbuffer.Header) { 95 sent := buffer.GetInt64(offset) 96 now := time.Now().UnixNano() 97 98 hist.RecordValue(now - sent) 99 100 if logger.IsEnabledFor(logging.DEBUG) { 101 logger.Debugf("Received message at offset %d, length %d, position %d, termId %d, frame len %d", 102 offset, length, header.Offset(), header.TermId(), header.FrameLength()) 103 } 104 } 105 106 srcBuffer := atomic.MakeBuffer(make([]byte, *examples.ExamplesConfig.Size)) 107 108 warmupIt := 1000 109 logger.Infof("Sending %d messages of %d bytes for warmup", warmupIt, srcBuffer.Capacity()) 110 for i := 0; i < warmupIt; i++ { 111 now := time.Now().UnixNano() 112 srcBuffer.PutInt64(0, now) 113 114 for true { 115 ret := publication.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil) 116 if ret > 0 { 117 break 118 } else { 119 panic(fmt.Sprintf("Failed to offer message of %d bytes due to %d", srcBuffer.Capacity(), ret)) 120 } 121 } 122 123 for true { 124 ret := subscription.Poll(handler, 10) 125 if ret > 0 { 126 break 127 } else if ret < 0 { 128 panic(fmt.Sprintf("Failed to poll due to %d", ret)) 129 } 130 } 131 } 132 hist.Reset() 133 134 cnt := atomic.Int{} 135 136 logger.Infof("Sending %d messages of %d bytes", *examples.ExamplesConfig.Messages, srcBuffer.Capacity()) 137 for ; int(cnt.Get()) < *examples.ExamplesConfig.Messages; cnt.Add(1) { 138 now := time.Now().UnixNano() 139 srcBuffer.PutInt64(0, now) 140 141 for publication.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil) < 0 { 142 } 143 144 for subscription.Poll(handler, 10) <= 0 { 145 } 146 } 147 148 OutputPercentileDistribution(os.Stdout, hist, 1000.0) 149 } 150 151 func OutputPercentileDistribution(out io.Writer, h *hdrhistogram.Histogram, scalingFactor float64) { 152 153 fmt.Print("Value Percentile TotalCount 1/(1-Percentile)\n\n") 154 155 //Value Percentile TotalCount 1/(1-Percentile) 156 for _, b := range h.CumulativeDistribution() { 157 pct := b.Quantile / 100.0 158 io.WriteString(out, fmt.Sprintf("%12.3f %2.12f %10d %14.2f\n", 159 float64(b.ValueAt)/scalingFactor, 160 pct, 161 b.Count, 162 1/(1-pct))) 163 } 164 165 io.WriteString(out, fmt.Sprintf("#[Mean = %12.3f, StdDeviation = %12.3f]\n", 166 h.Mean()/scalingFactor, 167 h.StdDev()/scalingFactor)) 168 io.WriteString(out, fmt.Sprintf("#[Max = %12.3f, Total count = %12d]\n", 169 float64(h.Max())/scalingFactor, 170 h.TotalCount())) 171 }