雑なメモ書き

気楽にいきます

camelcaseでgoのbenchをやってみた

結論

  • forの入れ子無くなると早いよね
  • allocationの減少がパフォーマンスに影響が高い
  • []bytes操作はやい

ベンチ結果

  • goのtest benchで実行
go test -bench . -benchmem -count=1
  • 1と2の間は実行速度に差があるレベル
  • 2と3はallocationが減ってる
BenchmarkCamelize1-4       500000          2216 ns/op        1392 B/op         45 allocs/op
BenchmarkCamelize2-4     2000000           953 ns/op         320 B/op         14 allocs/op
BenchmarkCamelize3-4     2000000           812 ns/op         224 B/op          8 allocs/op

本体

  • 1-3まである
package camelcase

import "strings"

func camelize1(src string) string {
    splitedSrcs := strings.Split(src, "_")
    cameliedStrs := make([]string, len(splitedSrcs))

    for splitedSrcIndex, splitedSrc := range splitedSrcs {
        splitedStrsParts := make([]string, len(splitedSrc))
        for i, v := range strings.Split(splitedSrc, "") {
            if i == 0 {
                splitedStrsParts[i] = strings.ToUpper(v)
            } else {
                splitedStrsParts[i] = strings.ToLower(v)
            }
        }
        cameliedStrs[splitedSrcIndex] = strings.Join(splitedStrsParts, "")
    }

    return strings.Join(cameliedStrs, "")
}

func camelize2(src string) string {
    splitedSrcs := strings.Split(src, "_")

    cameliedStrs := make([]string, len(splitedSrcs))

    for splitedSrcIndex, splitedSrc := range splitedSrcs {
        splitedSrcRune := []rune(splitedSrc)
        cameliedStrs[splitedSrcIndex] = strings.ToUpper(string(splitedSrcRune[0])) + strings.ToLower(string(splitedSrcRune[1:]))
    }

    return strings.Join(cameliedStrs, "")
}

func camelize3(src string) string {
    splitedSrcs := strings.Split(src, "_")
    cameliedStrs := make([]byte, 0, len(src))

    for _, splitedSrc := range splitedSrcs {
        splitedSrcRune := []rune(splitedSrc)
        cameliedStrs = append(cameliedStrs, []byte(strings.ToUpper(string(splitedSrcRune[0]))+strings.ToLower(string(splitedSrcRune[1:])))...)
    }

    return string(cameliedStrs)
}
package camelcase

import (
    "log"
    "testing"
)

func TestCamelize1(t *testing.T) {
    if re := camelize1("AAAAA_Bnnnn_AA_CCCCCCCCC_DDDDDD_XXXXXXX"); re != "AaaaaBnnnnAaCccccccccDdddddXxxxxxx" {
        log.Fatal("unexpected case: " + re)
    }
}

func TestCamelize2(t *testing.T) {
    if re := camelize2("AAAAA_Bnnnn_AA_CCCCCCCCC_DDDDDD_XXXXXXX"); re != "AaaaaBnnnnAaCccccccccDdddddXxxxxxx" {
        log.Fatal("unexpected case: " + re)
    }
}

func TestCamelize3(t *testing.T) {
    if re := camelize3("AAAAA_Bnnnn_AA_CCCCCCCCC_DDDDDD_XXXXXXX"); re != "AaaaaBnnnnAaCccccccccDdddddXxxxxxx" {
        log.Fatal("unexpected case: " + re)
    }
}

func BenchmarkCamelize1(b *testing.B) {
    for i := 0; i < b.N; i++ {
        camelize1("AAAAA_Bnnnn_AA_CCCCCCCCC_DDDDDD_XXXXXXX")
    }
}

func BenchmarkCamelize2(b *testing.B) {
    for i := 0; i < b.N; i++ {
        camelize2("AAAAA_Bnnnn_AA_CCCCCCCCC_DDDDDD_XXXXXXX")
    }
}

func BenchmarkCamelize3(b *testing.B) {
    for i := 0; i < b.N; i++ {
        camelize3("AAAAA_Bnnnn_AA_CCCCCCCCC_DDDDDD_XXXXXXX")
    }
}