糾纏與糾結

contents

  1. 1. 工作
    1. 1.1. 單元測試
    2. 1.2. 資料庫
  2. 2. 周末
  3. 3. 生活

工作

距離上一次編寫日記到現在已過五個月,累積著不同的經歷與感受,才能寫出一篇有所不同的日記。然而,工作後每天回寢室不是睡覺就是打個遊戲,周末也沒特別想做什麼,完全地放空就是最好的休閒,這使得寫一篇文章又變得更加困難。一成不變的煩惱,到底能寫些什麼。

單元測試

這幾個月來,總算把單元測試拉了起來,從原本代碼覆蓋率 1% 拉到 6%,測試數量十幾拉到四百多個,這過程最痛苦的就是慢慢將所有代碼重新審視,就會開始發現一堆函數不同名稱卻功能相似,甚至是子集合的概念。有人會說「至少沒錯啊,你改那個做什麼」。的確,只是重複的代碼多了一點,但後續的維護就非常痛苦,一旦這重複的代碼中出了 BUG,我們花了九牛二虎之力修了它,卻發現到處都有,這時候心裡不鬱悶嗎?

「感覺超沮喪的」-《這個勇者明明超TUEEE卻過度謹慎》

程式碼多寡會影響效能嗎?大部分的情況並不會,但是對於 Java 的 JIT 而言,跑越多次的代碼它就會更進一步地優化,把沒有用處的代碼移除,做到跟 GCC O2 的效果類似。這其中最困難的處理操作為另一個函數的子集,大部分的情況下,直接導向到另一個函數是沒有問題的,例外是時間複雜度增加與例外處理的不同,為了處理更複雜的情況,功能越強的函數通常都會有一些額外的邊際效應 (side effect),這時候就要非常小心。

於是每天就是把上千行代碼、數百條函數裝進腦子裡,然後攪一攪把相同功能的代碼移除。好比,判斷一個圖是否同構,這基本上已經接近 NP-Complete 問題,一下子腦子運轉就會過熱,無法去思考其他的項目。有些人的腦子的確可以完全阻隔思考吧,但是對我來說,潛意識帶動的壓迫卻是無盡的痛苦。

《這個勇者明明超TUEEE卻過度謹慎》

做這一些很無趣,出於使命必須審視它,不然每次呼叫函數都不確定自己在處理什麼,甚至傳錯了組態也不會噴任何錯誤。於是開始加起了無數的防火牆,各種防禦性編程的代碼。果真還有不少代碼使用錯了,造成永遠拿到錯誤的結果,那問題就擴散出去,於是又針對相關函數進行修改,連帶回歸測試都要更新,工程浩大卻沒有產出。

《這個勇者明明超TUEEE卻過度謹慎》

這過程發現一些無理的要求,發現自己努力了好幾個月,依然會有人亂加函數,要解決問題,果然還是要拔除源頭。傳了個完全不到的參數,還特地做了重載 (overloading),此時心裡就納悶了,這傢伙到底是怎麼想的?「因為原先的代碼我不敢改,但是為了效能我複製了一份,又怕自己忘記於是弄了相同的函數名稱 …」這樣子我有點明白了,永遠不該去用常理去看待問題,問題就是那些思維上的漏洞。

架設了 SonarQube 這一類的代碼品質監控後,上千個 bug、vulnerability 和數萬的 code smell,這幾個月終於把前者壓到三位數,目標是控制在一百內。在這五十萬行的裡,多半程式根本不會用到,也不會讓使用者觸及到。那修到底有什麼動力嗎?只有一個,因為初學者會複製類似的行為,做出一樣的蠢事。

公司在美國那裡的新成員,開始寫的時候總會搞不清楚 Java 的特性,就像從 C++ 跳過來的孩子,常常會忘東忘西地,不斷地複製類似的代碼片段來做事,就像字串常量常常會到處冒出來,實際上這些常量如果會一起變動,就應該用一個變數去取代之,這也方便我們去追蹤使用情況。實際的結果不是,造成了無數問題,升級版本的時候,常量到處找,耗費工時又一堆 bug 有待追蹤。

資料庫

因為製程的進展,大廠開始要求效能,來解決上億物件的資料庫問題,物件存取速度要快,開檔存檔都要更進一步加速。於是又開始放下那些代碼的修正,跑回去研讀資料庫相關的處理,由於 EDA 工具總是自己刻一個資料庫,方便規則的變化以及升降版本之間的問題,更提供鬆散的客製化需求,相當於要求自己刻一個嚴謹的資料庫介面。

