golang byte转string_golang面试题:怎么避免内存逃逸?
问题
怎么避免内存逃逸?
怎么答
在runtime/stubs.go:133
有个函数叫noescape
。noescape
可以在逃逸分析中隐藏一个指针。让这个指针在逃逸分析中不会被检测为逃逸。
// noescape hides a pointer from escape analysis. noescape is// the identity function but escape analysis doesn't think the// output depends on the input. noescape is inlined and currently// compiles down to zero instructions.// USE CAREFULLY!//go:nosplitfunc noescape(p unsafe.Pointer) unsafe.Pointer {x := uintptr(p)return unsafe.Pointer(x ^ 0)
}
举例
- 通过一个例子加深理解,接下来尝试下怎么通过
go build -gcflags=-m
查看逃逸的情况。
package mainimport ("unsafe"
)type A struct {S *string
}func (f *A) String() string {return *f.S
}type ATrick struct {S unsafe.Pointer
}func (f *ATrick) String() string {return *(*string)(f.S)
}func NewA(s string) A {return A{S: &s}
}func NewATrick(s string) ATrick {return ATrick{S: noescape(unsafe.Pointer(&s))}
}func noescape(p unsafe.Pointer) unsafe.Pointer {x := uintptr(p)return unsafe.Pointer(x ^ 0)
}func main() {s := "hello"f1 := NewA(s)f2 := NewATrick(s)s1 := f1.String()s2 := f2.String()_ = s1 + s2
}
执行go build -gcflags=-m main.go
$go build -gcflags=-m main.go
# command-line-arguments
./main.go:11:6: can inline (*A).String
./main.go:19:6: can inline (*ATrick).String
./main.go:23:6: can inline NewA
./main.go:31:6: can inline noescape
./main.go:27:6: can inline NewATrick
./main.go:28:29: inlining call to noescape
./main.go:36:6: can inline main
./main.go:38:14: inlining call to NewA
./main.go:39:19: inlining call to NewATrick
./main.go:39:19: inlining call to noescape
./main.go:40:17: inlining call to (*A).String
./main.go:41:17: inlining call to (*ATrick).String
/var/folders/45/qx9lfw2s2zzgvhzg3mtzkwzc0000gn/T/go-build763863171/b001/_gomod_.go:6:6: can inline init.0
./main.go:11:7: leaking param: f to result ~r0 level=2
./main.go:19:7: leaking param: f to result ~r0 level=2
./main.go:24:16: &s escapes to heap
./main.go:23:13: moved to heap: s
./main.go:27:18: NewATrick s does not escape
./main.go:28:45: NewATrick &s does not escape
./main.go:31:15: noescape p does not escape
./main.go:38:14: main &s does not escape
./main.go:39:19: main &s does not escape
./main.go:40:10: main f1 does not escape
./main.go:41:10: main f2 does not escape
./main.go:42:9: main s1 + s2 does not escape
其中主要看中间一小段
./main.go:24:16: &s escapes to heap //这个是NewA中的,逃逸了
./main.go:23:13: moved to heap: s
./main.go:27:18: NewATrick s does not escape // NewATrick里的s的却没逃逸
./main.go:28:45: NewATrick &s does not escape
解释
- 上段代码对
A
和ATrick
同样的功能有两种实现:他们包含一个string
,然后用String()
方法返回这个字符串。但是从逃逸分析看ATrick
版本没有逃逸。 noescape()
函数的作用是遮蔽输入和输出的依赖关系。使编译器不认为p
会通过x
逃逸, 因为uintptr()
产生的引用是编译器无法理解的。- 内置的
uintptr
类型是一个真正的指针类型,但是在编译器层面,它只是一个存储一个指针地址
的int
类型。代码的最后一行返回unsafe.Pointer
也是一个int
。 noescape()
在runtime
包中使用unsafe.Pointer
的地方被大量使用。如果作者清楚被unsafe.Pointer
引用的数据肯定不会被逃逸,但编译器却不知道的情况下,这是很有用的。- 面试中秀一秀是可以的,如果在实际项目中如果使用这种unsafe包大概率会被同事打死。不建议使用! 毕竟包的名字就叫做
unsafe
, 而且源码中的注释也写明了USE CAREFULLY!
。
文章推荐:
- golang面试题:简单聊聊内存逃逸?
- golang面试题:字符串转成byte数组,会发生内存拷贝吗?
- golang面试题:翻转含有中文、数字、英文字母的字符串
- golang面试题:拷贝大切片一定比小切片代价大吗?
- golang面试题:能说说uintptr和unsafe.Pointer的区别吗?
如果你想每天学习一个知识点,关注我上面的【公】【众】【号】【golang小白成长记】。
golang byte转string_golang面试题:怎么避免内存逃逸?相关推荐
- golang byte转string_Golang和Rust语言常见功能/库
时下最流行.最具发展前途的的两门语言是Golang和Rust.Golang语言简洁.高效.并发.并且有个强大的囊括了常见功能标准库.与之相对比,Rust语言则主要是安全.高性能.虽然Rust没有gol ...
- golang byte转string_golang版memcached之groupcache缓存入门
概述 groupcache is a distributed caching and cache-filling library, intended as a replacementfor a poo ...
- golang byte转string_golang系列——实战http服务器
上一篇讲解了client端相关的知识,这一篇讲解服务端.golang语言可以快速实现一个简单的server端,如下所示: package 上述代码就轻松实现一个监听本地8000端口的服务端.大家可能注 ...
- golang []byte 和 string相互转换
原文链接:golang []byte和string相互转换 测试例子 package mainimport ("fmt" )func main() {str2 := "h ...
- golang byte 和 java byte 的区别
大家应该都了解,java byte 的范围是 -128-127,而golang byte 是uint8的别名,范围是0-255.那么要把java byte 转成 golang byte 怎么转呢? 方 ...
- Golang byte 拼接方法性能对比
Golang byte 拼接方法性能对比 最近项目上遇到需要将[]Byte进行拼接的需求,对[]Byte拼接的各种方法进行了对比,测试代码如下: package main import (" ...
- golang int 转string_Golang的逃逸分析
逃逸分析 逃逸分析(Escape Analysis)指的是将变量的内存分配在合适的地方(堆或者栈). 在函数中申请内存有2种情况: - 如果内存分配在栈(stack)上,当函数退出的时候,这部分内存会 ...
- Golang的GC和内存逃逸
简介 每个版本的Golang的垃圾回收都在不断优化中,而且方法和策略都在变化,因此这里只是总结出以下几个关键点: 什么样的数据需要GC 触发GC的条件是什么 GC时发生了什么 能否从代码层面上提高GC ...
- C++面试题-指针-动态内存指针
C++面试题-指针-动态内存指针 问:什么是内存泄漏和内存溢出? 答:内存泄漏:在程序申请内存后,该内存不再会被引用,但是不能释放该内存空间.如果你delete指针之后,该空间不能归还,自己又不能进行 ...
最新文章
- 腾讯和头条,构建类脑神经元网络的两条路线之争
- Hyperledger Fabric 智能合约实战 (7) windows安装fabric
- Unity 高清渲染管线 ShaderGraph 实现简单的表面水流效果
- 汇编语言(二)之数值求和
- PHP中获取星期的几种方法
- Castle动态代理拦截器可跟踪模型更改和触发规则
- Qt: 非阻塞时间延迟;
- 利用Python进行数据分析(2) 尝试处理一份JSON数据并生成条形图
- 恒强制版系统980_恒功率、大功率及无线充电,充电设备面临哪些趋势和挑战?...
- 公司小规模纳税人税务零申报操作说明
- (软件测试)代码覆盖(语句覆盖,分支覆盖,条件覆盖,条件组合覆盖,路径覆盖)
- 解决web系统session劫持
- 深度学习CTR模型粗略记录
- 12-机械键盘和普通键盘的区别
- 手把手教你写批处理-批处理的介绍
- 教你小小JAVA爬虫爬到HDU首页(只为学习)
- Java基础--object类详解
- window手动注册达梦ODBC驱动
- 基于SOCK_RAW的泛洪攻击
- 制作pDF 格式电子书
热门文章
- 常见的大数据安全5个问题和解决策略
- offset must be non-negative and no greater than buffer length (0)(tensorflow.keras)
- 线性回归和广义线性回归
- html 并集选择器,HTML+CSS基础 并集选择器
- python将list转为数组_python如何将list中的字符转为数字
- 各种门锁的内部结构图_逃生门锁,我们的生命之锁!
- asp sql 导出 excel_使用SQL进行数据分析(八)
- 应用联合服务 云计算拉近应用和操作距离
- 出现( linker command failed with exit code 1)错误总结
- careercup-链表 2.4