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 BenchmarkB2sNew(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = s2b(s)
}
} func BenchmarkB2sNormal(b *testing.B) {
var _ []byte
for i := 0; i < b.N; i++ {
_ = []byte(s)
}
} var bt = []byte("adsfasdfadsfadsfasdfadfadfasdfasdfadsfasdfasdfasdfsadfas")
func BenchmarkS2BNew(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = b2s(bt)
}
} func BenchmarkS2BNormal(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
BenchmarkB2sNew
BenchmarkB2sNew-8 1000000000 0.2401 ns/op
BenchmarkB2sNormal
BenchmarkB2sNormal-8 40813272 27.49 ns/op
BenchmarkS2BNew
BenchmarkS2BNew-8 1000000000 0.2393 ns/op
BenchmarkS2BNormal
BenchmarkS2BNormal-8 49520067 22.56 ns/op
PASS

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

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

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

golang []byte和string的高性能转换的更多相关文章

  1. 转载 Golang []byte与string转换的一个误区

    Golang []byte与string转换的一个误区 https://www.oyohyee.com/post/Note/golang_byte_to_string/ 2019-08-10 23:4 ...

  2. 如何在Byte[]和String之间进行转换

    源自C#与.NET程序员面试宝典. 如何在Byte[]和String之间进行转换? 比特(b):比特只有0 1,1代表有脉冲,0代表无脉冲.它是计算机物理内存保存的最基本单元. 字节(B):8个比特, ...

  3. golang []byte 和 string相互转换

    原文链接:golang []byte和string相互转换 测试例子 package main import ( "fmt" ) func main() { str2 := &qu ...

  4. go byte 和 string 类型之间转换

    string 不能直接和byte数组转换 string可以和byte的切片转换 1,string 转为[]byte var str string = "test" var data ...

  5. 关于byte[]与string、Image转换

    byte[]与string转换 参考网址:https://www.cnblogs.com/xskblog/p/6179689.html 1.使用System.Text.Encoding.Default ...

  6. golang byte转string 字节数组转字符串的问题

    golang语言本身就是c的工具集,开发c的程序用到的大部分结构体,内存管理,携程等,golang基本都有,他只是在这个基础上又加了一些概念这里说一个很小的问题,就是字节数组转string的问题,网上 ...

  7. golang []byte转string

    golang中,字符切片[]byte转换成string最简单的方式是 package main import ( "fmt" _ "unsafe" ) func ...

  8. java String与Byte[]和String 与InputStream转换时注意编码问题。。。

    前一段日子,我在做rsa加密和通过http get方式获取验证码图片通过BitmapFactory创建bitmap 出现了一系列的问题. 通过一系列的调试,发现有些问题原来是在进行String 与By ...

  9. golang []byte和string相互转换

    测试例子 package main   import (     "fmt" )   func main() {     str2 := "hello"     ...

随机推荐

  1. T-SQL - 习题02_将数据表year|month|amount查询成year|m1|m2|m3|m4的样式

    时间:2017-09-11 整理:byzqy 题目:有个年度统计表,结构如下: 怎么样把这个表,查询成这样一个结果: 这是在面试过程中遇到的一个关于数据库的题,没有一点思路,不知它考查到的知识点是什么 ...

  2. Java反射的浅显理解

    一.回顾反射相关的知识 1.在xml文件中使用反射的好处: 1)代码更加灵活,后期维护只需要修改配置文件即可 · 初学者一般习惯于在代码本身上直接修改,后期也可以修改配置文件达到相同的目的 · 修改配 ...

  3. 【Python机器学习实战】决策树与集成学习(四)——集成学习(2)GBDT

    本打算将GBDT和XGBoost放在一起,但由于涉及内容较多,且两个都是比较重要的算法,这里主要先看GBDT算法,XGBoost是GBDT算法的优化和变种,等熟悉GBDT后再去理解XGBoost就会容 ...

  4. Sentry-CLI 使用详解(2021 Sentry v21.8.x)

    内容源于:https://docs.sentry.io/platforms/javascript/guides/vue/ 系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创 ...

  5. 服务器安装CentOS7.9系统(U盘启动方式)

    一.安装环境 机房的华为GPU服务器,型号G2500,8张P4显卡,需要安装最小化的CentOS7.9操作系统,利用U盘启动的方式进行安装. 二.安装说明 虽然本环境是GPU服务器,但是安装方式同样适 ...

  6. Linux内核中的Workqueue机制分析

    1. 什么是workqueue Linux中的workqueue(工作队列)主要是为了简化在内核创建线程而设计的.通过相应的工作队列接口,可以使开发人员只关心与特定功能相关的处理流程,而不必关心内核线 ...

  7. 使用easyui进行上左右布局

    在后台管理系统开发的过程中,上左右的布局是最常见的页面布局方式,现在我们来看看使用easyui这个jquery前端框架如何快速搭建一个可用的页面框架. 1.在页面中引入easyui所需的文件 1 &l ...

  8. 使用ECS和OSS搭建个人网盘

    体验简介 本场景将提供一台配置了Centos 7.7版本的ECS实例(云服务器)和对象存储OSS实例.通过本教程的操作,您可以基于ECS和OSS快速搭建一个个人网盘. 体验此场景后,可以掌握的知识有: ...

  9. pip更新升级和删除包

    pip检测更新命令:pip list –outdated pip升级包命令:pip install --upgrade packagename pip卸载包命令:pip uninstall packa ...

  10. 什么是 baseline 和 benchmark

    baseline 一个算法被称为 baseline 算法说明这个比目前这个算法还差的已经不能接受了,方法有革命性的创新点可以挖掘,且存在巨大提升空间和超越benchmark的潜力,只是由于发展初期导致 ...