golangパフォーマンス1:文字列とビット転換


golang 文字列とビット転換のパフォーマンス
テスト環境: go version go1.7.3 windows/amd64

ファイル構造:
rootファイル/01byteToString.go
rootファイル/01byteToString_test.go (転換効率テスト用)

01byteToString.go

package go1_6

import "unsafe"

func StringToByte(s string) []byte {
    //[]byte(s)処理はまず文字列をコピーしてbyteに転換を行う
    return []byte(s)
}

func ByteToString(b []byte) string {
    return string(b)
}

//StringToByteにより早いし 余裕メモリが利用なし
func StringToBytePerf(s string) []byte {
    //メモリで直接転換可能
    x := (*[2]uintptr)(unsafe.Pointer(&s)) //stringは静的系ためメモリ中にポインタで  x[0] : メモリスタート場所  x[1] : 長さ
    h := [3]uintptr{x[0], x[1], x[1]}      // []byteは動的ためメモリ中にポインタで x[0] : メモリスタート場所 x[1] : 実際長さ(len) x[2] : 良いした長さ(cap)
    return *(*[]byte)(unsafe.Pointer(&h))
}

//ByteToStringにより早いし 余裕メモリが利用なし
func ByteToStringPerf(b []byte) string {
    //byteポインタ直接にstirngポインタに転換(x[2]なしになる)
    return *(*string)(unsafe.Pointer(&b))
}

01byteToString_test.go

package go1_6

import (
    "github.com/stretchr/testify/assert"
    "testing"
)

const StringTest = "hello, world!"

func TestStringToByte(t *testing.T) {
    assert.Equal(t, StringToByte(StringTest), []byte(StringTest))
}

func TestByteToString(t *testing.T) {
    assert.Equal(t, ByteToString([]byte(StringTest)), StringTest)
}

func BenchmarkStringToByte(b *testing.B) {
    for i := 0; i < b.N; i++ {
        StringToByte(StringTest)
    }
}

func BenchmarkByteToString(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ByteToString([]byte(StringTest))
    }
}

//---------------------------------------------------------------------

func TestStringToBytePerf(t *testing.T) {
    assert.Equal(t, StringToBytePerf(StringTest), []byte(StringTest))
}

func TestByteToStringPerf(t *testing.T) {
    assert.Equal(t, ByteToStringPerf([]byte(StringTest)), StringTest)
}

func BenchmarkStringToBytePerf(b *testing.B) {
    for i := 0; i < b.N; i++ {
        StringToBytePerf(StringTest)
    }
}

func BenchmarkByteToStringPerf(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ByteToStringPerf([]byte(StringTest))
    }
}

テスト結果:

ポイント:
string構造:[3]uintptr{x[0], x[1], x[2]}
[]byte構造:[2]uintptr{x[0], x[1]}
デメリット:
変数のポインタが変わります。(使い場合は用注意)