multiprocessing.manager管理的对象需要加锁吗_Go: 内存管理和分配

445fcead3e8fc2d05b73614f86b4f2de.png

本文基于Go1.13

当不再使用内存时,标准库会自动执行Go的内存管理即从分配到回收。尽管开发者不需要处理它,但是Go的底层管理进行了很好的优化并且充满了有趣的概念。

堆上的分配

内存管理被设计可以在并发环境快速执行并且集成了gc。让我们从一个例子开始:

package maintype smallStruct struct {a, b int64c, d float64
}func main() {smallAllocation()
}//go:noinline
func smallAllocation() *smallStruct {return &smallStruct{}
}

注释//go:noinline 将会阻止内联优化,以避免内联通过移除函数的方式优化这段代码,从而造成最终没有分配内存的情况。

运行逃逸分析命令go tool compile "-m" main.go可以确认Go执行了分配:

main.go:14:9: &smallStruct literal escapes to heap

借助go tool compile -S main.go 输出的程序汇编代码,同样可以明确的展示了分配:

0x001d 00029 (main.go:14)   LEAQ   type."".smallStruct(SB), AX
0x0024 00036 (main.go:14)  PCDATA $0, $0
0x0024 00036 (main.go:14)  MOVQ   AX, (SP)
0x0028 00040 (main.go:14)  CALL   runtime.newobject(SB)

函数newobject是新分配对象和代理mallocgc的内置函数,该函数在堆上管理它们。Go中有两种策略,一种用于较小的分配,一种用于较大的分配。

小分配

对于低于32kb的小分配,Go将会尝试从本地mcache 缓存中获取内存。此缓存包含一组mspan

7ec3f12e49405473dc00790d9b4187e6.png

每个M 被分配给一个处理器P并且一次只能处理一个goroutine。当需要分配内存时,当前goroutine会使用它当前P的本地缓存来从中寻找第一个可用空闲对象。使用本地缓存不需要加锁会使得分配更加高效。

mspan被分为约70个尺寸类型,从8字节到32k字节。

e7db4fee4567edd156b78556f440f358.png

每个mspan会存在2次:一个不包含指针,一个包含指针。这种区别会使得gc更加容易因为它不需要扫描那些不包含指针的mspan。

在我们之前的例子里,结构体是32字节所以它适合于32 字节的mspan。

2ce8e3a43953f926200b4889f22c5e4e.png

现在会疑惑如果mspan在内存分配时候没有空闲插槽会发生什么。Go维护了包含全尺寸类型的中央链表mcentral,其中包含空闲和非空闲对象的mspan:

6a72c51d03ca5abd88acc042d5a0fc53.png

mcentral 维护着mspan的双向链表; 在非空链表(non-empty list:尚有空闲object的mspan链表) — 非空(“non-empty” )代表链表中至少有一个插槽是空闲可供分配 — 可能包含一些正在使用的内存。当gc 清理内存时,他会清理一部分mspan标记不再使用,并放回非空链表(non-empty list)

我们程序可以在插槽耗尽后向中央链表申请mspan:

74eeeec828b46a00d4363d49e73415b1.png

如果空链表中没有可用的mspan,Go需要为中央链表获取新的mspan。新的mspan会从堆上分配并链接到中央链表上:

0a7a3b546d662041ad1b827a0f558b1a.png

堆在需要时从OS中提取内存。如果需要更多内存,堆会分配一个叫做 arena 的大块内存, 在 64 位架构下为 64Mb,在其他架构下大多为 4Mb。arena 同样使用mspan来映射内存:

b834f377fae25807e1dfbfb2d36d4fe2.png

大分配

Go并不适用本地缓存来管理较大的内存空间分配。对于超过 32kb 的分配,会向上取整到页的大小,并直接从堆上分配。

e64af3636225fe3d93a0f9b188018984.png

全景图

现在我们对内存分配的时候发生了什么有了更好的认识。现在将所有的组成部分放在一起来得到全景图:

84355ad99e1c1dca9dbfc9f770604e24.png
编译整理自 Go: Memory Management and Allocationhttps://medium.com/a-journey-with-go/go-memory-management-and-allocation-a7396d430f44

db05ec903f465f389d878919fd3a6e62.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374010.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NYOJ 35表达式求值

表达式求值 时间限制:3000 ms | 内存限制:65535 KB难度:4描述 ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个AB的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请…

Java EE6 CDI,命名组件和限定符

Java EE6的最大承诺之一就是简化了依赖注入的使用。 他们做到了,使用CDI 。 CDI代表Java EE的上下文和依赖注入,它提供了一个基础集,用于在企业应用程序中应用依赖注入。 在CDI之前,EJB 3还引入了依赖注入,但这有点基础…

c#获取当前目录的一些方法

【内容来源地址】:http://www.cnblogs.com/marcozh/archive/2008/10/19/1314667.html Assembly myAssembly Assembly.GetEntryAssembly(); string path myAssembly.Location; DirectoryInfo dr new DirectoryInfo(path); pathd…

linux里的进程简介

/sbin/init 内核启动的第一个用户级进程,引导用户空间服务 [kthreadd] 内核线程管理[migration/0] 用于进程在不同的CPU间迁移[ksoftirqd/0] 内核调度/管理第0个CPU软中断的守护进程[migration/1] 管理多核心[ksoftirqd/1] 内核调度/管…