除了資料庫的基本理論,還有牽涉到開檔讀檔這種小眾知識,解壓縮與壓縮的效能,在每一個階段的每一種算法中追求內存用量最少,額外宣告變數量最少,盡可能使用位址定位等等,每一步都要精準到位,當處理數量破億時,問題就會放大得相當嚴重。就像原本內存 50 GB 可以開起來,修改完卻變成 100 GB 才能使用,這種算法常數的影響就很嚴重,這些問題甚至不是整體的結果,而是處理的過程。也就是說,甚至要最小化中間過程,否則造成某個時間點是達不到運行需求。最後,記憶體用量少一半,存取速度快兩倍之多。

在這過程中,見識到了各種邪門歪道的升降版本的修正技術,這也造成了無數相依性問題。例如在這個時間點,你所請求的物件並未存在,實際上這段代碼毫無作用,卻也活了無數年,沒有人測試過它,看起來又相當合理。陸陸續續地將這些問題分析與移除,有時不小心修正了,激活了無數功能,卻要花時間更新好幾條的回歸測試。

資料庫接口的重要性影響著整個軟體的效能與穩定性,有時會有人受不了效能而開啟平行計算,那首先的問題是「為什麼會慢?」,並不是單純地「因為慢,所以開平行。」一旦開平行下去,有些問題可能不是真的問題,因為 GC 在平行情況下,遮掩著你對剖析器 (profiler) 的觀感,因為整個停頓點如果偏移一點,就會造成優化的方向都不對。

這麼說也許是理論派吧,信者恆信。因為能解決問題的方法,總是把原先的解法全部砍掉重做,要拿這些說服別人的確是難上加難,這裡也許該相信未來會解決吧,總有一個人會跳出來滅了這個火,也許是像神一般的編譯器、或者是 AI 可以幫你除錯並修改,就不再提及了這些公司鬼故事。

「我已經沒有什麼可以失去的」-《BEASTARS》]

周末

其實已經沒小夥伴在玩楓之谷,身邊認識的人也不會玩這種遊戲,大多都是課金到滿的手機遊戲或者單機遊戲。逐漸地,也不是很想玩遊戲,王沒課金也打不贏,花時間也無法達到那個境界,跟團又要看別人臉色和時間。玩遊戲各路牛馬鬼神的人都有,跟不同文化背景的人打交道相當不容易。

最後,我仍選擇了淡出,周末坐在電腦桌前,開著麥克風,要講著自己不太喜歡的詞,看著那無法理解的笑點,時間久了喉嚨不好受。每天上線,還會有一些不雅遊戲暱稱的人騷擾,不知道是吃飽閒著還怎麼的,難道就這麼有趣嗎?即使封鎖拉黑都沒有,這樣的情況持續一個多月,嘗試去找兇手,卻總是沒有任何音訊。

奇怪的是,總能挑到上線的時候發出訊息,非常高的機率是相關人士。後來有一天,群組還是透露了他們其實都知道是誰搞得,還給出了一堆提示後,仍然不願意告訴我那個混蛋是誰。這樣的狀況仍持續了幾周,依舊只說了「如果要答案的話,下一次線下聚會就跟你說。」,這種說詞,徹底讓我貫穿了所有雲雨。

明知答案為何,卻老是不願意透露。這讓我想到寫了幾千題的過程中,遇過一些人也採用類似的策略,終究也沒辦法從之獲得什麼,那一種糾結始終在我心裡迴盪。有一天,我突然想到自己那種快樂遊玩的感覺沒了,都是在過程中想辦法找到玩下去的理由,開始剝離原先的群組,也不需要什麼理由,我累了,在尋找那簡單快樂的旅途中累了。

「我果然是累了吧」-《這個勇者明明超TUEEE卻過度謹慎》

接下來的幾周,逐漸地縮短遊戲時間,開始想了當初一些還沒做好的事情,整理一些瑣事,跑了一些實驗驗證算法。在房裡發呆也好,不跟人說話也罷,那一種重新探求的感覺,心想還可以持續多久?

年底的最後幾周,拾起了論文,開著 sci-hub 下載論文來看,嘗試解決當年規劃的藍圖,藍圖都還沒做好,卻發現了工作上更多的問題,甚至還找到了原生 JDK bug,這也解釋了為什麼老是愛開平行解決事情,這都還只是附加產物。印出了一疊論文在公司裡放著,稍微有空閒的時候看。

如果能解決根本問題,不需要研究論文的話,其實也不用這麼痛苦地看論文。若在公司要分享論文知識,或者請求別人一起努力什麼的,這是不太可能的。曾經與同事這麼說道「這個問題很難,總是要有人去犧牲、去解決的,看論文也是這個原因」,得到的回應卻是「那你去犧牲吧」。也許,不經意的一句話才是現實的真相

生活

「不過我的生活方式」-《BEASTARS》

沒有。

這些日子研究了一些持久化結構,但我的生活卻不會這麼地持久。