| [62402e2] | 1 | package main
 | 
|---|
 | 2 | 
 | 
|---|
 | 3 | import (
 | 
|---|
 | 4 |         "flag"
 | 
|---|
 | 5 |         "fmt"
 | 
|---|
 | 6 |         "math/rand"
 | 
|---|
| [160ee4c] | 7 |         "runtime"
 | 
|---|
| [62402e2] | 8 |         "sync"
 | 
|---|
 | 9 |         "sync/atomic"
 | 
|---|
 | 10 |         "time"
 | 
|---|
 | 11 |         "golang.org/x/text/language"
 | 
|---|
 | 12 |         "golang.org/x/text/message"
 | 
|---|
 | 13 | )
 | 
|---|
 | 14 | 
 | 
|---|
| [160ee4c] | 15 | func churner(result chan uint64, start *sync.WaitGroup, spots [] chan struct {}) {
 | 
|---|
| [62402e2] | 16 |         s := rand.NewSource(time.Now().UnixNano())
 | 
|---|
 | 17 |         rng := rand.New(s)
 | 
|---|
 | 18 | 
 | 
|---|
 | 19 |         count := uint64(0)
 | 
|---|
 | 20 |         start.Wait()
 | 
|---|
 | 21 |         for true {
 | 
|---|
 | 22 | 
 | 
|---|
 | 23 |                 sem := spots[ rng.Intn(100) % len(spots) ];
 | 
|---|
| [160ee4c] | 24 |                 sem <- (struct {}{})
 | 
|---|
 | 25 |                 <- sem;
 | 
|---|
| [62402e2] | 26 | 
 | 
|---|
 | 27 |                 count += 1
 | 
|---|
 | 28 |                 if  clock_mode && atomic.LoadInt32(&stop) == 1 { break }
 | 
|---|
 | 29 |                 if !clock_mode && count >= stop_count { break }
 | 
|---|
 | 30 |         }
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 |         atomic.AddInt64(&threads_left, -1);
 | 
|---|
 | 33 |         result <- count
 | 
|---|
 | 34 | }
 | 
|---|
 | 35 | 
 | 
|---|
 | 36 | func main() {
 | 
|---|
 | 37 |         var spot_cnt int
 | 
|---|
 | 38 | 
 | 
|---|
 | 39 |         spot_cntOpt := flag.Int("s", 1, "Number of spots in the system")
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 |         bench_init()
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 |         spot_cnt = *spot_cntOpt
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 |         threads_left = int64(nthreads)
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 |         result := make(chan uint64)
 | 
|---|
 | 48 |         var wg sync.WaitGroup
 | 
|---|
 | 49 |         wg.Add(1)
 | 
|---|
 | 50 | 
 | 
|---|
| [160ee4c] | 51 |         spots := make([] chan struct {}, spot_cnt)
 | 
|---|
| [62402e2] | 52 |         for i := range spots {
 | 
|---|
| [160ee4c] | 53 |                 spots[i] = make(chan struct {}, 1)
 | 
|---|
| [62402e2] | 54 |         }
 | 
|---|
 | 55 | 
 | 
|---|
 | 56 |         for i := 0; i < nthreads; i++ {
 | 
|---|
| [160ee4c] | 57 |                 go churner(result, &wg, spots)
 | 
|---|
| [62402e2] | 58 |         }
 | 
|---|
 | 59 |         fmt.Printf("Starting\n");
 | 
|---|
 | 60 |         atomic.StoreInt32(&stop, 0)
 | 
|---|
 | 61 |         start := time.Now()
 | 
|---|
 | 62 |         wg.Done();
 | 
|---|
 | 63 |         wait(start, true);
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 |         atomic.StoreInt32(&stop, 1)
 | 
|---|
 | 66 |         end := time.Now()
 | 
|---|
 | 67 |         duration := end.Sub(start)
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 |         fmt.Printf("\nDone\n")
 | 
|---|
 | 70 | 
 | 
|---|
| [160ee4c] | 71 |         for atomic.LoadInt64(&threads_left) != 0 {
 | 
|---|
 | 72 |                 for i := range spots {
 | 
|---|
| [ee0176b] | 73 |                         select {
 | 
|---|
 | 74 |                         case <- spots[i]:
 | 
|---|
 | 75 |                         default:
 | 
|---|
 | 76 |                         }
 | 
|---|
| [160ee4c] | 77 |                         select {
 | 
|---|
 | 78 |                         case spots[i] <- (struct {}{}):
 | 
|---|
 | 79 |                         default:
 | 
|---|
 | 80 |                         }
 | 
|---|
 | 81 |                         runtime.Gosched()
 | 
|---|
 | 82 |                 }
 | 
|---|
| [62402e2] | 83 |         }
 | 
|---|
 | 84 | 
 | 
|---|
 | 85 |         global_counter := uint64(0)
 | 
|---|
 | 86 |         for i := 0; i < nthreads; i++ {
 | 
|---|
 | 87 |                 global_counter += <- result
 | 
|---|
 | 88 |         }
 | 
|---|
 | 89 | 
 | 
|---|
 | 90 |         p := message.NewPrinter(language.English)
 | 
|---|
 | 91 |         p.Printf("Duration (ms)        : %d\n", duration.Milliseconds())
 | 
|---|
 | 92 |         p.Printf("Number of processors : %d\n", nprocs);
 | 
|---|
 | 93 |         p.Printf("Number of threads    : %d\n", nthreads);
 | 
|---|
 | 94 |         p.Printf("Number of spots      : %d\n", spot_cnt);
 | 
|---|
 | 95 |         p.Printf("Total Operations(ops): %15d\n", global_counter);
 | 
|---|
 | 96 |         // p.Printf("Total blocks         : %15d\n", global_blocks);
 | 
|---|
 | 97 |         p.Printf("Ops per second       : %18.2f\n", float64(global_counter) / duration.Seconds());
 | 
|---|
 | 98 |         p.Printf("ns per ops           : %18.2f\n", float64(duration.Nanoseconds()) / float64(global_counter))
 | 
|---|
 | 99 |         p.Printf("Ops per threads      : %15d\n", global_counter / uint64(nthreads))
 | 
|---|
 | 100 |         p.Printf("Ops per procs        : %15d\n", global_counter / uint64(nprocs))
 | 
|---|
 | 101 |         p.Printf("Ops/sec/procs        : %18.2f\n", (float64(global_counter) / float64(nprocs)) / duration.Seconds())
 | 
|---|
 | 102 |         p.Printf("ns per ops/procs     : %18.2f\n", float64(duration.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
 | 
|---|
| [ee0176b] | 103 | }
 | 
|---|