私はgolangにかなり慣れていないので、この質問は主に私の側の概念的な欠点によるものだと確信しています。
golang では、非バッファ型とバッファ型 (それぞれ同期と非同期) の 2 種類のチャネルを使用できます。
unbufferedChan := make(chan string)
bufferedChan := make(chan string, 100)
バッファリングされていないチャネルを介して通信する 2 つのゴルーチンは、互いに待機する必要があります。つまり、受信ゴルーチンは送信者が送信するまでブロックし、送信者は受信者が受信するまでブロックします。
バッファリングの場合、レシーバはチャネルが空の場合にのみブロックします。送信者は、チャネルがいっぱいの場合にのみブロックします。
バッファリングされたチャネルを使用することで、ゴルーチンがブロックしている時間を短縮し、コードの速度を向上できると期待していました。代わりに、すべてが遅くなりました。私の予想に反して (つまり、「バッファリングはより効率的です」)、バッファリングされていないチャネルはかなり高速になりました。
これがすべてのコードです。最初に必要になります。go get code.google.com/p/go-html-transform/html/transform
package main
import (
"fmt"
"math/rand"
"os"
"sync"
"time"
sel "code.google.com/p/go-html-transform/css/selector"
h5 "code.google.com/p/go-html-transform/h5"
gnhtml "code.google.com/p/go.net/html"
)
// Find a specific HTML element and return its textual element children.
func main() {
test := `
<html>
<head>
<title>This is the test document!</title>
<style>
header: color=blue;
</style>
</head>
<body>
<div id="h" class="header">This is some text</div>
</body>
</html>`
// Get a parse tree for this HTML
h5tree, err := h5.NewFromString(test)
if err != nil {
die(err)
}
n := h5tree.Top()
// Create a Chain object from a CSS selector statement
chn, err := sel.Selector("#h")
if err != nil {
die(err)
}
// Find the item. Should be a div node with the text "This is some text"
h := chn.Find(n)[0]
// run our little experiment this many times total
var iter int = 100000
// When buffering, how large shall the buffer be?
var bufSize uint = 100
// Keep a running total of the number of times we've tried buffered
// and unbuffered channels.
var bufCount int = 0
var unbufCount int =0
// Keep a running total of the number of nanoseconds that have gone by.
var bufSum int64 = 0
var unbufSum int64 = 0
// Call the function {iter} times, randomly choosing whether to use a
// buffered or unbuffered channel.
for i := 0; i < iter; i++ {
if rand.Float32() < 0.5 {
// No buffering
unbufCount += 1
startTime := time.Now()
getAllText(h, 0)
unbufSum += time.Since(startTime).Nanoseconds()
} else {
// Use buffering
bufCount += 1
startTime := time.Now()
getAllText(h, bufSize)
bufSum += time.Since(startTime).Nanoseconds()
}
}
unbufAvg := unbufSum / int64(unbufCount)
bufAvg := bufSum / int64(bufCount)
fmt.Printf("Unbuffered average time (ns): %v\n", unbufAvg)
fmt.Printf("Buffered average time (ns): %v\n", bufAvg)
}
// Kill the program and report the error
func die(err error) {
fmt.Printf("Terminating: %v\n", err.Error())
os.Exit(1)
}
// Walk through all of a nodes children and construct a string consisting
// of c.Data where c.Type == TextNode
func getAllText(n *gnhtml.Node, bufSize uint) string {
var texts chan string
if bufSize == 0 {
// unbuffered, synchronous
texts = make(chan string)
} else {
// buffered, asynchronous
texts = make(chan string, bufSize)
}
wg := sync.WaitGroup{}
// Go walk through all n's child nodes, sending only textual data
// over the texts channel.
wg.Add(1)
nTree := h5.NewTree(n)
go func () {
nTree.Walk(func (c *gnhtml.Node) {
if c.Type == gnhtml.TextNode {
texts <- c.Data
}
})
close(texts)
wg.Done()
}()
// As text data comes in over the texts channel, build up finalString
wg.Add(1)
finalString := ""
go func () {
for t := range texts {
finalString += t
}
wg.Done()
}()
// Return finalString once both of the goroutines have finished.
wg.Wait()
return finalString
}
プログラムを 10 回実行した結果は次のとおりです。
Buffered average time (ns): 32088
Buffered average time (ns): 32183
Buffered average time (ns): 35091
Buffered average time (ns): 35798
Buffered average time (ns): 36966
Buffered average time (ns): 38707
Buffered average time (ns): 39464
Buffered average time (ns): 40021
Buffered average time (ns): 41063
Buffered average time (ns): 46248
Unbuffered average time (ns): 18265
Unbuffered average time (ns): 18804
Unbuffered average time (ns): 20268
Unbuffered average time (ns): 20401
Unbuffered average time (ns): 21652
Unbuffered average time (ns): 22630
Unbuffered average time (ns): 22907
Unbuffered average time (ns): 23326
Unbuffered average time (ns): 24133
Unbuffered average time (ns): 27546