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. Linux云服务部署Spring boot项目

    Linux云服务部署Spring boot项目 背景: 之前经过两个周的时间,做了一个简单的博客网站,网址:点击进入,在本地可以正常使用以后,想着部署到服务器上,给大家伙看个乐呵,于是有了这篇部署文章 ...

  2. 基于SigalR实现的奥运会实时金牌榜

    系统架构 三端 winform 后台数据管理 + Asp.Net Mvc 前台数据展示 + Xamarin.Forms 移动端跨平台APP 因为本人的代码水平一般,期间遇到了一些问题,如signalR ...

  3. Linux centos7 nginx 平滑升级

    2021-08-19为了方便读者的阅读,该文通篇使用绝对路径,各位朋友们在实际上操作中可以根据实际情况编写路径(#^.^#)1. 当前环境 # system cat /etc/redhat-relea ...

  4. 实例_ Java中的代理模式

    静态代理 我们定义一个接口,并且使用代理模式,想要做到的就是在调用这个接口的实现类时在此方法上添加功能. public interface HelloInterface { void sayHello ...

  5. Linux基于Docker的Redis主从复制、哨兵模式搭建

    本教程基于CentOS7,开始本教程前,请确保您的Linux系统已安装Docker. 1.使用docker下载redis镜像 docker pull redis 安装完成后,使用docker imag ...

  6. python 回归分析

    一.线性回归 1 绘制散点图 import matplotlib.pyplot as plt x = [5,7,8,7,2,17,2,9,4,11,12,9,6] y = [99,86,87,88,1 ...

  7. ubantu与CentOS虚拟机之间搭建GRE隧道

    Author       : Email         : vip_13031075266@163.com Date          : 2020.01.23 Copyright : 未经同意不得 ...

  8. 装配Bean的三种方式

    一.装配Bean就是在xml写一个Bean标签:装配完Bean,还需要读取xml配置文件创建Spring容器来创建对象: 1.new 实现类方式 正常的三种创建Bean容器的方法都可以根据装配的Bea ...

  9. Linux的基础命令(一)

    目录: 一.Linux系统基础 1.shell      2. Linux命令的分类 二.Linux命令行 1.Linux命令行提示符      2.Linux通用命令行使用格式      3.Lin ...

  10. 如何在win10中Java中JDK的安装和path,classpath的环境配置

    1,第一步,不用说肯定是去下一个java JDK了.目前最新版本的java JDK应该是JDK 7.0,这个就自己去百度一下了,好多网站都可以找到.2,第二步就是安装JDK虚拟机了,按照它里面的提示一 ...