Go语言中文网 为您找到相关结果 136

golang 内存分配

golang 的内存分配类似于tcmalloc(全局缓存堆和进程所属私有缓存)内存分配策略,大致采用三层内存分配模式。其中主要分为mheap, mCentral, mCache.mheap:直接向操作系统申请内存,申请对象以页为基础单位,同时还负责大内存的直接分配。mCentral:作为上级mheap, 下级mCache的中间项,起承上启下的作用, 当下级mCache内存不够时,mCache向mCentral申请,mCentral不够时,向mheap申请。mCache:与MPG并发调度模型中的P关联,每个P拥有一个mCache,由于单个P每个时刻只能调度一个goroutine,所以不存在多个goroutine同时共享一个mCache,也避免了分配内存时候的加锁。mCache主要负责小对象的内...阅读全文

博文 2019-08-09 00:32:55 SuperGopher

Go语言中映射表map的使用

1 概述 Go语言中的键值对(key->value)集合,称之为映射map。映射map是变长类型,定义时不需要指定长度。映射map是无序的,遍历是的顺序不可期,原因是底层由hash表实现。逻辑结构表示为: 2 创建语法 var m = map[key_type]value_type{key1: value1, key2: value2} var m = make(map[key_type]value_type) // 示例,字符串型下标,字符串型值: var m = make(map[string]string) //make()会分配内存空间,初始化。 m["east"] = "东" m["west"] = "西" // 直接初始化 var m = map[string]string{"e...阅读全文

博文 2018-10-31 16:35:28 小韩说课

图解Golang的内存分配

一般程序的内存分配 在讲Golang的内存分配之前,让我们先来看看一般程序的内存分布情况: 以上是程序内存的逻辑分类情况。 我们再来看看一般程序的内存的真实(真实逻辑)图: Go的内存分配核心思想 Go是内置运行时的编程语言(runtime),像这种内置运行时的编程语言通常会抛弃传统的内存分配方式,改为自己管理。这样可以完成类似预分配、内存池等操作,以避开系统调用带来的性能问题,防止每次分配内存都需要系统调用。 Go的内存分配的核心思想可以分为以下几点: 每次从操作系统申请一大块儿的内存,由Go来对这块儿内存做分配,减少系统调用 内存分配算法采用Google的TCMalloc算法。算法比较复杂,究其原理可自行查阅。其核心思想就是把内存切分的非常的细小,分为多级管理,以降低锁的粒度。 回收对象...阅读全文

博文 2019-06-10 12:34:28 RyuGou

图解 TCMalloc

