github.com/searKing/golang/go@v1.2.117/time/rate/example_test.go (about)

     1  package rate_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"runtime"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/searKing/golang/go/time/rate"
    12  )
    13  
    14  func ExampleNewReorderBuffer() {
    15  	const n = 10
    16  	// See https://web.archive.org/web/20040724215416/http://lgjohn.okstate.edu/6253/lectures/reorder.pdf for more about Reorder buffer.
    17  	limiter := rate.NewReorderBuffer()
    18  	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
    19  	defer cancel()
    20  
    21  	var wg sync.WaitGroup
    22  
    23  	for i := 0; i < n; i++ {
    24  		i := i
    25  
    26  		// Allocate: The dispatch stage reserves space in the reorder buffer for instructions in program order.
    27  		r := limiter.Reserve(ctx)
    28  
    29  		wg.Add(1)
    30  		go func() {
    31  			defer wg.Done()
    32  			// Execute out of order
    33  			runtime.Gosched() // Increase probability of a race for out-of-order mock
    34  			//fmt.Printf("%03d Execute out of order\n", i)
    35  
    36  			defer r.PutToken()
    37  			//fmt.Printf("%03d Wait until in order\n", i)
    38  			// Wait: The complete stage must wait for instructions to finish execution.
    39  			err := r.Wait(ctx) // Commit in order
    40  			if err != nil {
    41  				fmt.Printf("err: %s\n", err.Error())
    42  				return
    43  			}
    44  			// Complete: Finished instructions are allowed to write results in order into the architected registers.
    45  			fmt.Printf("%03d Complete in order\n", i)
    46  		}()
    47  	}
    48  	wg.Wait()
    49  	// Output:
    50  	// 000 Complete in order
    51  	// 001 Complete in order
    52  	// 002 Complete in order
    53  	// 003 Complete in order
    54  	// 004 Complete in order
    55  	// 005 Complete in order
    56  	// 006 Complete in order
    57  	// 007 Complete in order
    58  	// 008 Complete in order
    59  	// 009 Complete in order
    60  
    61  }
    62  
    63  func ExampleNewFullBurstLimiter() {
    64  	const (
    65  		burst = 3
    66  	)
    67  	limiter := rate.NewFullBurstLimiter(burst)
    68  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    69  	defer cancel()
    70  
    71  	// expect dropped, as limiter is initialized with full tokens(3)
    72  	limiter.PutToken()
    73  
    74  	for i := 0; ; i++ {
    75  		// fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339))
    76  		fmt.Printf("Wait %03d, tokens left: %d\n", i, limiter.Tokens())
    77  		err := limiter.Wait(ctx)
    78  		if err != nil {
    79  			fmt.Printf("err: %s\n", err.Error())
    80  			return
    81  		}
    82  		fmt.Printf("Got %03d, tokens left: %d\n", i, limiter.Tokens())
    83  
    84  		// actor mocked by gc
    85  		runtime.GC()
    86  
    87  		if i == 0 {
    88  			// refill one token
    89  			limiter.PutToken()
    90  		}
    91  	}
    92  	// Output:
    93  	// Wait 000, tokens left: 3
    94  	// Got 000, tokens left: 2
    95  	// Wait 001, tokens left: 3
    96  	// Got 001, tokens left: 2
    97  	// Wait 002, tokens left: 2
    98  	// Got 002, tokens left: 1
    99  	// Wait 003, tokens left: 1
   100  	// Got 003, tokens left: 0
   101  	// Wait 004, tokens left: 0
   102  	// err: context deadline exceeded
   103  }
   104  
   105  func ExampleNewEmptyBurstLimiter() {
   106  	const (
   107  		burst       = 3
   108  		concurrency = 2
   109  	)
   110  	limiter := rate.NewEmptyBurstLimiter(burst)
   111  	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
   112  	defer cancel()
   113  
   114  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   115  
   116  	// expect not allowed, as limiter is initialized with empty tokens(0)
   117  	if limiter.Allow() {
   118  		fmt.Printf("allow passed\n")
   119  	} else {
   120  		fmt.Printf("allow refused\n")
   121  	}
   122  	// fill one token
   123  	limiter.PutToken()
   124  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   125  
   126  	// expect allowed, as limiter is filled with one token(1)
   127  	if limiter.Allow() {
   128  		fmt.Printf("allow passed\n")
   129  	} else {
   130  		fmt.Printf("allow refused\n")
   131  	}
   132  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   133  
   134  	var mu sync.Mutex
   135  	var wg sync.WaitGroup
   136  	for i := 0; i < concurrency; i++ {
   137  		wg.Add(1)
   138  		go func() {
   139  			defer wg.Done()
   140  			// fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339))
   141  			mu.Lock()
   142  			fmt.Printf("Wait 1 Token, tokens left: %d\n", limiter.Tokens())
   143  			mu.Unlock()
   144  			err := limiter.Wait(ctx)
   145  			if err != nil {
   146  				mu.Lock()
   147  				fmt.Printf("err: %s\n", err.Error())
   148  				mu.Unlock()
   149  				return
   150  			}
   151  
   152  			mu.Lock()
   153  			fmt.Printf("Got 1 Token, tokens left: %d\n", limiter.Tokens())
   154  			mu.Unlock()
   155  		}()
   156  	}
   157  
   158  	time.Sleep(10 * time.Millisecond)
   159  	for i := 0; i < concurrency; i++ {
   160  		time.Sleep(10 * time.Millisecond)
   161  		mu.Lock()
   162  		fmt.Printf("PutToken #%d: before tokens left: %d\n", i, limiter.Tokens())
   163  		// fill one token
   164  		limiter.PutToken()
   165  		fmt.Printf("PutToken #%d: after tokens left: %d\n", i, limiter.Tokens())
   166  		mu.Unlock()
   167  	}
   168  	wg.Wait()
   169  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   170  
   171  	// expect allowed, as limiter is filled with one token(1)
   172  	if limiter.Allow() {
   173  		fmt.Printf("allow passed\n")
   174  	} else {
   175  		fmt.Printf("allow refused\n")
   176  	}
   177  	fmt.Printf("tokens left: %d\n", limiter.Tokens())
   178  
   179  	// expect not allowed, as limiter is initialized with empty tokens(0)
   180  	if limiter.Allow() {
   181  		fmt.Printf("allow passed\n")
   182  	} else {
   183  		fmt.Printf("allow refused\n")
   184  	}
   185  	// Output:
   186  	// tokens left: 0
   187  	// allow refused
   188  	// tokens left: 1
   189  	// allow passed
   190  	// tokens left: 0
   191  	// Wait 1 Token, tokens left: 0
   192  	// Wait 1 Token, tokens left: 0
   193  	// PutToken #0: before tokens left: 0
   194  	// PutToken #0: after tokens left: 0
   195  	// Got 1 Token, tokens left: 0
   196  	// PutToken #1: before tokens left: 0
   197  	// PutToken #1: after tokens left: 0
   198  	// Got 1 Token, tokens left: 0
   199  	// tokens left: 0
   200  	// allow refused
   201  	// tokens left: 0
   202  	// allow refused
   203  }
   204  
   205  func ExampleBurstLimiter_Reserve() {
   206  	const (
   207  		burst = 1
   208  		n     = 10
   209  	)
   210  	limiter := rate.NewFullBurstLimiter(burst)
   211  	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
   212  	defer cancel()
   213  
   214  	// expect dropped, as limiter is initialized with full tokens(1)
   215  	limiter.PutToken()
   216  
   217  	type Reservation struct {
   218  		index int
   219  		r     *rate.Reservation
   220  	}
   221  
   222  	var mu sync.Mutex
   223  	var wg sync.WaitGroup
   224  	var rs []*Reservation
   225  
   226  	for i := 0; i < n; i++ {
   227  		// fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339))
   228  		// fmt.Printf("Reserve %03d\n", i)
   229  		r := &Reservation{
   230  			index: i,
   231  			r:     limiter.Reserve(ctx),
   232  		}
   233  		if i%2 == rand.Intn(2)%2 {
   234  			rs = append(rs, r)
   235  			continue
   236  		}
   237  		wg.Add(1)
   238  		go func() {
   239  			defer wg.Done()
   240  			// fmt.Printf("%03d %s\n", r.index, time.Now().Format(time.RFC3339))
   241  			// fmt.Printf("Wait %03d\n", r.index)
   242  			err := r.r.Wait(ctx)
   243  			if err != nil {
   244  				mu.Lock()
   245  				fmt.Printf("err: %s\n", err.Error())
   246  				mu.Unlock()
   247  			}
   248  
   249  			mu.Lock()
   250  			fmt.Printf("%03d Got 1 Token, tokens left: %d\n", r.index, limiter.Tokens())
   251  			mu.Unlock()
   252  			r.r.PutToken()
   253  		}()
   254  	}
   255  
   256  	for i := 0; i < len(rs); i++ {
   257  		r := rs[i]
   258  		wg.Add(1)
   259  		go func() {
   260  			defer wg.Done()
   261  			// fmt.Printf("%03d %s\n", r.index, time.Now().Format(time.RFC3339))
   262  			// fmt.Printf("Wait %03d\n", r.index)
   263  			err := r.r.Wait(ctx)
   264  			if err != nil {
   265  				mu.Lock()
   266  				fmt.Printf("err: %s\n", err.Error())
   267  				mu.Unlock()
   268  			}
   269  
   270  			mu.Lock()
   271  			fmt.Printf("%03d Got 1 Token, tokens left: %d\n", r.index, limiter.Tokens())
   272  			mu.Unlock()
   273  			r.r.PutToken()
   274  		}()
   275  	}
   276  	wg.Wait()
   277  	// Output:
   278  	// 000 Got 1 Token, tokens left: 0
   279  	// 001 Got 1 Token, tokens left: 0
   280  	// 002 Got 1 Token, tokens left: 0
   281  	// 003 Got 1 Token, tokens left: 0
   282  	// 004 Got 1 Token, tokens left: 0
   283  	// 005 Got 1 Token, tokens left: 0
   284  	// 006 Got 1 Token, tokens left: 0
   285  	// 007 Got 1 Token, tokens left: 0
   286  	// 008 Got 1 Token, tokens left: 0
   287  	// 009 Got 1 Token, tokens left: 0
   288  
   289  }