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  }