1. 程式人生 > 其它 >分享一個我看原始碼時的小技巧。

分享一個我看原始碼時的小技巧。

你好呀,我是歪歪。

我在之前的文章裡面不是經常叫大家拉原始碼,然後看程式碼提交記錄嗎。

也就是看類似於這個介面:

比如上面這個介面中,就可以看到 RedissonBaseLock.java 這個檔案,由誰在什麼時候進行過變更,以及變更對應的 commit 資訊是什麼。

這樣就能很直觀的看到檔案的演變過程。

那麼問題就來了,有好幾個同學都問過我這個問題:怎麼在 idea 裡面檢視 git 提交記錄呢?這個介面是藏在哪裡的呢,我的 idea 裡面怎麼沒有呢?

好的,是我疏忽了,我先入為主的認為這個大家應該都知道是怎麼來的。

但是確實是有一些同學是不太清楚的,那我這篇文章就給大家分享一下我通過這個東西看原始碼的一點點小技巧,希望能幫助到你。

怎麼搞出來?

那麼怎麼把這個檢視搞出來呢?

首先,你本地得有一個 git.exe。

這個玩意怎麼來的,就不用我說了吧,如果連這個都沒有,說明你之前還沒有接觸過 git,那就是另外一回事兒了,不在本文討論範圍內。趕緊去安裝一個 git,然後學學 git 的用法啥的。

我個人的習慣是先用 gitbash,也就是這個玩意,從 github 上 clone 一個專案下來:

比如我就用之前寫文章的 Redssion 做演示吧,你也可以隨便找一個自己感興趣的開源專案。

執行下面命令把專案下載下來:

git clone https://github.com/redisson/redisson.git

下載完成之後,開啟你的 idea,匯入我們剛剛下載的專案。

然後隨便開啟一個檔案,點選右鍵,看看有沒有 Git 這個選項:

如果順利的話,你點選 ShowHistory 之後,就能看到這個視窗了:

如果不順利,說明你的 git 配置有問題。

在 idea 的 Settings 裡面進行對應的設定:

設定完成之後,可以點選旁邊的 test 按鈕,如果有彈窗告訴你對應的版本號,那就說明配置成功了:

總之,只要能調出 Version Control 標籤頁或者有的高版本里面就叫做 git,就代表配置成功了。

怎麼看?

不管是在工作中還是寫文章的時候,我一般在 idea 裡面只是看提交記錄,我不會用 idea 裡面的 git 去做提交程式碼的動作。

其實 idea 裡面拉取程式碼,提交程式碼什麼的視覺化頁面做的很好,但是我還是比較喜歡直接在 gitbash 裡面敲命令,也沒有什麼特別的原因,只是這樣顯得逼格高而已。

那麼,到底怎麼去看呢?

以我之前寫的 Redisson 文章為例。

主要是圍繞著 RedissonLock.java 這個類在寫,我是怎麼知道這個類的呢?

其實自己帶著問題去 debug 也肯定能定位到這個類,但是需要一點時間。

我以前就是搭完環境之後,就開始瘋狂的寫案例 debug 了。

現在我學聰明瞭,環境搞定之後,先去 github 的 issues 裡面拿著關鍵詞去搜一下。

比如我的關鍵詞就是死鎖:

但是我強烈建議你別用中文搜尋,用英文,deadLock:

這樣能搜出來的資訊就很多,剩下的就是你一個個點開,看看是不是和自己遇到的問題一樣,或者相似。

這個過程會花一點點時間,但是絕對比你一頭扎進原始碼裡面找答案快的多。

比如,上面的截圖中,最後一個叫 Deadlock after Redis timeout 的 issue,就是我想要找的東西:

在這個裡面給出了復現的程式碼,涉及的版本,以及預期的結果和實際的表現。

比如說我找到這個連結之後,對我而言就是找到了一個測試用例,同時他告訴了我一個命令:

CLIENT PAUSE 5000

