爲 tunny 提交的一次 PR

背景

上週我寫了一篇文章Go 每日一庫之 ants,深刻剖析了ants這個 goroutine 池的實現。在反覆閱讀了多遍panjf2000關於ants的起源的文章——GMP 併發調度器深度解析之手擼一個高性能 goroutine pool,我感受收穫滿滿。這篇文章對於理解 Go 的 goroutine 併發機制有很大的參考價值,強烈建議一讀。而後我花了幾個小時時間詳細閱讀了ants的源碼,代碼寫的很棒,很是優美。然後我寫了一遍文章分析了ants的源碼,見ants源碼賞析。在寫介紹ants的文章和深刻閱讀源碼過程當中,網上的資料說起 Go 語言中 goroutine 池的實現,時常會帶上tunny這個庫。因而,我又去研究了tunny的源碼,產出一篇文章Go 每日一庫之 tunnygit

在閱讀tunny源碼時,我發現有個方法的實現有些問題。我也在Go 每日一庫之 tunny中也指出了:github

原理

咱們知道 slice 結構中有一個指向數組的指針。假設一開始tunny中有 5 個 worker,示意圖以下:golang

數組中每一個元素都是一個指針,指向一個worker結構。而後咱們使用s := s[:4]縮容了,進變成了下面這樣:數組

如今最後一個元素沒法經過切片訪問了,可是又被底層數組引用着,沒法被 Go 運行時的 gc 清理掉,360 軟件管家都不行。這就有內存泄漏了。雖然這個泄漏並不嚴重,一是由於量不可能很大,由於 worker 數量有限,二是下次擴容後位置被覆蓋就能夠釋放原 worker 了(由於沒有引用它的指針了)。微信

ants源碼中也有相似的操做,可是會將縮容掉的元素置爲nil。例如worker_stack.go中的reset()方法:併發

func (wq *workerStack) reset() {
  for i := 0; i < wq.len(); i++ {
    wq.items[i].task <- nil
    wq.items[i] = nil
  }
  wq.items = wq.items[:0]
}

PR

肯定了問題。我先 fork 了tunny的倉庫。點擊 fork 按鈕:dom

然後將 fork 後的我本身的倉庫下載:性能

$ git clone git@github.com:darjun/tunny.git

修改代碼,commit,push 到個人遠程倉庫。下面是我所作的改動:學習

而後去tunny源倉庫,點擊Pull Request按鈕。而後點擊右側的New pull request按鈕:spa

新建一個 PR,而後點擊compare across forks,選擇個人 fork:

選擇我作修改的那次提交,而後填寫信息,提交,因爲我已經提交了 PR。此次比較就沒有差別了。

而後等待做者合併。一天後,做者合併了此次修改:

總結

GitHub 提交 PR 並不難,大到新增特性,小到一個拼寫錯誤,均可以提 PR。相信很多人都據說過,Linus Torvalds 親自合併了一個來自 11 歲小孩提交的關於 Linux 源碼註釋中拼寫錯誤的 PR。

GitHub 上 star 不少的項目並不是完美,確定也有不少值得改進的地方。因此閱讀源碼時須要帶有必定的懷疑精神,不要把什麼奉爲圭臬。

你們若是發現好玩、好用的 Go 語言庫,歡迎到 Go 每日一庫 GitHub 上提交 issue😄

參考

  1. tunny GitHub:github.com/Jeffail/tunny
  2. ants GitHub:github.com/panjf2000/ants
  3. Go 每日一庫 GitHub:https://github.com/darjun/go-daily-lib

個人博客:https://darjun.github.io

歡迎關注個人微信公衆號【GoUpUp】,共同窗習,一塊兒進步~

相關文章
相關標籤/搜索