您的位置:

golang数据分析,golang数据分析框架

本文目录一览:

(十一)golang 内存分析

编写过C语言程序的肯定知道通过malloc()方法动态申请内存,其中内存分配器使用的是glibc提供的ptmalloc2。 除了glibc,业界比较出名的内存分配器有Google的tcmalloc和Facebook的jemalloc。二者在避免内存碎片和性能上均比glic有比较大的优势,在多线程环境中效果更明显。

Golang中也实现了内存分配器,原理与tcmalloc类似,简单的说就是维护一块大的全局内存,每个线程(Golang中为P)维护一块小的私有内存,私有内存不足再从全局申请。另外,内存分配与GC(垃圾回收)关系密切,所以了解GC前有必要了解内存分配的原理。

为了方便自主管理内存,做法便是先向系统申请一块内存,然后将内存切割成小块,通过一定的内存分配算法管理内存。 以64位系统为例,Golang程序启动时会向系统申请的内存如下图所示:

预申请的内存划分为spans、bitmap、arena三部分。其中arena即为所谓的堆区,应用中需要的内存从这里分配。其中spans和bitmap是为了管理arena区而存在的。

arena的大小为512G,为了方便管理把arena区域划分成一个个的page,每个page为8KB,一共有512GB/8KB个页;

spans区域存放span的指针,每个指针对应一个page,所以span区域的大小为(512GB/8KB)乘以指针大小8byte = 512M

bitmap区域大小也是通过arena计算出来,不过主要用于GC。

span是用于管理arena页的关键数据结构,每个span中包含1个或多个连续页,为了满足小对象分配,span中的一页会划分更小的粒度,而对于大对象比如超过页大小,则通过多页实现。

根据对象大小,划分了一系列class,每个class都代表一个固定大小的对象,以及每个span的大小。如下表所示:

上表中每列含义如下:

class: class ID,每个span结构中都有一个class ID, 表示该span可处理的对象类型

bytes/obj:该class代表对象的字节数

bytes/span:每个span占用堆的字节数,也即页数乘以页大小

objects: 每个span可分配的对象个数,也即(bytes/spans)/(bytes/obj)waste

bytes: 每个span产生的内存碎片,也即(bytes/spans)%(bytes/obj)上表可见最大的对象是32K大小,超过32K大小的由特殊的class表示,该class ID为0,每个class只包含一个对象。

span是内存管理的基本单位,每个span用于管理特定的class对象, 跟据对象大小,span将一个或多个页拆分成多个块进行管理。src/runtime/mheap.go:mspan定义了其数据结构:

以class 10为例,span和管理的内存如下图所示:

spanclass为10,参照class表可得出npages=1,nelems=56,elemsize为144。其中startAddr是在span初始化时就指定了某个页的地址。allocBits指向一个位图,每位代表一个块是否被分配,本例中有两个块已经被分配,其allocCount也为2。next和prev用于将多个span链接起来,这有利于管理多个span,接下来会进行说明。

有了管理内存的基本单位span,还要有个数据结构来管理span,这个数据结构叫mcentral,各线程需要内存时从mcentral管理的span中申请内存,为了避免多线程申请内存时不断的加锁,Golang为每个线程分配了span的缓存,这个缓存即是cache。src/runtime/mcache.go:mcache定义了cache的数据结构

alloc为mspan的指针数组,数组大小为class总数的2倍。数组中每个元素代表了一种class类型的span列表,每种class类型都有两组span列表,第一组列表中所表示的对象中包含了指针,第二组列表中所表示的对象不含有指针,这么做是为了提高GC扫描性能,对于不包含指针的span列表,没必要去扫描。根据对象是否包含指针,将对象分为noscan和scan两类,其中noscan代表没有指针,而scan则代表有指针,需要GC进行扫描。mcache和span的对应关系如下图所示:

mchache在初始化时是没有任何span的,在使用过程中会动态的从central中获取并缓存下来,跟据使用情况,每种class的span个数也不相同。上图所示,class 0的span数比class1的要多,说明本线程中分配的小对象要多一些。

cache作为线程的私有资源为单个线程服务,而central则是全局资源,为多个线程服务,当某个线程内存不足时会向central申请,当某个线程释放内存时又会回收进central。src/runtime/mcentral.go:mcentral定义了central数据结构:

lock: 线程间互斥锁,防止多线程读写冲突

spanclass : 每个mcentral管理着一组有相同class的span列表

nonempty: 指还有内存可用的span列表

empty: 指没有内存可用的span列表

nmalloc: 指累计分配的对象个数线程从central获取span步骤如下:

