golang []byte和string的高性能转换

简介: golang []byte和string的高性能转换

golang []byte和string的高性能转换

fasthttp的最佳实践中有这么一句话:


Avoid conversion between []byte and string, since this may result in memory allocation+copy. Fasthttp API provides functions for both []byte and string - use these functions instead of converting manually between []byte and string. There are some exceptions - see this wiki page for more details.


大概意思就是说,要尽量避免[]bytestring的转换,因为转换过程会存在内存拷贝,影响性能。此外在fasthttp中还提出了一个解决方案,用于[]bytestring的高性能转换。直接看下源码:


// b2s converts byte slice to a string without memory allocation.
// See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
//
// Note it may break if string and/or slice header will change
// in the future go versions.
func b2s(b []byte) string {
  /* #nosec G103 */
  return *(*string)(unsafe.Pointer(&b))
}
// s2b converts string to a byte slice without memory allocation.
//
// Note it may break if string and/or slice header will change
// in the future go versions.
func s2b(s string) (b []byte) {
  /* #nosec G103 */
  bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
  /* #nosec G103 */
  sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
  bh.Data = sh.Data
  bh.Cap = sh.Len
  bh.Len = sh.Len
  return b
}

可以看到上述实现中并没有内存拷贝,使用类似C语言的类型强转实现[]bytestring之间的类型转换。那么他们和一般使用的转换之间的性能差异有多大?看下如下性能测试:

var s = "adsfasdfadsfadsfasdfadfadfasdfasdfadsfasdfasdfasdfsadfas"
func BenchmarkB2sFast(b *testing.B) {
for i := 0; i < b.N; i++ {
       _ = s2b(s)
    }
}
func BenchmarkB2sStd(b *testing.B) {
var _ []byte
for i := 0; i < b.N; i++ {
        _ = []byte(s)
    }
}
var bt = []byte("adsfasdfadsfadsfasdfadfadfasdfasdfadsfasdfasdfasdfsadfas")
func BenchmarkS2BFast(b *testing.B) {
for i := 0; i < b.N; i++ {
        _ = b2s(bt)
    }
}
func BenchmarkS2BStd(b *testing.B) {
var _ []byte
for i := 0; i < b.N; i++ {
        _ = string(bt)
    }
}

测试结果如下:

goos: windows
goarch: amd64
pkg: awesomeProject5/lib
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkB2sFast
BenchmarkB2sFast-8    1000000000           0.2383 ns/op
BenchmarkB2sStd
BenchmarkB2sStd-8     41089557          27.65 ns/op
BenchmarkS2BFast
BenchmarkS2BFast-8    1000000000           0.2378 ns/op
BenchmarkS2BStd
BenchmarkS2BStd-8     54249056          22.51 ns/op
PASS

可以看到在相同测试条件下,其性能差异竟然达到了100倍!


可见在高频网络访问中,如果直接在[]bytestring之间进行转换将会花费多大的性能!


需要注意的是这种方式也有弊端,在代码注释中可以看到它依赖golang中的string或slice的首部定义。如果后续golang版本对此有修改,则有可能导致代码无法运行。

目录
相关文章
|
7月前
|
传感器 监控 物联网
golang开源的可嵌入应用程序高性能的MQTT服务
golang开源的可嵌入应用程序高性能的MQTT服务
348 3
|
7月前
|
网络协议 Go 数据安全/隐私保护
golang开源的可嵌入应用程序高性能的MQTT服务
golang开源的可嵌入应用程序高性能的MQTT服务
445 2
|
4月前
|
JSON Go API
一文搞懂 Golang 高性能日志库 - Zap
一文搞懂 Golang 高性能日志库 - Zap
337 2
|
4月前
|
存储 Go 索引
Golang 中的 String、rune 和 byte
Golang 中的 String、rune 和 byte
|
4月前
|
存储 JSON Go
一文搞懂 Golang 高性能日志库 Zerolog
一文搞懂 Golang 高性能日志库 Zerolog
456 0
new String()定义字符串为空,char[] chs = {‘a‘,‘b‘,‘c‘} String s2 = new String(chs) 输出abc,byte定99为a
new String()定义字符串为空,char[] chs = {‘a‘,‘b‘,‘c‘} String s2 = new String(chs) 输出abc,byte定99为a
|
7月前
|
存储 中间件 Go
探索Gin框架:快速构建高性能的Golang Web应用
探索Gin框架:快速构建高性能的Golang Web应用
|
7月前
|
Go 机器学习/深度学习 Rust
Golang每日一练(leetDay0119) 反转字符串I\II Reverse String
Golang每日一练(leetDay0119) 反转字符串I\II Reverse String
92 0
Golang每日一练(leetDay0119) 反转字符串I\II Reverse String
|
7月前
|
存储 缓存 算法
Golang高性能内存缓存库BigCache设计与分析
【2月更文挑战第4天】分析Golang高性能内存缓存库BigCache设计
241 0
|
7月前
|
存储 编译器 Go
Golang底层原理剖析之string类型与字符编码
Golang底层原理剖析之string类型与字符编码
68 0
下一篇
DataWorks