Consistently use Sleep in state-management examples
Consistently use `time.Sleep`, instead of `runtime.Gosched`, to ensure all goroutines can make progress. `Gosched` wasn't working in the playground (ref #149). Also stop trying to compare operation rates. This was tenuous given e.g. how short the programs ran for, and with the `Sleep`s we now expect the rates to be similar anyways.
This commit is contained in:
parent
94cba6875d
commit
6a58750728
@ -10,7 +10,6 @@ package main
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
import "time"
|
import "time"
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
import "runtime"
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
@ -30,8 +29,8 @@ func main() {
|
|||||||
// `&` syntax.
|
// `&` syntax.
|
||||||
atomic.AddUint64(&ops, 1)
|
atomic.AddUint64(&ops, 1)
|
||||||
|
|
||||||
// Allow other goroutines to proceed.
|
// Wait a bit between increments.
|
||||||
runtime.Gosched()
|
time.Sleep(time.Millisecond)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
ddfef8425eef64cfcb82799c9bddca4bfa9bbd29
|
ce8821f1f4fd99d554ad6cde52403dd3b69bb70a
|
||||||
2h8nvrnaHP
|
8p48eFFxDZ
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Running the program shows that we executed about
|
# Running the program shows that we executed about
|
||||||
# 40,000 operations.
|
# 40,000 operations.
|
||||||
$ go run atomic-counters.go
|
$ go run atomic-counters.go
|
||||||
ops: 40200
|
ops: 41419
|
||||||
|
|
||||||
# Next we'll look at mutexes, another tool for managing
|
# Next we'll look at mutexes, another tool for managing
|
||||||
# state.
|
# state.
|
||||||
|
@ -8,7 +8,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"runtime"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -22,13 +21,14 @@ func main() {
|
|||||||
// This `mutex` will synchronize access to `state`.
|
// This `mutex` will synchronize access to `state`.
|
||||||
var mutex = &sync.Mutex{}
|
var mutex = &sync.Mutex{}
|
||||||
|
|
||||||
// To compare the mutex-based approach with another
|
// We'll keep track of how many read and write
|
||||||
// we'll see later, `ops` will count how many
|
// operations we do.
|
||||||
// operations we perform against the state.
|
var readOps uint64 = 0
|
||||||
var ops int64 = 0
|
var writeOps uint64 = 0
|
||||||
|
|
||||||
// Here we start 100 goroutines to execute repeated
|
// Here we start 100 goroutines to execute repeated
|
||||||
// reads against the state.
|
// reads against the state, once per millisecond in
|
||||||
|
// each goroutine.
|
||||||
for r := 0; r < 100; r++ {
|
for r := 0; r < 100; r++ {
|
||||||
go func() {
|
go func() {
|
||||||
total := 0
|
total := 0
|
||||||
@ -39,22 +39,15 @@ func main() {
|
|||||||
// exclusive access to the `state`, read
|
// exclusive access to the `state`, read
|
||||||
// the value at the chosen key,
|
// the value at the chosen key,
|
||||||
// `Unlock()` the mutex, and increment
|
// `Unlock()` the mutex, and increment
|
||||||
// the `ops` count.
|
// the `readOps` count.
|
||||||
key := rand.Intn(5)
|
key := rand.Intn(5)
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
total += state[key]
|
total += state[key]
|
||||||
mutex.Unlock()
|
mutex.Unlock()
|
||||||
atomic.AddInt64(&ops, 1)
|
atomic.AddUint64(&readOps, 1)
|
||||||
|
|
||||||
// In order to ensure that this goroutine
|
// Wait a bit between reads.
|
||||||
// doesn't starve the scheduler, we explicitly
|
time.Sleep(time.Millisecond)
|
||||||
// yield after each operation with
|
|
||||||
// `runtime.Gosched()`. This yielding is
|
|
||||||
// handled automatically with e.g. every
|
|
||||||
// channel operation and for blocking
|
|
||||||
// calls like `time.Sleep`, but in this
|
|
||||||
// case we need to do it manually.
|
|
||||||
runtime.Gosched()
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -69,8 +62,8 @@ func main() {
|
|||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
state[key] = val
|
state[key] = val
|
||||||
mutex.Unlock()
|
mutex.Unlock()
|
||||||
atomic.AddInt64(&ops, 1)
|
atomic.AddUint64(&writeOps, 1)
|
||||||
runtime.Gosched()
|
time.Sleep(time.Millisecond)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -79,9 +72,11 @@ func main() {
|
|||||||
// `mutex` for a second.
|
// `mutex` for a second.
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
// Take and report a final operations count.
|
// Take and report final operation counts.
|
||||||
opsFinal := atomic.LoadInt64(&ops)
|
readOpsFinal := atomic.LoadUint64(&readOps)
|
||||||
fmt.Println("ops:", opsFinal)
|
fmt.Println("readOps:", readOpsFinal)
|
||||||
|
writeOpsFinal := atomic.LoadUint64(&writeOps)
|
||||||
|
fmt.Println("writeOps:", writeOpsFinal)
|
||||||
|
|
||||||
// With a final lock of `state`, show how it ended up.
|
// With a final lock of `state`, show how it ended up.
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
3ce8467418aa740ea6c930afac3985a943c76311
|
e82356cbb37143862b0a9bbc68856f4b272c4918
|
||||||
kZrod-Rkos
|
a9Wky7k-Bw
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
# Running the program shows that we executed about
|
# Running the program shows that we executed about
|
||||||
# 3,500,000 operations against our `mutex`-synchronized
|
# 90,000 total operations against our `mutex`-synchronized
|
||||||
# `state`.
|
# `state`.
|
||||||
$ go run mutexes.go
|
$ go run mutexes.go
|
||||||
ops: 3598302
|
readOps: 83285
|
||||||
state: map[1:38 4:98 2:23 3:85 0:44]
|
writeOps: 8320
|
||||||
|
state: map[1:97 4:53 0:33 2:15 3:2]
|
||||||
|
|
||||||
# Next we'll look at implementing this same state
|
# Next we'll look at implementing this same state
|
||||||
# management task using only goroutines and channels.
|
# management task using only goroutines and channels.
|
||||||
|
@ -37,7 +37,8 @@ type writeOp struct {
|
|||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
// As before we'll count how many operations we perform.
|
// As before we'll count how many operations we perform.
|
||||||
var ops int64 = 0
|
var readOps uint64 = 0
|
||||||
|
var writeOps uint64 = 0
|
||||||
|
|
||||||
// The `reads` and `writes` channels will be used by
|
// The `reads` and `writes` channels will be used by
|
||||||
// other goroutines to issue read and write requests,
|
// other goroutines to issue read and write requests,
|
||||||
@ -80,7 +81,8 @@ func main() {
|
|||||||
resp: make(chan int)}
|
resp: make(chan int)}
|
||||||
reads <- read
|
reads <- read
|
||||||
<-read.resp
|
<-read.resp
|
||||||
atomic.AddInt64(&ops, 1)
|
atomic.AddUint64(&readOps, 1)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -96,7 +98,8 @@ func main() {
|
|||||||
resp: make(chan bool)}
|
resp: make(chan bool)}
|
||||||
writes <- write
|
writes <- write
|
||||||
<-write.resp
|
<-write.resp
|
||||||
atomic.AddInt64(&ops, 1)
|
atomic.AddUint64(&writeOps, 1)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -104,7 +107,9 @@ func main() {
|
|||||||
// Let the goroutines work for a second.
|
// Let the goroutines work for a second.
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
// Finally, capture and report the `ops` count.
|
// Finally, capture and report the op counts.
|
||||||
opsFinal := atomic.LoadInt64(&ops)
|
readOpsFinal := atomic.LoadUint64(&readOps)
|
||||||
fmt.Println("ops:", opsFinal)
|
fmt.Println("readOps:", readOpsFinal)
|
||||||
|
writeOpsFinal := atomic.LoadUint64(&writeOps)
|
||||||
|
fmt.Println("writeOps:", writeOpsFinal)
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
603a70a77ed18db9da4f8c7911a92b87fd21400c
|
c306add52c0752f0b3099eb669364fc4bdb74be1
|
||||||
-WqmiTr6ek
|
P4SrrlosMp
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Running our program shows that the goroutine-based
|
# Running our program shows that the goroutine-based
|
||||||
# state management example achieves about 800,000
|
# state management example completes about 80,000
|
||||||
# operations per second.
|
# total operations.
|
||||||
$ go run stateful-goroutines.go
|
$ go run stateful-goroutines.go
|
||||||
ops: 807434
|
readOps: 71708
|
||||||
|
writeOps: 7177
|
||||||
|
|
||||||
# For this particular case the goroutine-based approach
|
# For this particular case the goroutine-based approach
|
||||||
# was a bit more involved than the mutex-based one. It
|
# was a bit more involved than the mutex-based one. It
|
||||||
|
@ -44,7 +44,7 @@ counters</em> accessed by multiple goroutines.</p>
|
|||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
<a href="http://play.golang.org/p/2h8nvrnaHP"><img title="Run code" src="play.png" class="run" /></a>
|
<a href="http://play.golang.org/p/8p48eFFxDZ"><img title="Run code" src="play.png" class="run" /></a>
|
||||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
@ -60,7 +60,6 @@ counters</em> accessed by multiple goroutines.</p>
|
|||||||
<div class="highlight"><pre><span class="kn">import</span> <span class="s">"fmt"</span>
|
<div class="highlight"><pre><span class="kn">import</span> <span class="s">"fmt"</span>
|
||||||
<span class="kn">import</span> <span class="s">"time"</span>
|
<span class="kn">import</span> <span class="s">"time"</span>
|
||||||
<span class="kn">import</span> <span class="s">"sync/atomic"</span>
|
<span class="kn">import</span> <span class="s">"sync/atomic"</span>
|
||||||
<span class="kn">import</span> <span class="s">"runtime"</span>
|
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -127,12 +126,12 @@ address of our <code>ops</code> counter with the
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>Allow other goroutines to proceed.</p>
|
<p>Wait a bit between increments.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre> <span class="nx">runtime</span><span class="p">.</span><span class="nx">Gosched</span><span class="p">()</span>
|
<div class="highlight"><pre> <span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
<span class="p">}()</span>
|
<span class="p">}()</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
@ -187,7 +186,7 @@ fetch the value.</p>
|
|||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre><span class="gp">$</span> go run atomic-counters.go
|
<div class="highlight"><pre><span class="gp">$</span> go run atomic-counters.go
|
||||||
<span class="go">ops: 40200</span>
|
<span class="go">ops: 41419</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
@ -42,7 +42,7 @@ to safely access data across multiple goroutines.</p>
|
|||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
<a href="http://play.golang.org/p/kZrod-Rkos"><img title="Run code" src="play.png" class="run" /></a>
|
<a href="http://play.golang.org/p/a9Wky7k-Bw"><img title="Run code" src="play.png" class="run" /></a>
|
||||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
@ -58,7 +58,6 @@ to safely access data across multiple goroutines.</p>
|
|||||||
<div class="highlight"><pre><span class="kn">import</span> <span class="p">(</span>
|
<div class="highlight"><pre><span class="kn">import</span> <span class="p">(</span>
|
||||||
<span class="s">"fmt"</span>
|
<span class="s">"fmt"</span>
|
||||||
<span class="s">"math/rand"</span>
|
<span class="s">"math/rand"</span>
|
||||||
<span class="s">"runtime"</span>
|
|
||||||
<span class="s">"sync"</span>
|
<span class="s">"sync"</span>
|
||||||
<span class="s">"sync/atomic"</span>
|
<span class="s">"sync/atomic"</span>
|
||||||
<span class="s">"time"</span>
|
<span class="s">"time"</span>
|
||||||
@ -108,14 +107,14 @@ to safely access data across multiple goroutines.</p>
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>To compare the mutex-based approach with another
|
<p>We’ll keep track of how many read and write
|
||||||
we’ll see later, <code>ops</code> will count how many
|
operations we do.</p>
|
||||||
operations we perform against the state.</p>
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre> <span class="kd">var</span> <span class="nx">ops</span> <span class="kt">int64</span> <span class="p">=</span> <span class="mi">0</span>
|
<div class="highlight"><pre> <span class="kd">var</span> <span class="nx">readOps</span> <span class="kt">uint64</span> <span class="p">=</span> <span class="mi">0</span>
|
||||||
|
<span class="kd">var</span> <span class="nx">writeOps</span> <span class="kt">uint64</span> <span class="p">=</span> <span class="mi">0</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -124,7 +123,8 @@ operations we perform against the state.</p>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>Here we start 100 goroutines to execute repeated
|
<p>Here we start 100 goroutines to execute repeated
|
||||||
reads against the state.</p>
|
reads against the state, once per millisecond in
|
||||||
|
each goroutine.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
@ -145,7 +145,7 @@ reads against the state.</p>
|
|||||||
exclusive access to the <code>state</code>, read
|
exclusive access to the <code>state</code>, read
|
||||||
the value at the chosen key,
|
the value at the chosen key,
|
||||||
<code>Unlock()</code> the mutex, and increment
|
<code>Unlock()</code> the mutex, and increment
|
||||||
the <code>ops</code> count.</p>
|
the <code>readOps</code> count.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
@ -154,7 +154,7 @@ the <code>ops</code> count.</p>
|
|||||||
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span>
|
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span>
|
||||||
<span class="nx">total</span> <span class="o">+=</span> <span class="nx">state</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
<span class="nx">total</span> <span class="o">+=</span> <span class="nx">state</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||||
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
|
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
|
||||||
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddInt64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">readOps</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -162,19 +162,12 @@ the <code>ops</code> count.</p>
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>In order to ensure that this goroutine
|
<p>Wait a bit between reads.</p>
|
||||||
doesn’t starve the scheduler, we explicitly
|
|
||||||
yield after each operation with
|
|
||||||
<code>runtime.Gosched()</code>. This yielding is
|
|
||||||
handled automatically with e.g. every
|
|
||||||
channel operation and for blocking
|
|
||||||
calls like <code>time.Sleep</code>, but in this
|
|
||||||
case we need to do it manually.</p>
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre> <span class="nx">runtime</span><span class="p">.</span><span class="nx">Gosched</span><span class="p">()</span>
|
<div class="highlight"><pre> <span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
<span class="p">}()</span>
|
<span class="p">}()</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
@ -199,8 +192,8 @@ using the same pattern we did for reads.</p>
|
|||||||
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span>
|
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span>
|
||||||
<span class="nx">state</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="p">=</span> <span class="nx">val</span>
|
<span class="nx">state</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="p">=</span> <span class="nx">val</span>
|
||||||
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
|
<span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
|
||||||
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddInt64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">writeOps</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||||
<span class="nx">runtime</span><span class="p">.</span><span class="nx">Gosched</span><span class="p">()</span>
|
<span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
<span class="p">}()</span>
|
<span class="p">}()</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
@ -225,13 +218,15 @@ using the same pattern we did for reads.</p>
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>Take and report a final operations count.</p>
|
<p>Take and report final operation counts.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre> <span class="nx">opsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadInt64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">)</span>
|
<div class="highlight"><pre> <span class="nx">readOpsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">readOps</span><span class="p">)</span>
|
||||||
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"ops:"</span><span class="p">,</span> <span class="nx">opsFinal</span><span class="p">)</span>
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"readOps:"</span><span class="p">,</span> <span class="nx">readOpsFinal</span><span class="p">)</span>
|
||||||
|
<span class="nx">writeOpsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">writeOps</span><span class="p">)</span>
|
||||||
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"writeOps:"</span><span class="p">,</span> <span class="nx">writeOpsFinal</span><span class="p">)</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -260,15 +255,16 @@ using the same pattern we did for reads.</p>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>Running the program shows that we executed about
|
<p>Running the program shows that we executed about
|
||||||
3,500,000 operations against our <code>mutex</code>-synchronized
|
90,000 total operations against our <code>mutex</code>-synchronized
|
||||||
<code>state</code>.</p>
|
<code>state</code>.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre><span class="gp">$</span> go run mutexes.go
|
<div class="highlight"><pre><span class="gp">$</span> go run mutexes.go
|
||||||
<span class="go">ops: 3598302</span>
|
<span class="go">readOps: 83285</span>
|
||||||
<span class="go">state: map[1:38 4:98 2:23 3:85 0:44]</span>
|
<span class="go">writeOps: 8320</span>
|
||||||
|
<span class="go">state: map[1:97 4:53 0:33 2:15 3:2]</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
@ -46,7 +46,7 @@ by exactly 1 goroutine.</p>
|
|||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
<a href="http://play.golang.org/p/-WqmiTr6ek"><img title="Run code" src="play.png" class="run" /></a>
|
<a href="http://play.golang.org/p/P4SrrlosMp"><img title="Run code" src="play.png" class="run" /></a>
|
||||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
@ -117,7 +117,8 @@ goroutine to respond.</p>
|
|||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre> <span class="kd">var</span> <span class="nx">ops</span> <span class="kt">int64</span> <span class="p">=</span> <span class="mi">0</span>
|
<div class="highlight"><pre> <span class="kd">var</span> <span class="nx">readOps</span> <span class="kt">uint64</span> <span class="p">=</span> <span class="mi">0</span>
|
||||||
|
<span class="kd">var</span> <span class="nx">writeOps</span> <span class="kt">uint64</span> <span class="p">=</span> <span class="mi">0</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -190,7 +191,8 @@ result over the provided <code>resp</code> channel.</p>
|
|||||||
<span class="nx">resp</span><span class="p">:</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)}</span>
|
<span class="nx">resp</span><span class="p">:</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)}</span>
|
||||||
<span class="nx">reads</span> <span class="o"><-</span> <span class="nx">read</span>
|
<span class="nx">reads</span> <span class="o"><-</span> <span class="nx">read</span>
|
||||||
<span class="o"><-</span><span class="nx">read</span><span class="p">.</span><span class="nx">resp</span>
|
<span class="o"><-</span><span class="nx">read</span><span class="p">.</span><span class="nx">resp</span>
|
||||||
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddInt64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">readOps</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||||
|
<span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
<span class="p">}()</span>
|
<span class="p">}()</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
@ -216,7 +218,8 @@ approach.</p>
|
|||||||
<span class="nx">resp</span><span class="p">:</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">bool</span><span class="p">)}</span>
|
<span class="nx">resp</span><span class="p">:</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">bool</span><span class="p">)}</span>
|
||||||
<span class="nx">writes</span> <span class="o"><-</span> <span class="nx">write</span>
|
<span class="nx">writes</span> <span class="o"><-</span> <span class="nx">write</span>
|
||||||
<span class="o"><-</span><span class="nx">write</span><span class="p">.</span><span class="nx">resp</span>
|
<span class="o"><-</span><span class="nx">write</span><span class="p">.</span><span class="nx">resp</span>
|
||||||
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddInt64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
<span class="nx">atomic</span><span class="p">.</span><span class="nx">AddUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">writeOps</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||||
|
<span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
<span class="p">}()</span>
|
<span class="p">}()</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
@ -240,13 +243,15 @@ approach.</p>
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>Finally, capture and report the <code>ops</code> count.</p>
|
<p>Finally, capture and report the op counts.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code">
|
<td class="code">
|
||||||
|
|
||||||
<div class="highlight"><pre> <span class="nx">opsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadInt64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">)</span>
|
<div class="highlight"><pre> <span class="nx">readOpsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">readOps</span><span class="p">)</span>
|
||||||
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"ops:"</span><span class="p">,</span> <span class="nx">opsFinal</span><span class="p">)</span>
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"readOps:"</span><span class="p">,</span> <span class="nx">readOpsFinal</span><span class="p">)</span>
|
||||||
|
<span class="nx">writeOpsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">writeOps</span><span class="p">)</span>
|
||||||
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"writeOps:"</span><span class="p">,</span> <span class="nx">writeOpsFinal</span><span class="p">)</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
@ -260,14 +265,15 @@ approach.</p>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="docs">
|
<td class="docs">
|
||||||
<p>Running our program shows that the goroutine-based
|
<p>Running our program shows that the goroutine-based
|
||||||
state management example achieves about 800,000
|
state management example completes about 80,000
|
||||||
operations per second.</p>
|
total operations.</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td class="code leading">
|
<td class="code leading">
|
||||||
|
|
||||||
<div class="highlight"><pre><span class="gp">$</span> go run stateful-goroutines.go
|
<div class="highlight"><pre><span class="gp">$</span> go run stateful-goroutines.go
|
||||||
<span class="go">ops: 807434</span>
|
<span class="go">readOps: 71708</span>
|
||||||
|
<span class="go">writeOps: 7177</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user