将span归还步骤如下:

从mcentral数据结构可见,每个mcentral对象只管理特定的class规格的span。事实上每种class都会对应一个mcentral,这个mcentral的集合存放于mheap数据结构中。src/runtime/mheap.go:mheap定义了heap的数据结构:

lock: 互斥锁

spans: 指向spans区域,用于映射span和page的关系

bitmap:bitmap的起始地址

arena_start: arena区域首地址

arena_used: 当前arena已使用区域的最大地址

central: 每种class对应的两个mcentral

从数据结构可见,mheap管理着全部的内存,事实上Golang就是通过一个mheap类型的全局变量进行内存管理的。mheap内存管理示意图如下:

系统预分配的内存分为spans、bitmap、arean三个区域,通过mheap管理起来。接下来看内存分配过程。

针对待分配对象的大小不同有不同的分配逻辑:

(0, 16B) 且不包含指针的对象: Tiny分配

(0, 16B) 包含指针的对象:正常分配

[16B, 32KB] : 正常分配

(32KB, -) : 大对象分配其中Tiny分配和大对象分配都属于内存管理的优化范畴,这里暂时仅关注一般的分配方法。

以申请size为n的内存为例,分配步骤如下:

Golang内存分配是个相当复杂的过程,其中还掺杂了GC的处理,这里仅仅对其关键数据结构进行了说明,了解其原理而又不至于深陷实现细节。1、Golang程序启动时申请一大块内存并划分成spans、bitmap、arena区域

2、arena区域按页划分成一个个小块。

3、span管理一个或多个页。

4、mcentral管理多个span供线程申请使用

5、mcache作为线程私有资源,资源来源于mcentral。

六星教育:Python和go语言都很火,我要怎么选?

python和go语言有区别:1、Python语法使用缩进来指示代码块;Go语法基于打开和关闭括号;2、Python是基于面向对象编程的多范式语言;Go是基于并发编程范式的过程编程语言。3、Python是动态类型语言,Go是静态类型语言。

