go源码分析之内存分配

go源码分析之内存池

概述

go自带内存管理,主要是内存池和垃圾回收两部分。因为其对内存的管理在性能和空间利用率上的高效,go内存大多数情况不需要用户自己去管理内存,让程序员减少了很多在内存管理的心智成本。虽然如此,本文还是借着源码,分析下go的内存管理中内存池分配时如何实现的,希望对大家了解有所帮助。如有问题,欢迎探讨指正。
(源码基于go 1.10.3)

首先,内存分配模型基于tcmalloc,Tcmalloc是Google gperftools里的组件之一。全名是 thread cache malloc(线程缓存分配器),其内存管理分为线程内存和中央堆两部分。在并行程序下分配小对象(<=32k)的效率很高。
Tcmalloc核心思想是把内存分成多级来降低锁的粒度。每个线程都会有一个cache,用于无锁分配小对象,当内存不足分配小对象,就去central申请,在不足就去heap申请,heap最终是向操作系统申请。
这样的分配模型,维护一个用户态的内存池,不仅提高了内存在频繁分配、释放时的效率,而且有效地减少内存碎片。

下面我们依次看下go中内存如何划分,主要的一些内存结构,最后在结合源码看一下主要的内存分配流程。

Read More

go学习之堆栈中的变量

关于变量分配在堆和栈的问题一直不太了解,直到看了附录几篇文章,有了一个初步的认识。

先看官网怎么说

go变量分配到堆还是栈

从正确的角度来看,你不需要知道。Go中的每个变量只要有引用就会存在。实现选择的存储位置与语言的语义无关。

存储位置对编写高效程序有影响。如果可能的话,Go编译器将为该函数的栈帧(stack frame)中分配本地变量。但是,如果编译器无法证明变量在函数返回后未被引用,则编译器必须在存在垃圾回收的堆(garbage-collected heap)上分配变量以避免指针错误。另外,如果局部变量非常大,将其存储在堆而不是栈上可能更有意义。

在当前的编译器中,如果一个变量的地址被占用,那么该变量就成为堆中的一个候选对象。但是,一些基本的逃逸分析可以识别出某些情况下,这些变量不会在函数的返回后还存在,就可以驻留在栈中。

Read More

Go Memory Model

在了解golang的内存模型后,对一些读写顺序如何保证有了了解,记录在这里
官网原文

内存模型

Happens before

Go内存操作中定义读写执行的顺序,没有明确的执行先后,则不能保证其结果顺序

对V的写入w可被读取r的条件

1.r 不happen before w
2.没有其他的写入w’ happen after w 且 happen before r

保证对V的写入w是读取r唯一可获取的条件(无读写并发)
1.w happen before r
2.其他的写入w happen after r 或 happen before w

Read More

跨域登录态共享

登录态共享

登录态共享?什么鬼,不知道的就可以不用看啦,需要时再说,说不定到时也用不到,笑脸~~

场景

解决多个子系统中共用模块(比方说工单系统)可以共享子系统的登录态
为简化问题,设定场景:
登录系统A,点工单操作跳转系统B,并且无需登录(至于系统登录何时失效暂不考虑)

还有:别问我为什么不用单点登录(SSO),那个,不想说,笑脸~~

先别废话,直接代码上

Read More

php踩坑记录

函数

mb_strlen 不生效

有一天发现本地mb_strlen('哈')本地为1,服务器为3,猜测应该是配置问题
看文档关键在于mb_internal_encoding

1
2
3
4
5
6
7
8
9
mixed mb_strlen ( string $str [, string $encoding = mb_internal_encoding() ] )
继续搜 mbstring.internal_encoding (定义内部字符的默认编码)
Warning: This feature has been DEPRECATED as of PHP 5.6.0. Relying on this feature is highly discouraged.。
PHP 5.6 及更新版的用户应该将此选项留空,并设置 default_charset 作为代替。
好吧,服务器 default_charset 没设置,然后默认用 ISO-8859-1

Read More