github.com/bruceshao/lockfree@v1.1.3-0.20230816090528-e89824c0a6e9/example/perfect/main.go (about)

     1  /*
     2   * Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   */
     7  
     8  package main
     9  
    10  import (
    11  	"fmt"
    12  	"github.com/bruceshao/lockfree"
    13  	"os"
    14  	"runtime/pprof"
    15  	"sync"
    16  	"sync/atomic"
    17  	"time"
    18  )
    19  
    20  var (
    21  	goSize      = 10000
    22  	sizePerGo   = 10000
    23  	cap         = 1024 * 1024
    24  	timeAnalyse = false
    25  )
    26  
    27  func main() {
    28  	f, _ := os.OpenFile("cpu.pprof", os.O_CREATE|os.O_RDWR, 0644)
    29  	defer f.Close()
    30  	pprof.StartCPUProfile(f)
    31  	defer pprof.StopCPUProfile()
    32  	// 启动命令: .exe [all/lockfree/chan] [time]
    33  	arg := "all"
    34  	if len(os.Args) > 1 {
    35  		arg = os.Args[1]
    36  	}
    37  	if len(os.Args) > 2 {
    38  		timeAnalyse = true
    39  	}
    40  	if arg == "all" {
    41  		fmt.Println("start lockfree and channel test")
    42  		// 表示全部启动
    43  		var wg sync.WaitGroup
    44  		wg.Add(2)
    45  		go func() {
    46  			defer wg.Done()
    47  			lockfreeMain()
    48  		}()
    49  		go func() {
    50  			defer wg.Done()
    51  			chanMain()
    52  		}()
    53  		wg.Wait()
    54  	} else if arg == "chan" {
    55  		fmt.Println("start channel test")
    56  		// 表示启动chan
    57  		var wg sync.WaitGroup
    58  		wg.Add(1)
    59  		go func() {
    60  			defer wg.Done()
    61  			chanMain()
    62  		}()
    63  		wg.Wait()
    64  	} else if arg == "lockfree" {
    65  		fmt.Println("start lockfree test")
    66  		// 表示启动lockfree
    67  		var wg sync.WaitGroup
    68  		wg.Add(1)
    69  		go func() {
    70  			defer wg.Done()
    71  			lockfreeMain()
    72  		}()
    73  		wg.Wait()
    74  	}
    75  	fmt.Println("all queue is over")
    76  }
    77  
    78  func lockfreeMain() {
    79  	var (
    80  		t1_10us     = uint64(0) // 1-10微秒
    81  		t10_100us   = uint64(0) // 10-100微秒
    82  		t100_1000us = uint64(0) // 100-1000微秒
    83  		t1_10ms     = uint64(0) // 1-10毫秒
    84  		t10_100ms   = uint64(0) // 10-100毫秒
    85  		t100_ms     = uint64(0) // 大于100毫秒
    86  		slower      = uint64(0)
    87  	)
    88  	// 创建事件处理器
    89  	eh := &longEventHandler[uint64]{}
    90  	// 创建消费端串行处理的Lockfree
    91  	lf := lockfree.NewLockfree[uint64](cap, eh, lockfree.NewSleepBlockStrategy(time.Millisecond))
    92  	// 启动Lockfree
    93  	if err := lf.Start(); err != nil {
    94  		panic(err)
    95  	}
    96  	// lockfree计时
    97  	ts := time.Now()
    98  	// 获取生产者对象
    99  	producer := lf.Producer()
   100  	var wg sync.WaitGroup
   101  	wg.Add(goSize)
   102  	for i := 0; i < goSize; i++ {
   103  		go func(start int) {
   104  			if timeAnalyse {
   105  				for j := 0; j < sizePerGo; j++ {
   106  					//写入数据
   107  					tb := time.Now()
   108  					err := producer.Write(uint64(start*sizePerGo + j + 1))
   109  					tl := time.Since(tb)
   110  					ms := tl.Microseconds()
   111  					if ms > 1 {
   112  						atomic.AddUint64(&slower, 1)
   113  						if ms < 10 { // t1_10us
   114  							atomic.AddUint64(&t1_10us, 1)
   115  						} else if ms < 100 {
   116  							atomic.AddUint64(&t10_100us, 1)
   117  						} else if ms < 1000 {
   118  							atomic.AddUint64(&t100_1000us, 1)
   119  						} else if ms < 10000 {
   120  							atomic.AddUint64(&t1_10ms, 1)
   121  						} else if ms < 100000 {
   122  							atomic.AddUint64(&t10_100ms, 1)
   123  						} else {
   124  							atomic.AddUint64(&t100_ms, 1)
   125  						}
   126  					}
   127  					if err != nil {
   128  						panic(err)
   129  					}
   130  				}
   131  			} else {
   132  				for j := 0; j < sizePerGo; j++ {
   133  					err := producer.Write(uint64(start*sizePerGo + j + 1))
   134  					if err != nil {
   135  						panic(err)
   136  					}
   137  				}
   138  			}
   139  			wg.Done()
   140  		}(i)
   141  	}
   142  	wg.Wait()
   143  	fmt.Println("===== lockfree[", time.Now().Sub(ts), "] =====")
   144  	fmt.Println("----- lockfree write complete -----")
   145  	time.Sleep(3 * time.Second)
   146  	// 关闭Lockfree
   147  	lf.Close()
   148  	if timeAnalyse {
   149  		fmt.Printf("lockfree slow ratio = %.2f \n", float64(slower)*100.0/float64(goSize*sizePerGo))
   150  		fmt.Printf("lockfree quick ratio = %.2f \n", float64(goSize*sizePerGo-int(slower))*100.0/float64(goSize*sizePerGo))
   151  		fmt.Printf("lockfree [<1us][%d] \n", uint64(goSize*sizePerGo)-slower)
   152  		fmt.Printf("lockfree [1-10us][%d] \n", t1_10us)
   153  		fmt.Printf("lockfree [10-100us][%d] \n", t10_100us)
   154  		fmt.Printf("lockfree [100-1000us][%d] \n", t100_1000us)
   155  		fmt.Printf("lockfree [1-10ms][%d] \n", t1_10ms)
   156  		fmt.Printf("lockfree [10-100ms][%d] \n", t10_100ms)
   157  		fmt.Printf("lockfree [>100ms][%d] \n", t100_ms)
   158  	}
   159  }
   160  
   161  func chanMain() {
   162  	var (
   163  		t1_10us     = uint64(0) // 1-10微秒
   164  		t10_100us   = uint64(0) // 10-100微秒
   165  		t100_1000us = uint64(0) // 100-1000微秒
   166  		t1_10ms     = uint64(0) // 1-10毫秒
   167  		t10_100ms   = uint64(0) // 10-100毫秒
   168  		t100_ms     = uint64(0) // 大于100毫秒
   169  		slower      = uint64(0)
   170  	)
   171  	c := make(chan uint64, cap)
   172  	// 启动监听协程
   173  	go func() {
   174  		for {
   175  			x, ok := <-c
   176  			if !ok {
   177  				return
   178  			}
   179  			if x%10000000 == 0 {
   180  				fmt.Println("chan [", x, "]")
   181  			}
   182  		}
   183  	}()
   184  	// lockfree计时
   185  	ts := time.Now()
   186  	// 开始写入
   187  	var wg sync.WaitGroup
   188  	wg.Add(goSize)
   189  	for i := 0; i < goSize; i++ {
   190  		go func(start int) {
   191  			if timeAnalyse {
   192  				for j := 0; j < sizePerGo; j++ {
   193  					//写入数据
   194  					tb := time.Now()
   195  					c <- uint64(start*sizePerGo + j + 1)
   196  					tl := time.Since(tb)
   197  					ms := tl.Microseconds()
   198  					if ms > 1 {
   199  						atomic.AddUint64(&slower, 1)
   200  						if ms < 10 { // t1_10us
   201  							atomic.AddUint64(&t1_10us, 1)
   202  						} else if ms < 100 {
   203  							atomic.AddUint64(&t10_100us, 1)
   204  						} else if ms < 1000 {
   205  							atomic.AddUint64(&t100_1000us, 1)
   206  						} else if ms < 10000 {
   207  							atomic.AddUint64(&t1_10ms, 1)
   208  						} else if ms < 100000 {
   209  							atomic.AddUint64(&t10_100ms, 1)
   210  						} else {
   211  							atomic.AddUint64(&t100_ms, 1)
   212  						}
   213  					}
   214  				}
   215  			} else {
   216  				for j := 0; j < sizePerGo; j++ {
   217  					//写入数据
   218  					c <- uint64(start*sizePerGo + j + 1)
   219  				}
   220  			}
   221  			wg.Done()
   222  		}(i)
   223  	}
   224  	wg.Wait()
   225  	fmt.Println("=====channel[", time.Now().Sub(ts), "]=====")
   226  	fmt.Println("----- channel write complete -----")
   227  	time.Sleep(3 * time.Second)
   228  	// 关闭chan
   229  	close(c)
   230  	if timeAnalyse {
   231  		fmt.Printf("channel slow ratio = %.2f \n", float64(slower)*100.0/float64(goSize*sizePerGo))
   232  		fmt.Printf("channel  quick ratio = %.2f \n", float64(goSize*sizePerGo-int(slower))*100.0/float64(goSize*sizePerGo))
   233  		fmt.Printf("channel [<1us][%d] \n", uint64(goSize*sizePerGo)-slower)
   234  		fmt.Printf("channel [1-10us][%d] \n", t1_10us)
   235  		fmt.Printf("channel [10-100us][%d] \n", t10_100us)
   236  		fmt.Printf("channel [100-1000us][%d] \n", t100_1000us)
   237  		fmt.Printf("channel [1-10ms][%d] \n", t1_10ms)
   238  		fmt.Printf("channel [10-100ms][%d] \n", t10_100ms)
   239  		fmt.Printf("channel [>100ms][%d] \n", t100_ms)
   240  	}
   241  }
   242  
   243  type longEventHandler[T uint64] struct {
   244  }
   245  
   246  func (h *longEventHandler[T]) OnEvent(v uint64) {
   247  	if v%10000000 == 0 {
   248  		fmt.Println("lockfree [", v, "]")
   249  	}
   250  }