Go语言(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态以及 CSP-style 并发计算。

python是一种广泛使用的具有动态语义的解释型,面向对象的高级编程语言。

Python是一种面向对象的高级编程语言,具有集成的动态语义,主要用于Web和应用程序开发。它在快速应用程序开发领域极具吸引力,因为它提供动态类型和动态绑定选项。

Python是一种解释型语言,这意味着用Python编写的程序不需要事先编译就可以运行,从而可以轻松地测试小段代码并使用Python编写的代码更容易在平台之间移动。

python和go语言的区别:

1、语法

Python的语法使用缩进来指示代码块。Go的语法基于打开和关闭括号。

2、范例

Python是一种基于面向对象编程的多范式,命令式和函数式编程语言。它坚持这样一种观点,即如果一种语言在某些情境中表现出某种特定的方式,理想情况下它应该在所有情境中都有相似的作用。但是,它又不是纯粹的OOP语言,它不支持强封装,这是OOP的主要原则之一。

Go是一种基于并发编程范式的过程编程语言,它与C具有表面相似性。实际上,Go更像是C的更新版本。

3、并发

Python没有提供内置的并发机制,而Go有内置的并发机制。

4、类型化

Python是动态类型语言,而Go是一种静态类型语言,它实际上有助于在编译时捕获错误,这可以进一步减少生产后期的严重错误。

5、安全性

Python是一种强类型语言,它是经过编译的,因此增加了一层安全性。Go具有分配给每个变量的类型,因此,它提供了安全性。但是,如果发生任何错误,用户需要自己运行整个代码。

6、管理内存

Go允许程序员在很大程度上管理内存。而,Python中的内存管理完全自动化并由Python VM管理;它不允许程序员对内存管理负责。

7、库

与Go相比,Python提供的库数量要大得多。然而,Go仍然是新的,并且还没有取得很大进展。

8、速度:

Go的速度远远超过Python。

Python与Golang对比:

1、特点:

Golang

①静态强类型、编译型、并发型

静态类型语言,但是有动态语言的感觉。(静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高)

可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。

语言层面支持并发,这个就是Go最大的特色,天生的支持并发。Go就是基因里面支持的并发,可以充分地利用多核,很容易地使用并发。

②垃圾回收机制

内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC(内存垃圾回收机制)不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC。

③支持面向对象编程

有接口类型和实现类型的概念,但是用嵌入替代了继承。

④丰富的标准库

Go目前已经内置了大量的库,特别是网络库非常强大。

⑤内嵌C支持

Go里面也可以直接包含C代码,利用现有的丰富的C库

Python

①解释型语言

程序不需要在运行前编译,在运行程序的时候才翻译,专门的解释器负责在每个语句执行的时候解释程序代码。这样解释型语言每执行一次就要翻译一次,效率比较低。

②动态数据类型 

支持重载运算符,也支持泛型设计。(运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。泛型设计就是定义的时候不需要指定类型,在客户端使用的时候再去指定类型)

③完全面向对象的语言

函数,模块,数字,字符串都是对象,在Python中,一切接对象

完全支持继承,重载,多重继承 

④拥有强大的标准库

Python语言的核心只包含数字,字符串,列表,元祖,字典,集合,文件等常见类型和函数,而由Python标准库提供了系统管理,网络通信,文本处理,数据库接口,图形系统,XML处理等额外的功能。

⑤社区提供了大量第三方库

Python 社区提供了大量的第三方模块,使用方式与标准库类似。它们的功能覆盖 科学计算、人工智能、机器学习、Web 开发、数据库接口、图形系统 多个领域。

2、应用

Python

①网络编程

web应用,网络爬虫

②数据分析和机器学习

③自动化测试

④自动化运维

Golang

①服务器编程

处理日志、数据打包、虚拟机处理、文件系统等。

②分布式系统,数据库代理器等

③网络编程

这一块目前应用最广,包括Web应用、API应用、下载应用。

④内存数据库

如google开发的groupcache,couchbase的部分组件。

⑥云平台

Go语言和Python学哪个好?

Python 可以很好地集成到企业级应用中,可用于机器语言和 AI 应用。Go 语言的特点表明它具备轻量级线程实现(Goroutine)、智能标准库、强大的内置安全性,且可使用最简语法进行编程。Go 在大部分案例中领先,被认为是 Python 的有效替代方案。开发者在选择编程语言时,应考虑开发项目的性质和规模,以及所需的技能组合。

放下个人偏见和喜好,从优点和功能的角度来评价两种语言。不管选择了哪种语言,Go 和 Python 都在持续演进。尽管在大多数情况下 Golang 可能是更好的选择,但Python语言也是不断更新迭代的。以上就是本次分享的全部内容,如果你也想学习一门编程语言,可以考虑下 六星教育 ,这里的课程体系,师资团队以及售后服务,一定不会让你失望!

Golang database/sql源码分析

Gorm是Go语言开发用的比较多的一个ORM。它的功能比较全:

但是这篇文章中并不会直接看Gorm的源码,我们会先从database/sql分析。原因是Gorm也是基于这个包来封装的一些功能。所以只有先了解了database/sql包才能更加好的理解Gorm源码。

database/sql 其实也是一个对于mysql驱动的上层封装。”github.com/go-sql-driver/mysql”就是一个对于mysql的驱动,database/sql 就是在这个基础上做的基本封装包含连接池的使用

下面这个是最基本的增删改查操作

操作分下面几个步骤:

因为Gorm的连接池就是使用database/sql包中的连接池,所以这里我们需要学习一下包里的连接池的源码实现。其实所有连接池最重要的就是连接池对象、获取函数、释放函数下面来看一下database/sql中的连接池。

DB对象

获取方法

释放连接方法

连接池的实现有很多方法,在database/sql包中使用的是chan阻塞 使用map记录等待列表,等到有连接释放的时候再把连接传入等待列表中的chan 不在阻塞返回连接。

之前我们看到的Redigo是使用一个chan 来阻塞,然后释放的时候放入空闲列表,在往这一个chan中传入struct{}{},让程序继续 获取的时候再从空闲列表中获取。并且使用的是链表的结构来存储空闲列表。

database/sql 是对于mysql驱动的封装,然而Gorm则是对于database/sql的再次封装。让我们可以更加简单的实现对于mysql数据库的操作。

golang map源码浅析

golang 中 map的实现结构为: 哈希表 + 链表。 其中链表,作用是当发生hash冲突时,拉链法生成的结点。

可以看到, []bmap 是一个hash table, 每一个 bmap是我们常说的“桶”。 经过hash 函数计算出来相同的hash值, 放到相同的桶中。 一个 bmap中可以存放 8个 元素, 如果多出8个,则生成新的结点,尾接到队尾。

以上是只是静态文件 src/runtime/map.go 中的定义。 实际上编译期间会给它加料 ,动态地创建一个新的结构:

上图就是 bmap的内存模型, HOB Hash 指的就是 top hash。 注意到 key 和 value 是各自放在一起的,并不是 key/value/key/value/... 这样的形式。源码里说明这样的好处是在某些情况下可以省略掉 padding 字段,节省内存空间。

每个 bmap设计成 最多只能放 8 个 key-value 对 ,如果有第 9 个 key-value 落入当前的 bmap,那就需要再构建一个 bmap,通过 overflow 指针连接起来。

map创建方法:

我们实际上是通过调用的 makemap ,来创建map的。实际工作只是初始化了hmap中的各种字段,如:设置B的大小, 设置hash 种子 hash 0.

注意 :

makemap 返回是*hmap 指针, 即 map 是引用对象, 对map的操作会影响到结构体内部 。

使用方式

对应的是下面两种方法

map的key的类型,实现了自己的hash 方式。每种类型实现hash函数方式不一样。

key 经过哈希计算后得到hash值,共 64 个 bit 位。 其中后B 个bit位置, 用来定位当前元素落在哪一个桶里, 高8个bit 为当前 hash 值的top hash。 实际上定位key的过程是一个双重循环的过程, 外层循环遍历 所有的overflow, 内层循环遍历 当前bmap 中的 8个元素 。

举例说明: 如果当前 B 的值为 5, 那么buckets 的长度 为 2^5 = 32。假设有个key 经过hash函数计算后,得到的hash结果为:

外层遍历bucket 中的链表

内层循环遍历 bmap中的8个 cell

建议先不看此部分内容,看完后续 修改 map中元素 - 扩容 操作后 再回头看此部分内容。

扩容前的数据:

等量扩容后的数据:

等量扩容后,查找方式和原本相同, 不多做赘述。

两倍扩容后的数据

两倍扩容后,oldbuckets 的元素,可能被分配成了两部分。查找顺序如下:

此处只分析 mapaccess1 ,。 mapaccess2 相比 mapaccess1 多添加了是否找到的bool值, 有兴趣可自行看一下。

使用方式:

步骤如下:

扩容条件 :

扩容的标识 : h.oldbuckets != nil

假设当前定位到了新的buckets的3号桶中,首先会判断oldbuckets中的对应的桶有没有被搬迁过。 如果搬迁过了,不需要看原来的桶了,直接遍历新的buckets的3号桶。

扩容前:

等量扩容结果

双倍扩容会将old buckets上的元素分配到x, y两个部key 1 B == 0 分配到x部分,key 1 B == 1 分配到y部分

注意: 当前只对双倍扩容描述, 等量扩容只是重新填充了一下元素, 相对位置没有改变。

假设当前map 的B == 5,原本元素经过hash函数计算的 hash 值为:

因为双倍扩容之后 B = B + 1,此时B == 6。key 1 B == 1, 即 当前元素rehash到高位,新buckets中 y 部分. 否则 key 1 B == 0 则rehash到低位,即x 部分。

使用方式:

可以看到,每一遍历生成迭代器的时候,会随机选取一个bucket 以及 一个cell开始。 从前往后遍历,再次遍历到起始位置时,遍历完成。

golang数据分析,golang数据分析框架

2022-11-26
golang三大基础,golang语言和go

2022-11-26
golang大数据,golang大数据开发

2022-11-28
golang大数据,golang大数据导出excel

2022-11-27
golang脚本,go语言脚本

2022-11-27
golang服务器框架,golang 开源协议

2022-11-27
golang赛车源码,golang标准库源码分析

2022-11-28
golang框架编写,Golang 框架

2022-11-27
大厂Golang框架,golang主流框架

2022-11-28
golang的事物框架,golang 结构

2022-11-27
golang处理大数据,golang 大数据

本文目录一览: 1、golang适合做web开发吗 2、Golang解析json的特殊情况处理 3、【golang】海量数据去重-布隆过滤器 golang适合做web开发吗 golang适合做web开

2023-12-08
golang应用,golang应用框架

本文目录一览: 1、Go语言的应用 2、bpftrace动态追踪golang应用-函数内联问题 3、go语言适合做什么 4、Golang入门到项目实战 | 第一个golang应用 Go语言的应用 Go

2023-12-08
golang怎么写微服务,golang微服务框架有哪些

2022-11-26
golang框架设置,golangweb框架

2022-11-27
大厂用的golang框架,golang 大厂

2022-11-27
golangweb框架,golang web 框架

2022-11-27
golangc,golang测试框架

本文目录一览: 1、想学习一门新语言,golang 和 C++ 哪个是更好的选择 2、golang是什么意思? 3、golang c.cstring 返回的是什么类型 4、如何在golang 中调用c

2023-12-08
golang数据结构库,golang数据结构与算法

2022-11-27
golang常用命令,Golang语法

2022-11-27
golang学习小组,golang 教程 pdf

2022-11-27