zoukankan      html  css  js  c++  java
  • 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版本对此有修改,则有可能导致代码无法运行。

  • 相关阅读:
    VS2010快捷键
    mvc 简单的分页扩展
    Asp.net(C#)给图片加上水印效果
    HTML特殊字符编码大全
    获取URL上的参数值
    json数据的时间格式转换如:/Date(2342561534)/
    js中文编码到C#后台解码
    获取浏览器滚动条高度
    使用js画图
    silverlight实时从Javascript获取json数据
  • 原文地址:https://www.cnblogs.com/charlieroro/p/15410902.html
Copyright © 2011-2022 走看看