go的逃逸分析机制

简介: 快速学习go的逃逸分析机制

什么是逃逸分析

逃逸分析就是分析一个变量是否被引用,然后决定一个变量是分配在一个栈上还是一个堆上


什么是栈和堆

在计算机系统中,栈和堆都是操作系统对内存管理的两种方式。

栈的内存分配速度很快,而且会自动被释放,效率很高。

但是堆的分配速度比较慢,它需要先找到一块内存空间,而且不可以自动释放资源,在go中回收是由垃圾回收机制完成的。


优缺点分析

不管如何栈和堆对于一个程序来说都是储存变量的一个空间。

栈的优点,它是硬件支持的,入栈出栈很快,效率高。那么它就是和储存一些过期时间短、作用域小的变量,比如局部变量。

而堆呢,它的分配速度很慢,就可以储存一些过期时间长、作用域大的变量,比如全局变量。


go的逃逸机制

那么go的逃逸机制设计就是由一个点决定的---就是一个变量是否会被外部引用。

  • 如果变量在函数外部没用被引用,那么他就会优先被分配在栈上
  • 如果变量在函数外部被引用了,那么它就会一定被放到堆上
  • 如果栈上放不下,就一定放在堆上


go常见的内存逃逸场景

  • 返回局部变量指针,因为指针的原因,对象的内存不会随着函数的结束而被回收
  • 栈空间不足,比如创建了一个超长的切片
  • 动态类型逃逸,创建的时候数据类型使用了interface{},编译期间很难确定使用的类型,也会发生逃逸
  • 闭包引用导致逃逸分析
func getSum()func ()int{
    a := 1
    return func()int{
        a++
        return a
    }
}
复制代码


传值真的比传指针效率高吗?

如果拷贝的数据量小,指针可能会发生逃逸,会使用堆,增加GC的负担。所以指针传递效率不一定是最高的


go和c/c++的栈堆概念

  • 在c/c++中栈和堆都是操作系统层级上的概念,是关联硬件的,是由操作系统和编译器共同决定的
  • go中的栈和堆却都是逻辑上的概念(类似数据结构)。操作系统层级上的栈都被调度器、垃圾回收、系统调用等机制消耗了。而我们代码中使用的栈和堆其实是从操作系统申请的一块堆内存模拟出来的,是一种逻辑上的概念。
  • 也因此,c/c++的栈很小。而go的'栈'可以开很大,比如go的一个协程就是一个栈,通常是2或4kb,但可以开成千上万个协程。
  • 而且go有时候为了防止内存碎片化,会对整个栈就行内存迁移,然后拷贝数据(切片扩容机制,当容量大于原数组容量,就会进行迁移拷贝)。所以指针有时候是会变的,只有指针指向的值有意义。因此,go禁止指针的算术运算
