github.com/ii64/gouring@v0.4.1/bench/perf/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"runtime"
     8  	"runtime/pprof"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/ii64/gouring"
    13  )
    14  
    15  var fs = flag.NewFlagSet("perf", flag.ExitOnError)
    16  
    17  var (
    18  	entries      uint
    19  	sqPoll       bool
    20  	sqThreadCpu  uint
    21  	sqThreadIdle uint
    22  
    23  	N    uint
    24  	noti uint
    25  
    26  	pprofCpuFilename = "pprof.cpu"
    27  )
    28  
    29  func init() {
    30  	fs.UintVar(&entries, "entries", 256, "Entries")
    31  	fs.BoolVar(&sqPoll, "sqpoll", false, "Enable SQPOLL")
    32  	fs.UintVar(&sqThreadCpu, "sqthreadcpu", 16, "SQ Thread CPU")
    33  	fs.UintVar(&sqThreadIdle, "sqthreadidle", 10_000, "SQ Thread idle") // milliseconds
    34  
    35  	fs.UintVar(&N, "n", 10_000, "N times")
    36  	fs.UintVar(&noti, "noti", 10_000, "Notify per attempt N")
    37  
    38  	fs.StringVar(&pprofCpuFilename, "pprofCpu", pprofCpuFilename, "pprof cpu output file")
    39  }
    40  
    41  func main() {
    42  	err := fs.Parse(os.Args[1:])
    43  	if err != nil {
    44  		panic(err)
    45  	}
    46  
    47  	// check entries size
    48  	if entries > uint(^uint32(0)) {
    49  		panic("entries overflow.")
    50  	}
    51  
    52  	params := &gouring.IoUringParams{}
    53  	if sqPoll {
    54  		params.Flags |= gouring.IORING_SETUP_SQPOLL
    55  		params.SqThreadCpu = uint32(sqThreadCpu)
    56  		params.SqThreadIdle = uint32(sqThreadIdle)
    57  	}
    58  
    59  	h, err := gouring.NewWithParams(uint32(entries), params)
    60  	if err != nil {
    61  		panic(err)
    62  	}
    63  	defer h.Close()
    64  
    65  	f, err := os.Create(pprofCpuFilename)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  
    70  	fmt.Println("performing...")
    71  
    72  	pprof.StartCPUProfile(f)
    73  	defer pprof.StopCPUProfile()
    74  
    75  	var i, j uint
    76  	var sqe *gouring.IoUringSqe
    77  	var cqe *gouring.IoUringCqe
    78  	var submitted int
    79  
    80  	startTime := time.Now()
    81  	for i = 0; i < N; i++ {
    82  		if i%noti == 0 { // notify
    83  			fmt.Printf("n:%d e:%s\n", j, time.Now().Sub(startTime))
    84  		}
    85  
    86  		for j = 0; j < entries; j++ {
    87  			for {
    88  				// sqe could be nil if SQ is already full so we spin until we got one
    89  				sqe = h.GetSqe()
    90  				if sqe != nil {
    91  					break
    92  				}
    93  				runtime.Gosched()
    94  			}
    95  			gouring.PrepNop(sqe)
    96  			sqe.UserData.SetUint64(uint64(i + j))
    97  		}
    98  		submitted, err = h.Submit()
    99  		if err != nil {
   100  			panic(err)
   101  		}
   102  
   103  		if i%noti == 0 { // notify
   104  			fmt.Printf(" >> submitted %d\n", submitted)
   105  		}
   106  
   107  		for j = 0; j < entries; j++ {
   108  			err = h.WaitCqe(&cqe)
   109  			if err == syscall.EINTR {
   110  				continue
   111  			}
   112  			if err != nil {
   113  				panic(err)
   114  			}
   115  			if cqe == nil {
   116  				panic("cqe is nil!")
   117  			}
   118  			if cqe.Res < 0 {
   119  				panic(syscall.Errno(-cqe.Res))
   120  			}
   121  
   122  			h.SeenCqe(cqe)
   123  		}
   124  	}
   125  	_ = submitted
   126  	_ = err
   127  }