在這之前,我是不知道這個命令的。我還一直在想,我做 Demo 復現的時候,應該怎麼去模擬 Redis 執行命令超時的現象呢?

我當時能想到的一些方案就是 bigkey,或者灌很多資料進去,然後我執行 keys * 命令,再或者搞個 save 命令,這樣來模擬 Redis 阻塞。

但是,這都是有工作量且阻塞時間不可控的。而這個命令直接解決了我這個問題,至少讓我少走了幾步彎路吧。

同樣,這個 issues 裡面還關聯了幾個其他的 issues ,這些都是官方認為是同一個原因造成的問題:

然後怎麼解決的呢?

常規來說,他們應該關聯一個 pr,通過這個 pr 我就能直接關聯到對應的修復的內容。

但是這次他們搞了一個騷操作,直接先弄了一個 SNAPSHOT 版本,並沒有關聯 pr:

怎麼辦?

這個時候我想去看他是怎麼修復這個問題的,怎麼辦?

前面提到的 idea 裡面的 git 外掛就派上用場了。

首先,從他的評論時間我知道是 2019 年 3 月 13 號,那麼我可以直接在工具裡面定位到那一天提交的內容。

點選 Version Control 視圖裡面的 Log 標籤,就可以看到整個專案歷史上的所有的提交,它會按照時間的順序給你排好序,所有很容易就找到了當天的相關的提交:

你要是覺得難得找,也可以直接通過日期進行過濾:

從當天提交的這個 commit 資訊來看,就知道我找對地方了。

而這裡就只是修改了 RedissonLock.java 這個類,所以我就找到了這個關鍵的類:

然後點進去再分析一下這個類具體的修改,這樣算是找到了 debug 的時候我應該重點關注的地方。

又比如看門狗失效的那個 bug:

https://github.com/redisson/redisson/issues/3714

在這裡面,就是直接關聯了一個 pr,然後我們可以通過這個連結,找到提交的程式碼,也可以找到其對應的 issues。

這玩意屬於雙向奔赴了。

而且我也能知道這次提交對應的類叫做 RedissonBaseLock.java:

那我又可以回到 idea 的視圖裡面,直接看看這個類的提交記錄了:

一看才發現,這個哥們一共提交了三次。而且還發現這個類還挺年輕的, 2021 年 1 月 21 日才首次提交。

我之前在《踩到一個關於分散式鎖的非比尋常的BUG!》這篇文章裡面留了個思考題:

就是由這三次提交引起的。

我帶你看一下這三次提交分別是什麼。

首先第一次提交,加入了 else 分支,裡面執行了一次 cancelExpirationRenewal 方法,入參是 threadId。

含有是把當前執行緒的重入次數減一。

但是能走到 else 分支裡面來有個大前提是給鎖續命的 lua 指令碼返回 false,也就是說這個鎖都沒了。

鎖都沒了,還維護重入次數幹啥呢?

直接從 MAP 裡面把這個物件拿掉就行了。

怎麼拿掉呢?

傳入 null 就可以了:

所以,才有了第二次提交,把入參從 threadId 修改為 null:

那麼第三次提交又是幹啥呢?

是不是完全看不出來是幹啥?

別急,我這樣給你上個截圖你就懂了:

之前是用的 tab 製表符,後來修改為四個空格。這是編碼風格的問題。

提到用 tab 還是用空格,這又是另外一個在程式設計領域裡面爭論不止的話題了。

我記得之前我看過一個美劇,叫做《矽谷》。裡面的主人公就因為到底應該用 tab 還是用空格和女朋友吵了一架。

然後...

我寫文章的時候還想起了一個無聊的問題,並且去尋找到了答案。

我想知道 Redisson 是在什麼時候引進看門狗機制的,我想看看這個狗子最開始的模樣。

我怎麼找的呢?

首先我知道啟動看門狗的程式碼是位於 RedissonLock.java 中的 renewExpiration 這個方法:

那我就在 RedissonLock.java 的歷史提交記錄裡面用找一下 renewExpiration 這個方法什麼時候是第一次提交的就行了。