-- 前言 -- TCMalloc ( http://link.zhihu.com/?target=http%3A//goog-perftools.sourceforge.net/doc/tcmalloc.html ) 是 Google 开发的内存分配器,在不少项目中都有使用,例如在 Golang 中就使用了类似的算法进行内存分配。它具有现代化内存分配器的基本特征:对抗内存碎片、在多核处理器能够 scale。据称,它的内存分配速度是 glibc2.3 中实现的 malloc的数倍。 之所以学习 TCMalloc,是因为在学习 Golang 内存管理的时候,发现 Golang 竟然就用了鼎鼎大名的 TCMalloc,而在此之前虽然也对内存管理有过一些浅薄的了解,但一直没有机会深入。因此借此机会...阅读全文

博文 2017-09-14 06:08:50 hellocode

剖析使Go语言高效的5个特性(3/5): 垃圾回收机制

翻译原文链接 转帖/转载请注明出处 英文原文链接 发表于2014/06/07 垃圾回收机制(Garbage Collection) Go语言因为强制的内存垃圾回收机制变得更加简单和安全。但这并不意味着垃圾回收机制把Go程序变慢了,或者说垃圾回收机制最终决定了你程序的速度。不可否认,在堆(heap)上分配内存是有代价的。每次垃圾回收机制触发都会消耗一定的CPU。除非内存都被释放了,这些开销是不可避免的。 但是还有另外一个地方我们可以用来分配内存。那就是栈(stack)。 与C语言不同,Go语言不需要你选择一个变量是分配在堆上(通过malloc),还是栈上(通过将这个变量定义成函数内的局部变量)。Go语言实现了一个叫做逃逸分析(Escape Analysis)的优化技术。 逃逸分析能够判断是否有...阅读全文

博文 2017-08-13 05:34:58 曼托斯

Go语言内存分配器-MSpan

Go语言内存分配器-MSpan 11 October 2013 skoo 阅读 713 次 0 人喜欢 0 条评论 收藏 MSpan和FixAlloc一样,都是内存分配器的基础工具组件,但和FixAlloc没太大的交集,各自发挥功效而已。span(MSpan简称span)是用来管理一组组page对象,先解释一下page,page就是一个4k大小的内存块而已。span就是将这一个个连续的page给管理起来,注意是连续的page,不是东一个西一个的乱摆设的page。为了直观形象的感受一下span,还是得画个图吧,图形是最好的交流语言。 MSpan结构定义在malloc.h头文件中,代码如下: struct MSpan { MSpan *next; // in a span linked list...阅读全文

博文 2016-04-11 16:00:01 caoshulin1989

图解Go语言内存分配

Go语言内置运行时(就是runtime),抛弃了传统的内存分配方式,改为自主管理。这样可以自主地实现更好的内存使用模式,比如内存池、预分配等等。这样,不会每次内存分配都需要进行系统调用。 Golang运行时的内存分配算法主要源自 Google 为 C 语言开发的TCMalloc算法,全称Thread-Caching Malloc。核心思想就是把内存分为多级管理,从而降低锁的粒度。它将可用的堆内存采用二级分配的方式进行管理:每个线程都会自行维护一个独立的内存池,进行内存分配时优先从该内存池中分配,当内存池不足时才会向全局内存池申请,以避免不同线程对全局内存池的频繁竞争。 基础概念 Go在程序启动的时候,会先向操作系统申请一块内存(注意这时还只是一段虚拟的地址空间,并不会真正地分配内存),切成小...阅读全文

博文 2019-06-04 23:32:39 Stefno

图解Go语言内存分配

目录 基础概念 内存管理单元 内存管理组件 mcache mcentral mheap 内存分配流程 总结 参考资料 Go语言内置运行时(就是runtime),抛弃了传统的内存分配方式,改为自主管理。这样可以自主地实现更好的内存使用模式,比如内存池、预分配等等。这样,不会每次内存分配都需要进行系统调用。 Golang运行时的内存分配算法主要源自 Google 为 C 语言开发的TCMalloc算法,全称Thread-Caching Malloc。核心思想就是把内存分为多级管理,从而降低锁的粒度。它将可用的堆内存采用二级分配的方式进行管理:每个线程都会自行维护一个独立的内存池,进行内存分配时优先从该内存池中分配,当内存池不足时才会向全局内存池申请,以避免不同线程对全局内存池的频繁竞争。 基础概...阅读全文

博文 2019-05-22 15:26:26 qcrao-2018

Go ARM64 Map优化小记

Go内置了map类型,而其中重要的哈希算法是一个cityhash的变种。 同时,为了避免哈希冲突攻击(collision attack)和加速哈希计算速度,Keith Randall于Go1.0中就添加了x86_64支持的有硬件加速的AESHASH算法。 我搜遍了互联网,惊讶地发现,这个算法仅仅在Go里面有实现,这思路真是绝了。 这就被我这个四处搜索ARM64 Go runtime待优化点的人找到了:ARM64也支持AESHASH的硬件加速指令,但是Go并没有用上。 我嘴角又微微地一笑,满心欢喜准备加代码。可我并不知道,这看似平静的海面下不知道藏着什么妖怪…...阅读全文

博文 2018-03-16 17:15:38 zhuo/blog

Golang 数据结构:链表

Golang 中链表的实现及常用操作,数据结构系列原文:flaviocopes.com,翻译已获作者授权。 前言链表的结构类似于数组,但插入元素的代价比数组小得多,因为在数组中插入元素,需要把插入位置后边所有的元素后移一个位置,删除元素则要全部前移。 数组将元素顺序存储在内存单元中(静态分配内存),而链表是通过元素中的指针,将元素存储在零散的内存中(动态分配内存) 链表相比数组有个明显的缺点:查找元素时不知道元素在链表中的地址,需要从第一个元素开始遍历整条链表来寻找。 链表结构基本操作:12345678Append(t) // 将元素 t 追加到链表尾部Insert(i, t) // 在位置 i 处插入元素 tRemoveAt(i) // 移除位置 i 的元素IndexOf(t) // 返回...阅读全文

博文 2018-03-15 10:58:54 wuYinBlog

Go 语言方法接受者类型的选择

概述 很多人(特别是新手)在写 Go 语言代码时经常会问一个问题,那就是一个方法的接受者类型到底应该是值类型还是指针类型呢,Go 的 wiki 上对这点做了很好的解释,我来翻译一下。 何时使用值类型 如果接受者是一个 map,func 或者 chan,使用值类型(因为它们本身就是引用类型)。如果接受者是一个 slice,并且方法不执行 reslice 操作,也不重新分配内存给 slice,使用值类型。如果接受者是一个小的数组或者原生的值类型结构体类型(比如 time.Time 类型),而且没有可修改的字段和指针,又或者接受者是一个简单地基本类型像是 int 和 string,使用值类型就好了。 一个值类型的接受者可以减少一定数量的垃圾生成,如果一个值被传入一个值类型接受者的方法,一个栈上的拷...阅读全文

博文 2016-03-23 15:00:01 kai_ding

聊聊Golang中的make和new

概述 根据官方文档描述 make是用来分配并且初始化slice,map,chan等类型的对象 new也是用来分配内存的,返回对应内向的0值的指针,但并不初始化对象 看下面例子,就很明显了 a := new([]int) b := make([]int,1) fmt.Println(a) fmt.Println(b) fmt.Println(unsafe.Sizeof(*a)) fmt.Println(unsafe.Sizeof(b)+unsafe.Sizeof([1]int{})) output: &[] [0] 24 32 make make在初始化不同类型对象时,会调用不同的函数. make slice时会调用 runtime.makeslice make map时会调用 runtime...阅读全文

博文 2019-05-28 23:34:38 say_leo

golang 内存分配器

背景 go的很多东西是内敛的,提倡大道至简,但是,我们也看到过对于一些对性能要求比较高的业务场景(比如游戏的某些业务场景),使用cgo等技术手段来绕过go的垃圾回收。所以说,我们不要把所有的目光都盯到那95%上,依然还有5%的情况是需要我们来处理的。即便在今天来看,内存依然是非常紧缺的资源,那么我们可以想象一下,如何管理和分配内存资源,这是一个非常有挑战的话题。 下面我们来看一下这段代码,看看内存究竟发生来什么。 package main func A() *int { x := 100 return &x } 但是如果有c语言经验的人,会知道这个代码是有问题的,我们来简单测试一下这个代码。 package main import "testing" func BenchmarkA (b *...阅读全文

博文 2018-07-07 13:34:43 wolf4j

Go 内存管理

内存管理缓存结构Go实现的内存管理采用了tcmalloc这种架构,并配合goroutine和垃圾回收。tcmalloc的基本策略就是将内存分为多个级别。申请对象优先从最小级别的内存管理集合mcache中获取,若mcache无法命中则需要向mcentral申请一批内存块缓存到本地mcache中,若mcentral无空闲的内存块,则向mheap申请来填充mcentral,最后向系统申请。 mcache + mspan最小级别的内存块管理集合mcache由goroutine自己维护,这样从中申请内存不用加锁。它是一个大小为67的数组,不同的index对应不同规格的mspan。newobject的时候通过sizetoclass计算对应的规格,然后在mcache中获取mspan对象。 123type ...阅读全文

博文 2017-12-18 13:34:54 nino's blog

go-内存分配器

整合两个文章,FixAlloc 和 MSpan。 内存模型如下: FixAlloc FixAlloc称不上是核心组件,辅助实现整个内存分配器核心的一个基础工具。引入FixAlloc的目的只是用来分配MCache和MSpan两个特定的对象,所以内存分配器中有spanalloc和cachealloc两个组件。MCache和MSpan两个结构在malloc.h中有定义。 定义在malloc.h文件中的FixAlloc结构如下,比较关键的三个字段是alloc、list和chunk,其他的字段主要都是用来统计一些状态数据的,比如分配了多少内存之类。 struct FixAlloc { uintptr size; void *(*alloc)(uintptr); void (*first)(void *...阅读全文

博文 2016-02-18 22:00:00 lmxmimihuhu

golang内存清理

一、清理 当垃圾标记完成后,接着就以内存块(span)为单位进行清理操作;其实这里会带来一个疑问:是不是要挨个检查所有的内存单元,然后在一一清理。在理解这个东西之前需要看看mspan的结构 type mspan struct{ // 代表一个内存块 //... gcmarkBits *gcBits // 标记位图; 对应的object标记为垃圾 等待清理 allocBits *gcBits // 分配位图; 对应的内存块object使用情况 //... } 通过上面的源码可以看到有一个垃圾标记位图(gcmarkBits),垃圾回收器以此标记出可回收,也就是可被复用的内存位置(golang分配的内存块当在进行垃圾回收时,并不会直接归还给操作系统,而是完成清理后归还给central中间部件,以便...阅读全文

博文 2019-01-08 19:34:46 神奇的考拉

11.蛤蟆笔记go语言——内存分配器

11.蛤蟆笔记go语言——内存分配器 内存分配器,又叫做MemoryAllocator. 核心:自主管理,缓存复用,无锁分配。 内存管理以页为基本单位,多个地址连续页构成内存块。 页是page, 连续页是span. 按 8 倍数,将小对象分成多种大小规格。size class. 三级管理机构 三级管理机构如下图1: 算法依赖连续地址,预留较大地址空间。如下图2: 按页保存 span指针。 反查 object 所属 span。 检查相邻 span 是否可合并。 快速分配,按需扩张。 如下图3: 垃圾回收 垃圾回收器引发回收操作。如下图4: 为管理对象分配内存,不占用预留地址 图5...阅读全文

博文 2016-06-19 23:00:01 notbaron

简析Go与Java内存管理的差异

前 言 从实践中看,Golang(以下简称Go)应用程序比Java占用更少的内存,这与它们的运行时环境有关,其运行时自带了内存动态分配和自动垃圾回收的管理机制,本文通过分析Go与Java在内存管理机制上的差异,以期对两者在运行时内存方面有更进一步的认识。本文以Go(1.12)和当前使用较多的JDK8 HotSpot VM为例进行说明。本篇文章包含以下内容:介绍Go与Java的运行时内存结构差异介绍Go与Java的内存资源占用差异介绍Go与Java如何为对象分配内存介绍Go与Java的内存回收策略差异内存结构差异应用程序要能在linux系统上运行(其他平台类似),其可执行文件要求符合ELF规范(Executable and Linkable Format,可执行和可链接格式)。操作系统加载目标...阅读全文

博文 2019-06-11 19:59:01 咪付

golang内存扩容

一、内存构成 内存管理组件构成 二、扩容 一般来说当内存空间span不足时,需要进行扩容。而在扩容前需要将当前没有剩余空间的内存块相关状态解除,以便后续的垃圾回收期能够进行扫描和回收,接着在从中间部件(central)提取新的内存块放回数组中。 // 根据空间规格 获取对应的索引 再获取alloc数组中对应的span func (c *mcache) refill(spc spanClass){ s := c.alloc[spc] if s != &emptymspan{ s.incache = false} // 解除当前span的状态 s = mheap_.central[spc].mcentral.cacheSpan // 从中间部件获取新的span c.alloc[spc] = s ...阅读全文

博文 2019-01-08 17:34:52 神奇的考拉

go语言基础

运行:go run xxx.go 编译:go build xxx.go 生成可执行文件 程序开始:package main 引入包:import “fmt” 或者 import ( “fmt" “os" ) 注意:Println不支持,Printf才支持%式的输出 变量和常量: 在函数外声明变量用:var a 或者 var ( a int b str = “hi" ) 在函数里用: := 声明,如 t := 10 注:在go里,声明变量可以不声明类型,可以通过值来自动推断 常量定义 : 用const关键字 const s string = “hi” 或者 const( s string = “hi" pi float32 = 3.1415926 ) 数组: var a [5]int 定义长度...阅读全文

Golang 方法接收者是值还是指针问题

对于普通结构体作为接收者,值和指针并没有区别。 (以下代码摘抄自Go In Action 中文版) type defaultMatcher struct{} // 方法声明为使用 defaultMatcher 类型的值作为接收者 func (m defaultMatcher) Search(feed *Feed, searchTerm string) // 声明一个指向 defaultMatcher 类型值的指针 dm := new(defaultMatch) // 编译器会解开 dm 指针的引用,使用对应的值调用方法 dm.Search(feed, "test") // 方法声明为使用指向 defaultMatcher 类型值的指针作为接收者 func (m *defaultMatcher...阅读全文

博文 2018-06-07 15:30:02 gardenofhu

译文:Go 内存分配器可视化指南

译文:Go 内存分配器可视化指南 Sat 23 February 2019 当我第一次开始尝试理解 Go 语言的内存分配器时,整个过程让我抓狂。一切看起来都像一个神秘的黑盒子。因为几乎所有技术魔法(technical wizardry)都隐藏在抽象之下,所以你需要一层一层的剥离才能去理解它。 我们将通过这篇文章来一层层的剥离这些细节。如果你想学习所有关于 Go 内存分配器的知识,那么这篇文章正适合你。 物理内存和虚拟内存 每一个内存分配器都需要运行在由底层操作系统管理的虚拟内存空间(Virtual Memory Space)之上。 下图是一个物理内存单元(Physical Memory Cell)的简要说明(非精准) 一个内存单元的概述经过大大简化之后描述如下: 地址线(Address li...阅读全文

博文 2019-06-10 15:49:26 www.linuxzen.com

Go内存管理之TCMalloc

自公众号:灰子学技术,原文链接:https://mp.weixin.qq.com/s/-b26YiHjL3V9CNvk0LZmEgTCMalloc作为Go语言内存管理的核心算法,是理解和掌握Go的内存管理非常重要的一步,本章主要介绍TCMalloc的是什么样子的。TCMalloc的概述TCMalloc全称是Thread-Caching Malloc,是Google 开发的内存分配器,在不少项目中都有使用,例如在 Golang 中就使用了类似的算法进行内存分配。它具有现代化内存分配器的基本特征:对抗内存碎片、在多核处理器能够 scale。1. TCMalloc相比glibc 2.3而言内存分配更快。2.TCMalloc对于多线程程序而言,减少了锁机制,对于小对象而言,可以说没有锁的操作,对于大...阅读全文

博文 2020-01-27 17:08:32 ZhDavis

Go内存管理源码浅析

前一篇讲了Go的调度机制和相关源码,这里说一下内存的管理,代码片段也都是基于Go 1.12。 简要的背景 一个程序要运行起来,操作系统会分配一块很大的虚拟内存(或者说虚拟空间)供使用,程序实际可能只使用很小的物理内存。可以通过ps去查看vss(虚拟)和rss(实际)的部分。 虚拟内存空间一般会分为代码段,数据段,堆,栈等: 内存分段 程序执行时,函数中定义的各种变量,一般位于堆和栈中(上图中黄色、绿色、白色)部分。为了能动态分配内存,让程序运行过程中灵活使用,操作系统提供了很多相关函数,例如mmap/munmap,brk/sbrk,madvise,set_thread_area/get_thread_area等。C语言中malloc,free就是对这些基础函数的封装。 而其他高层语言中,例如...阅读全文

博文 2019-05-25 22:34:48 EagleChan

golang之旅--数据类型之字符串

背景 学习go已经有很长一段时间了,对于它的数据类型还没有更加深入的了解,这里做一下对数据类型的总结,第一篇是字符串的介绍。 golang中的字符串 func stringDemo() { str := "李阳" //len函数返回的是字节长度 fmt.Println(len(str)) //utf8的RuneCountInString判断的是ASCII长度 fmt.Println(utf8.RuneCountInString(str)) } 字符串拼接 在java中我们拼接字符串一般怎么做?用加号拼接、用StringBuffer、用StringBuilder。相对的在go中也有好几种方法,每种方法性能不一。 通过+进行字符串拼接 在go语言中,string在内存中的存储结构是长度固定的字节...阅读全文

图解golang内存分配

前言 我们知道所有程序运行都需要使用内存,而内存的管理和分配又是非常重要的,它决定了你的程序能不能在有限的资源内跑的更快。可以设想一下,如果你自己来设计的一个内存分配的规则,会遇到什么问题呢?如果你有了一大块内存你要怎么去合理的分配和使用呢?今天我们通过几张图来看看golang中的内存分配是怎样的。 前置知识:对golang的GPM模型有所了解,对GC有一定的了解,有助于你理解下面的内容。 想一想 我们首先来想一下,如果我们自己来分配内存的时候可能会遇到什么问题。 我想要512G,你能给吗? 操作系统的内存不是你想要多少就给你多少的。比如我跟操作系统说我要512G内存,你赶紧给我,不给我我就掐死你,如果你是操作系统,是不是立马就想把我给结束了? 能随便分割吗? 如果我拿到一块内存,挺大的,你...阅读全文

博文 2019-11-09 16:32:51 更多精彩内容Go内存分配机制总结adrian920Go内存分配机制-TCMalloc链人成长chainerup(十一)golang 内存分析杰克慢图解Golang的内存分配RyuGou图解Go语言内存分配ddu_sw

Golang new() 和 make() 的区别

二者看起来没有什么区别,都在堆上分配内存,但是它们的行为不同,适用于不同的类型。 new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体;它相当于 &T{} 。 make(T) 返回一个类型为 T 的初始值,它只适用于3种内建的引用类型:切片、map 和 channel(参见第 8 章,第 13 章)。 换言之,new 函数分配内存,make 函数初始化;下图给出了区别:
通过实验,可以更清楚的查看两者之间的区别 package main import "fmt" func main() { p := new([]int) //p == nil; with le...阅读全文

博文 2017-08-01 01:06:13 iCaptain

golang new和make的区别

Go语言中new和make都是用来内存分配的原语(allocation primitives)。简单的说,new只分配内存,make用于slice,map,和channel的初始化。 new new(T)函数是一个分配内存的内建函数。 我们都知道,对于一个已经存在变量,可对其指针进行赋值。 示例 var p int var v *int v = &p *v = 11 fmt.Println(*v) 那么,如果不是已经存在的变量会如何呢?能对其直接赋值吗? 示例 var v *int *v = 8 fmt.Println(*v) 结果会报如下错误 panic: runtime error: invalid memory address or nil pointer dereference[si...阅读全文

博文 2019-04-24 09:34:41 guyan0319

Go:内存管理分配

![Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.](https://raw.githubusercontent.com/studygolang/gctt-images2/master/20191103-Go-Memory-Management-and-Allocation/cover.png) ℹ️ *这篇文章基于 Go 1.13。* 在内存从分配到回收的生命周期中,内存不再被使用的时候,标准库会自动执行 Go 的内存管理。虽然开发者不必操心这些细节,但是 Go 语言所做的底层管理经过了很好的优化,同时有很多有趣的概念。 ## 堆...阅读全文

leetcode刷题记录Array篇(26&27~Remove Element)

26.Remove Duplicates from Sorted Array 题目:Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this in place with constant memory. 翻译:给定一个排序好了的数组,删除重复的位置,使每个元素只显示一次并返回新的长度。不要为另一个数组分配额外的空间,您必须使用常量内存来进行此操作。 思路:就是去除数组中重复的数,不过要求...阅读全文

博文 2017-04-24 12:54:00 L千年老妖

Golang 中 slice cap 增长模式小记

h3l · 2020-01-13 00:43:30 在 Golang 中,我们知道数组是固定长度的。一般我们在使用时,大多数情况下使用的其实都是 slice,但是 slice 的底层的数据其实还是数组。所以我们在向 slice append 数据的时候,Golang 会检查底层的数组的长度是否已经不够,如果长度不够,Golang 则会新建一个数组,把原数组的数据拷贝过去,再将 slice 中的指向数组的指针指向新的数组。 但是,新数组的长度该如何确定呢?如果每次新数组长度只增加 1,那么每次 append 数据都需要新建一个数组。但是如果每次新增数组的长度太大的,又会造成内存的浪费。先写一个简单的代码看看内存如何增长。 package main import ( "fmt" ) func m...阅读全文

博文 2020-03-12 11:13:24 h3l.github.io

区块链矿池的分配模式

### 作者介绍 JouyPub 技术经理 某互联网公司 ### 产生背景   当下各种以挖矿来获得收益的币种,随着时间的推移,挖矿的难度也越来越大,如果仍然靠单机去挖矿,几乎已经不可能了,所以就有矿池。例如按照当前的算力(20EH/s),一个20TH/s的矿机,挖到一个区块的时间为19年,也就是说如果单机挖矿需要19年才能获得奖励,这其中还不包括机器损耗、难度增大等因素,所以只有大家加入到一个矿池,共享自己的算力,爆块后,根据不同的分配模式,奖励再分配给个人。这种挖矿模式可以让个人的收益更加稳定,对于矿池而言,也会收取一些交易手续费。 顺便我们来算下现在挖矿多少天能回本。以蚂蚁矿机为例,每台的算力大概为20TH/s,功率1700W,成本取5000元,全网算力取20EH/s,当前爆块奖励为1...阅读全文

博文 2018-09-22 00:19:26 chongdongshequ

Go: GC 是怎样监听你的应用的?

![](https://raw.githubusercontent.com/studygolang/gctt-images2/master/20191002-Go-How-Does-the-Garbage-Collector-Watch-Your-Application/1.png)

Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

> 这篇文章是基于 Go 的 *1.13* 版本 Go 语言的垃圾收集器 (下文简称 GC )能够帮助到开发者,通过自动地释放掉一些程序中不再需要使用的内存。但...阅读全文

golang-interface{} 类型使用

interface{} 表示可以接纳所有的类型 未使用 interface{} 类型 package queue // 声明一个类型 Queue 类型,这个类型是用 []int 切片实现的 type Queue []int // 添加元素 func (q *Queue) Push(v int) { // 这里使用指针,才可以把数据真正的添加进去,共外部可用 *q = append(*q, v) } // 弹出顶层元素 func (q *Queue) Pop() int { // 获取最顶层元素 head := (*q)[0] // 把顶层元素剔除 *q = (*q)[1:] return head } // 判断是否有值, 是否为empty func (q *Queue) IsEmpty()...阅读全文

博文 2019-12-17 22:32:44 爱吃豆包

STL string与Go string

P.S. 这里不讨论COW(copy-on-write)和SSO(short-string-optimization) STL string(gcc 4.9.3) 通过源码可以发现,std::string继承与basic_string模板,而basic_string中仅包含_Alloc_hider _M_dataplus一个非静态变量,而_Alloc_hider仅包含一个指针,所以sizeof(string)可能会出乎你的意料。 class basic_string { //统计信息结构 struct _Rep_base { size_type _M_length; //长度 size_type _M_capacity; //能力 _Atomic_word _M_refcount; //引用...阅读全文

博文 2017-09-14 06:07:49 Love语鬼

golang 数据二 (切片)

在项目开发过程中,更多的场景是需要一个长度可以动态更新的数据存储结构,切片本身并非是动态数组或数组指针,他内部通过指针引用底层数组,并设定相关属性将数据读写操作限定在指定区域内。比如:/runtime/slice.go type slice struct { array unsafe.Pointer len int cap int }切片初始化切片有两种基本初始化方式:切片可以通过内置的make函数来初始化,初始化时len=cap,一般使用时省略cap参数,默认和len参数相同,在追加元素时,如果容量cap不足时,将按len的2倍动态扩容。通过数组来初始化切片,以开始和结束索引位置来确定最终所引用的数组片段。//make([]T, len, cap) //T是切片的数据的类型,len表示le...阅读全文

博文 2017-02-10 10:23:32 100018

golang接口的使用(练习一)

在go语言中,一个类只要实现了接口要求的所有函数,我们就说这个类实现了这个接口。golang接口赋值实现方式一:将对象实例赋值给接口 package main import "fmt" //定义一个Animal接口,实现飞和跑的功能 type Animal interface { Fly() Run() } //定义一个Bird类 type Bird struct { } //通过类实现接口的函数功能 func (bird Bird) Fly() { fmt.Println("the bird is flying!!!") } func (bird Bird) Run() { fmt.Println("the bird is running!!!") } func main() { // 声...阅读全文

博文 2018-10-22 22:35:42 PowerMichael

想获取唯一ID?常见发号器、ID分配器方案对比介绍

发号器应具有的特性: 发号器作为一个独立的系统对外提供服务、满足高可用、高并发、弱依赖、不存在单点问题 服务自我监控与治理 现有系统接入成本低 ID具有唯一性:不能出现重复的ID号 趋势递增 实现方案目前常见的发号器实现方案如下1.UUID UUID(Universally Unique Identifier)的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000。 优点: 性能非常高:本地生成,没有网络消耗。 缺点: 不易于存储:UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。 信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,...阅读全文

博文 2020-04-14 17:33:39 Charles_Wong

Go:我应该用指针替代结构体的副本吗?

![logo](https://raw.githubusercontent.com/studygolang/gctt-images/master/go-should-i-use-a-pointer-instead-of-a-copy-of-my-struct-44b43b104963/1_IO4bo74w6aX7rKC_spjmvw.png) 对于许多 `golang` 开发者来说,考虑到性能,最佳实践是系统地使用指针而非结构体副本。 我们将回顾两个用例,来理解使用指针而非结构体副本的影响。 ## 1. 数据分配密集型 让我们举一个简单的例子,说明何时要为使用值而共享结构体: ```go type S struct { a, b, c int64 d, e, f string g, h, i...阅读全文

博文 2019-07-08 21:46:07 polaris

Golang引用类型

引用类型包含 slice、map、channel 内置函数:new 为其分配零值内存 并返回指针 make 为其分配内存初始化结构 并返回对象 package main import ( "fmt" ) func main() { a := make([]int, 3) a[1] = 10 b := new([]int) b[1] = 20 //error : invalid operation: b[1] (type *[]int does not support indexing) ...阅读全文

博文 2016-09-07 07:00:03 lt695981642

golang pprof

基本路径:/debug/pprof/ 支持的分析类型: cpu(CPU Profiling): HOST/debug/pprof/block,查看导致阻塞同步的堆栈跟踪 goroutine:HOST/debug/pprof/heap,查看活动对象的内存分配情况 mutex(Mutex Profiling):HOST/debug/pprof/threadcreate,查看创建新OS线程的堆栈跟踪 启动 PProf 可视化界面 方法一: go tool pprof -http=:8080 cpu.prof 方法二: go tool pprof cpu.prof we...阅读全文

博文 2019-03-22 14:35:13 凯文不上班

go数组、切片

数组 package main import "fmt" func main() { /*数组的声明 * 1、var ab [2]int 2、var bc 3、cd := [2]int{} [3]int{1, 2} [5]int{4: 1} [...]int{4: 1} [...]int{4, 1, 3} [...]int{0: 4, 1: 1, 2: 3} */ var a [2]string fmt.Println(a) var ab [2]int = [2]int{} fmt.Println(ab) var bc = [2]int{1, 2} fmt.Println(bc) c := [3]int{} fmt.Println(c) b := [3]int{1, 2} fmt.Print...阅读全文

博文 2016-11-09 11:00:03 u013210620

高效地使用字符串(Golang)

字符串是不可变字节(byte)序列,默认值是"",而不是nil。 使用 “`” 定义的原始字符串(raw strubg),支持跨行。字符串支持 !=、==、<、>、+、+= 操作符。允许以索引号访问字节数组,但不能获取元素地址。 使用 for 遍历字符串时,分 byte 和 rune 两种方式。 转换 修改字符串,需将其转换为可变类型([]byte 或 []rune),待完成后再转换回来。这个过程将重新分配内存,并复制数据。这个转换过程有一定的性能损失。要想获得更好的性能可以使用 “非安全” 的方式进行改善。 func bytesToString(bs []byte) string { return *(*string)(unsafe.Pointer(&bs)) } 亦可以用同样的方式将 s...阅读全文

博文 2017-08-03 12:34:55 勿以浮沙筑高台

golang 1.9 新特性预览:Logging, interfaces, and allocation

该文翻译自:http://commaok.xyz/post/interface-allocs/几个星期前,Peter Bourgon在golang-dev开了一个关于标准化日志记录的帖子。 日志很常用,因此性能很快提升。 go-kit日志包使用结构化日志,接口如下:typeLoggerinterface {Log(keyvals ...interface{}) error}调用代码:logger.Log("transport","HTTP","addr", addr,"msg","listening")请注意,进入日志调用的所有内容都将转换为interface{}。 这意味着它分配了不少内存。与另一个结构化日志库zap进行比较。 Zap为了避免内存分配和interface{}使用,导致了更丑...阅读全文

图解Golang的内存分配

一般程序的内存分配 在讲Golang的内存分配之前,让我们先来看看一般程序的内存分布情况: image 以上是程序内存的逻辑分类情况。 我们再来看看一般程序的内存的真实(真实逻辑)图: image Go的内存分配核心思想 Go是内置运行时的编程语言(runtime),像这种内置运行时的编程语言通常会抛弃传统的内存分配方式,改为自己管理。这样可以完成类似预分配、内存池等操作,以避开系统调用带来的性能问题,防止每次分配内存都需要系统调用。 Go的内存分配的核心思想可以分为以下几点: 每次从操作系统申请一大块儿的内存,由Go来对这块儿内存做分配,减少系统调用 内存分配算法采用Google的TCMalloc算法。算法比较复杂,究其原理可自行查阅。其核心思想就是把内存切分的非常的细小,分为多级管理,以...阅读全文

博文 2019-06-09 23:02:47 RyuGou

golang中的make与new

golang 中有两个内存分配机制 :new和make,二者有明显区别. new:new(T)分配了零值填充的T类型的内存空间,并且返回其地址,即一个*T类型的值。其自身是一个指针.可用于初始化任何类型 make: 返回一个有初始值(非零)的T类型,而不是*T,其只能用来初始化:slice,map和channel三种类型。 对比: 适用范围:make 只能创建内建类型(slice map channel), new 则是可以对所有类型进行内存分配 返回值: new 返回指针, make 返回引用 填充值: new 填充零值, make 填充非零值 代码: package main import ( "fmt" "reflect" ) type Books struct { Title, Co...阅读全文

golang学习之struct

结构体定义的一般方式如下: type identifier struct { field1 type1 field2 type2 ... } type T struct {a, b int} 也是合法的语法,它更适用于简单的结构体。 var t *T t = new(T) 变量 t 是一个指向 T的指针,此时结构体字段的值是它们所属类型的零值,使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针。 无论变量是一个结构体类型还是一个结构体类型指针,都使用同样的 选择器符(selector-notation) 来引用结构体的字段,即: type myStruct struct { i int } var v myStruct // v是结构体类型变量 var p *mySt...阅读全文

博文 2016-11-08 13:00:12 caiyezi

golang slice 和 string 重用

相比于 c/c++,golang 的一个很大的改进就是引入了 gc 机制,不再需要用户自己管理内存,大大减少了程序由于内存泄露而引入的 bug,但是同时 gc 也带来了额外的性能开销,有时甚至会因为使用不当,导致 gc 成为性能瓶颈,所以 golang 程序设计的时候,应特别注意对象的重用,以减少 gc 的压力。而 slice 和 string 是 golang 的基本类型,了解这些基本类型的内部机制,有助于我们更好地重用这些对象 slice 和 string 内部结构slice 和 string 的内部结构可以在 $GOROOT/src/reflect/value.go 里面找到 type StringHeader struct { Data uintptr Len int } type ...阅读全文

博文 2018-09-04 12:05:49 hatlonely的小站

Go内存分配那些事,就这么简单!

文链接:https://mp.weixin.qq.com/s/3g... 新老朋友好久不见,我是大彬,这篇文章准备了很久,不是在拖延,而是中间做了一些其他事情,耽搁了一些。 这篇文章主要介绍Go内存分配和Go内存管理,会轻微涉及内存申请和释放,以及Go垃圾回收。 从非常宏观的角度看,Go的内存管理就是下图这个样子,我们今天主要关注其中标红的部分。 友情提醒:文章有点长,建议先收藏,后阅读,绝对是学习内存管理的好资料。 本文基于go1.11.2,不同版本Go的内存管理可能存在差别,比如1.9与1.11的mheap定义就是差别比较大的,后续看源码的时候,请注意你的go版本,但无论你用哪个go版本,这都是一个优秀的资料,因为内存管理的思想和框架始终未变。 Go这门语言抛弃了C/C++中的开发者管理...阅读全文

【深度知识】Go语言:启动和内存分配初始化

本文是 Golang 内部机制探索系列博客的后续。这个系列博客的目的是探索 Go 启动过程,这个过程也是理解 Go 运行时(runtime)的关键之处。本文中我们将一起去看看启动过程的第二个部分,分析参数是怎么被初始化的及其中有哪些函数调用等等。 启动顺序 我们从上次结束的地方继续。在 runtime.r0_to 函数中,我们还有一部分没有分析: CLD // convention is D is always left cleared CALL runtime·check(SB) MOVL 16(SP), AX // copy argc MOVL AX, 0(SP) MOVQ 24(SP), AX // copy argv MOVQ AX, 8(SP) CALL runtime·args(...阅读全文

博文 2019-08-13 01:32:47 笔名辉哥