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]}
デメリット:
変数のポインタが変わります。(使い場合は用注意)