於是我很快就找到了 2019 年 3 月 13 日的這次:

我才發現原來看門狗還換過名字,它之前叫做 scheduleExpirationRenewal,後來才改名叫 renewExpiration。

很顯然,我覺得新名字更好。

然後我就繼續找 scheduleExpirationRenewal 是什麼時候第一次出現的,我找啊找啊,找到了 2015 年 12 月 14 日的這次提交:

好傢伙,這個狗子還有個叫做 newRefreshTask 的曾用名啊。

最終,找到了 newRefreshTask 第一次出現的地方,就是 2015 年 7 月 4 日:

這就是看門狗的生日,距離今天不到兩個月了,我提前祝它生日快樂。

但是,我不得不吐槽一句。

關於看門狗的這一次提交,提交了非常多的東西。可以在這次提交上右鍵,然後點選下面框起來的選項:

就能看到這次提交的所有東西:

提交了 31 個檔案,其中包含了看門狗機制。

但是提交的 commit 資訊非常簡陋,只體現了因為涉及到事務操作,所以使用了 LUA 指令碼的這一個特性。

這就是一個非常不好的 commit 提交示例。

但是你轉念一想,你每次提交的時候示例是怎麼寫的,是不是也經常偷懶。

別問我是怎麼知道。

所以,每次提交的 commit 資訊還是要認真寫的,因為你要知道,總是有我這樣無聊的人,會去翻一些沒啥卵用的知識點出來。

比如我問你,我找看門狗機制的這段描述,除了讓你知道它的生日和幾個曾用名之外還有什麼卵用嗎?

是的,沒有。

恭喜你又學到了一個沒啥卵用的知識點。

再來一個

我再帶你看一個專案,Dubbo。

還是按照我前面說的,把專案拉下來,然後點選這裡的 log,就可以看到整個專案歷史上的所有提交:

拉到最下面,可以找到歷史上第一次提交的情況:

第一次提交是樑飛在 2011 年 10 月 20 日 23 點 04 分提交的。

但是從提交的 commit 資訊來看,我們也知道這是一次空提交。

真正的第一次提交是 2 分鐘之後的 23 點 06 分:

9 個模組,共計 669 個檔案,就是日後這個一路坎坎坷坷、幾近夭折、友商續命,最終成為 Apache 頂級開源專案的雛形。

11 年前的 10 月 20 日,樑飛從晚上 23 點幹到了凌晨 5 點 25 分,終於給 Dubbo 打上了第一個里程碑 tag:2.0.7。

期間,還發布了一個微博:

而他自己,第二天的中午,也在自己的部落格上公佈了這件事情:

https://www.iteye.com/blog/javatar-1206888

為什麼 Dubbo 會選在這一天進行開源呢?

我想應該是為了趕上兩天之後的 Qcon 全球軟體開發者大會:

那一天,才是 Dubbo 真正意義上,站在大眾視野裡,接受讚揚與嘲諷的開始。

在 idea 的視圖裡面,還可以過濾指定的人提交的記錄。

比如樑飛就用過下面這幾個賬號提交程式碼:

我過濾了一下,發現多達 1294 次,最後一次提交在 2015 年 4 月 1 日:

而且我還發現他特別能肝,類似這樣時間點的提交記錄有好幾處:

然後我還找了幾個類,想看看經過 10 多年的發展,這些類中還留下多少他的程式碼。

首先我給你看看這個負載均衡策略相關的類 AbstractLoadBalance.java。

在這個類上右鍵,然後選擇 git->Annotate 就可以調出左邊的(時間-使用者)的檢視:

這就表示的是當前這個類,每一行程式碼是誰在什麼時候提交的。

還是可以看到樑飛的身影。

而且我給你看看這個:

這個方法是 Dubbo 啟動的時候,給新機器預熱,一點點的給權重。第一分鐘給 10% 的流量,第二分鐘給 20% 的流量...第十分鐘這個時候機器基本上已經經過充分的預熱,所以可以給到 100% 的流量。

