GO的環境配置?
GOPATH GOROOT 都是干嘛用的?
配置環境跟java對比有點奇怪
https://blog.csdn.net/weixin_40563757/article/details/115476327
語言特性
協程?
建立一個協程很簡單 加一個go關鍵字就可以
package concurrence
import (
"fmt"
"time"
)
func hello(i int) {
println("hello goroutine : " + fmt.Sprint(i))
}
func HelloGoRoutine() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
通過通信共享記憶體而不是通過共享記憶體而實作通信?

先提供一個或多個高性能佇列,執行緒/行程/微服務之間需要訪問別人時,不能直接讀寫別人的資料,而要通過佇列提出請求,然后在對方處理請求時再做相應處理,
Q&A
Q:我對java比較熟悉,java里面通過鎖來實作共享記憶體,從而實作通信, 那啥叫”通過通信共享記憶體“啊?
A:ultimate go notebook 里面講把channel當做信號收發,而不是一種資料結構,
Q:我可以理解成chenel在go里 就像 阻塞佇列BlockingQueu在java里嗎? 只不過chenel顆粒度更小實作的更加底層?
A:無人回復,,,,
https://juejin.cn/post/7096859698984386574/#heading-14
Channel?
make(chan元素型別,[緩沖大小])·
- 無緩沖通道 make(chan int)
- 有緩沖通道 make(chan int,2)
例子:一個經典的生產消費模型
package concurrence
func CalSquare() {
src := make(chan int)
dest := make(chan int, 3)
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
//復雜操作
println(i)
}
}
LOCK?
package concurrence
import (
"sync"
"time"
)
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
記憶體管理
相關概念
-
Mutator:業務執行緒,分配新物件,修改物件指向關系
-
Collector: GC執行緒,找到存活物件,回收死亡物件的記憶體空間. Serial GC:只有一個collector
-
Parallel GC;:支持多個collectors同時回收的 GC演算法.
-
Concurrent GC: mutator(s)和collector(s)可以同時執行
? Collectors必須感知物件指向關系的改變!


ConcurrentGC 的實作方式
- 三色標記
- 混合寫屏障
追蹤垃圾回收
可達性分析
-
物件被回收的條件:指標指向關系不可達的物件
-
標記根物件
靜態變數、全域變數、常量、執行緒堆疊等
-
標記:找到可達物件
求指標指向關系的傳遞閉包:從根物件出發,找到所有可達物件 -
清理:所有不可達物件
將存活物件復制到另外的記憶體空間(Copying GC)
將死亡物件的記憶體標記為句分配“(Mark-sweep GC)移動并整理存活物件(Mark-compact GC)
-
根據物件的生命周期,使用不同的標記和清理策略

參考計數
- 每個物件都有一個與之關聯的參考數目
- 物件存活的條件:當且僅當參考數大于0
- 優點:
記憶體管理的操作被平攤到程式執行程序中
記憶體管理不需要了解runtime的實作細節:C++智能指標(smart pointer) - 缺點:
維護參考計數的開銷較大:通過原子操作保證對參考計數操作的原子性和可見性 - 無法回識訓形資料結構—— weak reference (swift 使用了 weal reference,相對解決了參考計數無法回識訓形資料結構的問題)
記憶體開銷:每個物件都引入的額外記憶體空間存盤參考數目 - 回收記憶體時依然可能引發暫停
分塊
-
目標:為物件在heap 上分配記憶體·提前將記憶體分塊
-
呼叫系統呼叫mmap()向OS申請一大塊記憶體,例如4 MB·先將記憶體劃分成大塊,例如8KB,稱作mspan
再將大塊繼續劃分成特定大小的小塊,用于物件分配
noscan nspan:分配不包含指標的物件——GC不需要掃描
scan mspan:分配包含指標的物件—— GC需要掃描
-
物件分配:根據物件的大小,選擇最合適的塊回傳
快取
- TCMalloc: thread caching
- 每個p包含一個nrache用于快速分配,用于為系結于p上的g分配物件
- mcache管理一組mspan
- 當mcache中的nspan分配完畢,向mcentral申請帶有未分配塊的mspan
- 當ms pan中沒有分配的物件,ns pan會被快取在mcentral中,而不是立刻釋放并歸還給OS

記憶體管理優化
- 物件分配是非常高頻的操作:每秒分配GB級別的記憶體
- 小物件占比較高
- Go記憶體分配比較耗時
分配路徑長:g -> m->p -> mache -> ms pan -> memory block -> return pointer. - pprof:物件分配的函式是最頻繁呼叫的函式之一
Balanced GC(根據物件的生命周期,使用不同的標記和清理策略)
小物件的管理
- 每個g 都系結一大塊記憶體(1KB),稱作 goroutine allocation buffer (GAB)·
- GAB用于noscan型別的小物件分配:<128 B
- 使用三個指標維護GAB: base, end, top
- Bump pointer(指標碰撞)風格物件分配
無須和其他分配請求互斥
分配動作簡單高效

大物件的管理
-
GAB對于Go記憶體管理來說是一個物件
-
本質:將多個小物件的分配合并成一次達物件的分配
-
問題:GAB的物件分配方式會導致記憶體被延遲釋放
-
方案:移動 GAB中存活的物件
當GAB總大小超過一定閾值時,將GAB中存活的物件復制到另外分配的GAB中
原先的 GAB可以釋放,避免記憶體泄漏
本質:用copying GC的演算法管理小物件
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/474618.html
標籤:Go
