tombo2-progress’s diary

できるだけ毎日1時間を切り取ってここに晒す。誤字脱字気にしない。日本語が崩壊するのも気にしない。最終的にまとめて本ブログに書く

benchmark取るとchannel使うのが厳しいのがわかる

チャネル使って並列ド上げつつredigo.Send多用して行きたいけど、パフォーマンス上がらん

package main

import (
    "github.com/go-redis/redis"
    redigo "github.com/gomodule/redigo/redis"
    "runtime"
    "sync"
    "testing"
)

var redisOpts = &redis.Options{
    Addr:     "localhost:16379",
    Password: "",
    DB:       0,
}

func lpushRedis(c *redis.Client, i int) {
    c.Do("LPUSH", "key1", string(i))
}

func BenchmarkRedisSet(b *testing.B) {
    client := redis.NewClient(redisOpts)
    defer client.Close()
    wg := &sync.WaitGroup{}
    cpus := runtime.NumCPU() / 2 // Need to experimentations
    semaphore := make(chan bool, cpus)
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        semaphore <- true
        wg.Add(1)
        go func() {
            defer func() { <-semaphore }()
            lpushRedis(client, i)
            wg.Done()
        }()
    }
    wg.Wait()
}

func lpushRedigo(c redigo.Conn, i int) {
    c.Do("LPUSH", "key2", string(i))
}

func BenchmarkRedigoSet(b *testing.B) {
    conn, _ := redigo.Dial("tcp", "localhost:16379")
    defer conn.Close()
    wg := &sync.WaitGroup{}
    cpus := runtime.NumCPU() / 2 // Need to experimentations
    semaphore := make(chan bool, cpus)
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        semaphore <- true
        wg.Add(1)
        go func() {
            defer func() { <-semaphore }()
            lpushRedigo(conn, i)
            wg.Done()
        }()
    }
    wg.Wait()
}

func sendDoPeriodically(chdo chan int) {
    for {
        time.Sleep(100 * time.Millisecond)
        chdo <- 1
    }
}

func sendRedigoClient(chstr chan string, chdo chan int, che chan int) {
    c, _ := redigo.Dial("tcp", "localhost:16379")
L:
    for {
        select {
        case <- chdo:
            c.Do("")
        case s := <- chstr:
            c.Send("LPUSH", "key3", s)
        case <- che:
            c.Do("")
            break L
        }
    }
    che <- 1
}

func sendRedigoClient2(chstr chan string, chdo chan int, che chan int) {
    c, _ := redigo.Dial("tcp", "localhost:16379")
L:
    for {
        select {
        case <- chdo:
            c.Do("")
        case s := <- chstr:
            c.Send("LPUSH", "key3", s)
        case <- che:
            c.Do("")
            break L
        }
    }
    che <- 1
}


func BenchmarkRedigoSend(b *testing.B) {
    chstr := make(chan string)
    chdo := make(chan int, 1000)
    che := make(chan int)
    go sendRedigoClient(chstr, chdo, che)
    go sendDoPeriodically(chdo)
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        chstr <- string(i)
    }
    che <- 1
    <- che
}

func BenchmarkRedigoSend2(b *testing.B) {
    chstr := make(chan string)
    chdo := make(chan int, 200000)
    che := make(chan int)

    chstr2 := make(chan string)
    chdo2 := make(chan int, 100000)
    che2 := make(chan int)

    go sendRedigoClient(chstr, chdo, che)
    go sendRedigoClient2(chstr2, chdo2, che2)
    go sendDoPeriodically(chdo)
    go sendDoPeriodically(chdo2)
    b.ResetTimer()
<200b>
    for i := 0; i < b.N/2; i++ {
        chstr <- string(i)
        chstr2 <- string(i)
    }
    che <- 1
    che2 <- 1
    <- che
    <- che2
}