相关文章
|
2月前
|
存储 消息中间件 大数据
Go语言在大数据处理中的实际应用与案例分析
【2月更文挑战第22天】本文深入探讨了Go语言在大数据处理中的实际应用,通过案例分析展示了Go语言在处理大数据时的优势和实践效果。文章首先介绍了大数据处理的挑战与需求,然后详细分析了Go语言在大数据处理中的适用性和核心技术,最后通过具体案例展示了Go语言在大数据处理中的实际应用。
|
2月前
|
负载均衡 算法 数据库连接
Go语言性能优化实践:案例分析与解决方案
【2月更文挑战第18天】本文将通过具体的案例分析,探讨Go语言性能优化的实践方法和解决方案。我们将分析几个典型的性能瓶颈问题,并详细介绍如何通过优化代码、调整并发模型、改进内存管理等方式来提升程序的性能。通过本文的学习,读者将能够掌握一些实用的Go语言性能优化技巧,为实际项目开发中的性能优化工作提供指导。
|
2月前
|
缓存 负载均衡 Java
Go语言调度器机制详解
【2月更文挑战第16天】Go语言以其强大的并发编程能力而闻名,这背后离不开其高效的调度器机制。本文将对Go语言的调度器机制进行详细的解析,包括调度器的设计原理、核心组件、调度策略以及优化技巧等方面,帮助读者深入理解Go语言并发编程的底层原理,更好地发挥Go语言并发编程的优势。
|
3月前
|
Go 开发者
Go语言中的错误处理与异常机制:实践与最佳策略
【2月更文挑战第7天】Go语言以其独特的错误处理机制而闻名,它鼓励显式错误检查而不是依赖于异常。本文将探讨错误处理与异常机制在Go语言中的实际应用,并分享一些最佳实践,帮助开发者编写更加健壮和易于维护的Go代码。
|
2天前
|
存储 安全 中间件
【Go语言专栏】Go语言中的安全认证与授权机制
【4月更文挑战第30天】本文探讨了Go语言中实现安全认证与授权的方法。认证机制包括HTTP Basic Auth、表单认证、OAuth和JWT,可借助`net/http`及第三方库实现。授权则通过中间件或拦截器,如RBAC、ABAC和上下文相关授权,`casbin`和`go-permission`等库提供解决方案。实践中,需设计认证流程、存储用户凭证、实现逻辑、定义授权策略和编写中间件,并确保安全性。案例分析展示了认证授权在RESTful API服务中的应用。在Go开发中,不断学习和优化安全策略以应对安全挑战至关重要。
|
2天前
|
监控 算法 测试技术
【Go语言专栏】Go语言的性能优化与内存分析
【4月更文挑战第30天】本文探讨了Go语言的性能优化策略和内存分析方法。性能优化原则包括基准测试、分析瓶颈、避免过早优化和持续监控。优化策略涉及减少内存分配、避免内存逃逸、利用并发、优化算法和数据结构以及减少系统调用。内存分析借助于Go的`pprof`工具、内存分配跟踪和第三方工具,以发现内存泄漏和管理问题。通过这些方法,开发者能提升Go程序效率和资源利用率。
|
2天前
|
Go 数据处理
【Go 语言专栏】Go 语言的反射机制及其应用
【4月更文挑战第30天】Go语言的反射机制通过`reflect`包实现,允许运行时检查和操作类型信息。核心概念包括`reflect.Type`(表示类型)和`reflect.Value`(表示值)。主要操作包括获取类型信息、字段信息及动态调用方法。反射适用于通用数据处理、序列化、动态配置和代码生成等场景,但也带来性能开销和维护难度,使用时需谨慎。通过实例展示了如何使用反射处理不同类型数据,强调了在理解和应用反射时需要不断实践。
|
2天前
|
Go API 开发者
【Go语言专栏】Go语言的错误处理机制
【4月更文挑战第30天】Go语言的错误处理机制简洁强大,错误被视为`error`类型的值。通过`if err != nil`检查错误,使用`log.Fatal`记录并结束程序。错误可被包装以提供上下文信息,通过`Unwrap()`解包找到底层错误。Go 1.13引入的`errors.Is()`、`errors.As()`和改进的`fmt.Errorf()`支持错误链和追踪,助力编写健壮的Go代码。理解并熟练运用这些机制对开发者至关重要。
|
2天前
|
缓存 编译器 Go
【Go语言专栏】理解Go语言的包管理机制
【4月更文挑战第30天】Go语言包管理是构建可维护应用的关键,从基本概念如包导入、初始化到版本管理和依赖管理,再到Go Modules的引入,简化了过程。包的可见性规则和社区生态也至关重要。理解并掌握这些机制对于编写高质量Go代码具有决定性影响。随着Go语言的持续发展,包管理将更加强大易用。
|
5天前
|
网络协议 物联网 Java
Go与Java:在物联网领域的适用性分析
本文对比分析了Go和Java在物联网领域的适用性。Go语言因其轻量级、高效和并发特性,适合资源受限的物联网设备,特别是处理并发连接和数据流。Java则凭借跨平台性、丰富的生态系统和企业级应用能力,适用于大型物联网系统和复杂业务场景。两者在物联网领域各有优势,开发者可根据项目需求选择合适的语言。