至於為什麼要預熱呢,這個就和 JVM 相關了,你如果感興趣的話,可以去研究一下。

就是這個功能,這一個核心方法,經過 10 多年時間,除了一點微調,其核心演算法、核心邏輯沒有發生一點變化。

再比如,我給你看看最少活躍數負載均衡策略的實現 LeastActiveLoadBalance.java:

從初始化提交之後,一共就沒修改過幾次。

但是你要知道每次提交都是有它的意義的,比如這兩次:

一次提交是把變數 leastIndexs 修改為 leastIndexes,因為 index 是 x 結尾的,以 s、x、sh、ch 結尾的名詞,它的複數形式應該是加 es。這是一個英語小知識。

一次提交是把 Random 替換為 ThreadLocalRandom,因為後者效能更好,這是程式設計小知識,背後的原因是值得深挖的。就看有沒有有心人了。

你也可以對比一下,初始版本和當前最新的版本,核心演算法、核心邏輯基本沒有發生變化:

這兩個類告訴我一個什麼道理?

比起業務程式碼的增刪改查,只有演算法,穩定的演算法才是更容易再歲月的長河中留下來的,而且歷久彌新。

然後,再回到 log 的標籤中,你會發現一個很奇怪的現象。

整個 2014 年到 2015 年,都沒有提交過幾次程式碼:

其實從 2013 年開始到 2017 年基本上就沒多少提交了。

這是為什麼呢?

這就不得不說一下 Dubbo 坎坷的一生了。

前面說了,2011 年它是屬於出生豪門,從阿里開源走了出來。

但是在 2012 年 10 月 23 日,Dubbo 2.5.3 釋出後,阿里就基本上停止了對於 Dubbo 的維護升級。

然後一直到 2017 年 9 月 7 日,Dubbo 悄悄在 GitHub 釋出了 2.5.4 版本。隨後,又迅速釋出了 2.5.5、2.5.6、2.5.7 等版本。在 10 月舉行的雲棲大會上,阿里宣佈 Dubbo 被列入集團重點維護開源專案,這也就意味著 Dubbo 起死回生,開始重新進入快車道。

在 2012 年到 2017 年這五年間,噹噹網自己拉了一個 Dubbox 的分支開搞,相當於幫 Dubbo 把命給續住了。

2018 年 1 月 8 日,Dubbo 2.6.0 版本釋出,新版本將之前噹噹網開源的 Dubbox 進行了合併,實現了 Dubbo 版本的統一整合。

然後 2018 年 2 月,阿里巴巴宣佈將 Dubbo 捐獻給 apache,進入 apache 孵化器。

2019 年 5 月 21 號,經過了漫長的孵化期,Dubbo 迎來了畢業。成為Apache基金會頂級專案。

之後的故事你應該也就知道了,Dubbo 現在都搞到 3.0 了,準備在雲原生的賽道上發力。

所以你看,這妥妥的就是一個爽文的套路啊。

這就是一個富家子弟不慎流落街頭,被人收養,悉心照料,最後在一片驚呼中,又重回巔峰的故事啊。

那麼這個故事告訴了我們一個什麼道理呢?

它告訴我們,有個好爸爸真的是太好了。要是 Dubbo 不是阿里開源出來的,起死回生是很難了,對半已經是消失在歷史的長河中了。

話說回來,前面提到的這些東西,都是可以由我這篇文章給你提到的這個 idea 的檢視衍生出來的。

而且我只是給你介紹了一些非常常規的用法,你可以自己去挖掘出更適合你自己的關注點。

這玩意,平時自己沒事,拉個自己感興趣的專案下來,看看提交記錄,看看新特性。

就像我前面說的,每次提交都是有它的意義的,有的提交背後是值得深挖的,就看有沒有有心人了。

你說,這玩意難道不比小說好看嗎?

歡迎關注公眾號why技術,第一時間接收最新文章。