python画画bup_Python中的高效Vector / Point类

实现高效的Vector / Point类的最佳方法是什么(甚至更好:是否有一个),可以在Python 2.7和3.x中使用?我找到了the blender-mathutils,但它们似乎只支持Python 3.x.然后是this Vector class,使用numpy,但它只是一个3D矢量.使用具有静态属性(x和y)的像kivy’…

CSDN 编程挑战——《coder的计算器》

coder的计算器 题目详情: coder现在已经上初中,也会用计算器实现 ,-,*,/和幂运算^了,但他觉得市场那些计算器太繁琐了,有很多他不认识的符号,所以他现在很想要能计算带括号的 ,-,*,/和幂运算^的混合表达式就可以了,你…

OpenShift Express:部署Java EE应用程序(支持AS7)

在过去的几年中,我越来越听到有关“云”服务的信息。 最初,我并不是很想尝试一下。 但是几个月后(一年?),我决定看看这是怎么回事。 我从事Java EE开发已经超过7年了,所以我决定看看将Java EE应…

07 总结ProgressDialog 异步任务

1,ProgressDialog> //使用对象 设置标题 progressDialog.setTitle("标题"); //设置图标 progressDialog.setIcon(R.drawable.ic_launcher); //设置展示的内容 progressDialog.setMessage(&q…

python函数封装计算n运算_在Python里面怎么可以运算出999999999**999999999,求思路?...

>>> 999999999 * math.log(999999999, 2) / 8 / 1024 ** 33.480509950621777所以这个数字本身就差不多需要3.5GB内存,考虑到计算过程中需要存储临时结果,还需要翻个两三倍吧而Python中的long可以到多少呢:#define MAX_LONG_DIGITS \…

C++中const关键字的使用总结

const是不变的意思,在C程序中,经常用const来限制对一个对象的操作: 1.1 const变量 例如: const int n3; 则这个变量的值不能改变,即不能对变量赋值。 1.2 const参数 出现在函数参数中的const表示在函数体中不能对这个参数做修改…

php封装redis负载均衡类

$array array( master > array( "redis://127.0.0.1:6379?timeout1", ), slave > array( "redis://127.0.0.1:6479?timeout1", "redis://127.0.0.1:6579?timeout1", ) ); $redis R…

我今天对JavaFX的了解

如果您没有听说过,JavaFX 2是Java的新Desktop / web / client框架。 自JavaFX 1以来,它已经进行了相当大的改动(坦率地说,效果并不那么令人印象深刻)。 自定义脚本语言已经淘汰了,您可以使用标准Java和基于…

怎么解决xp系统不能安装NET Framework4.0?

.net 4.0安装不上解决方法: 引用 9 楼 MoreQuestion 的回复: 全部都不行!就是用360软件管家安装那个就可以了。用了楼主的方法,果然可行啊 1.先安装wic。 2.用360安装.net40 本帖最后由 不懂 于 2014-6-6 00:56 编辑Windows Server 2003 如何…

C++内联(inline)函数

内联函数 内联函数是一种特殊类型的函数,内联函数在定义或声明时前面加上“inline”关键字。比如: inline int max(int a,int b) { return (a>b)?a:b; } 内联(inline)是内联扩展(inline expansion)的简…

我的python学习笔记全集_记录我的Python学习笔记

不想再像以前那样,什么都从头开始学习语法、总结语法,这样反而会过分纠结于语法,耽误了开发,毕竟语言的主要属性是工具,次要的属性是语言本身。所以还是先熟练使用语言去进行开发,等足够熟悉了,…

HDU 5794:A Simple Chess(Lucas + DP)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid5794 题意:让一个棋子从(1,1)走到(n,m),要求像马一样走日字型并只能往右下角走。里面还有r个障碍点不能经过或者到达&am…

php源码分析之PHPAPI宏的作用

在PHP源码中,我们经常会看到很多函数前面有个PHPAPI,但这是什么呢? 于是我在php源码/main/php.h中找到了它的定义 #ifdef PHP_WIN32 # include "tsrm_win32.h" # include "win95nt.h" # ifdef PHP_EXPORTS # …

15分钟内开始使用Amazon Web Services和全自动资源调配

在等待一个新项目时,我想学习一些有用的东西。 而且由于在许多项目中我们需要评估和测试正在开发的应用程序的性能,而很少有足够的硬件来生成实际负载,因此我决定学习更多有关按需在云中按需配置虚拟机的知识,即Amazon Web Servic…

解析JVM内存区域组成

在方法(代码块)中定义一个变量时,java就在栈中为这个变量分配JVM内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的JVM内存空间;而在堆中分配的JVM内存由java虚拟机的自动垃圾回收器来管理。…

python打开浏览器后带cookie_Python爬虫使用浏览器的cookies:browsercookie

很多用Python的人可能都写过网络爬虫,自动化获取网络数据确实是一件令人愉悦的事情,而Python很好的帮助我们达到这种愉悦。然而,爬虫经常要碰到各种登录、验证的阻挠,让人灰心丧气(网站:天天碰到各种各样的爬虫抓我们网…