# 資訊科技產業專案設計課程作業 3 ## Mock interview Interviewer: :dog: Interviewee: :cat: ## [Backend Engineer, Golang, NVIDIA](https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/Backend-Engineer_JR1962842) :dog: 可以幫我先自我介紹一下 > :cat: 我曾經做過不少專案,例如說在 Jserv 的書、課程專案,還有包括學校的 Final project 做額外的擴充,跟學弟妹分享時備課的教材拓展成比較完整的框架。過去也在團段合作的過程中我們是如何溝通彼此有衝突的意見。還有在我前一份工作,我從 onbourd 開始計算,5 個小時就對公司貢獻第一筆 commit。也在我們的 scrum meeting 裡面,team members 所有人認為應該要花 20 小時的情況下,我評估預期工時只需要 3 小時,結果也如預期在三小時完成。 :dog: 好,那。先來看一下你的工作經驗的部分。你可以講解一下你在裡面負責的任務,以及你有沒有一些印象深刻的成就,或者是專案。 > :cat: 我負責的任務跟印象深刻的成就跟專案。嗯,我想是我想是這樣子就是說,因為我們的公司的產品呢?會服務3個平臺,包括 Windows,Linux 及 Mac OS,那我第一開始剛剛講說我馬上能夠提出那個PR。 > :cat: 那是我們的 base library, 就是可以跨3個平臺共用的share library的部分,那,這是當然,可能就是我們的 team leader 會希望說能夠先試試看,說我這個人的程度大概到哪邊,那也希望能夠快速的去比較了解這個公司產品 infra 的部分,以利後來後續維護。 > :cat: 接下來第二個階段就是,我去幫忙開發、解決了一個問題:公司有個客戶要掃描的可疑檔案非常多,可能十幾萬筆20萬筆;但是在公司原本的程式模型,producer consumer 模型,上面會有超出記憶體使用,炸掉的情況。 > :cat: 我提出了一個我自己的解決方案,讓這個問題呢是絕對不會再發生。也可以保證原本的程式效率,不會有 starvation 的情況發生。 :dog: 你可以再細講一下你的 producer consumer 的那部分的改善該怎麼做? > :cat: 原本的做法,是 producer consumer 共享 global queue,有一個 producer 配上很多個 consumer。我每個 consumer 做完會重新去跟 producer 要資料,他們就不再是共享同一個 Queue 也不會去不會讓 producer 不斷的產生:可能瞬間瞬間好幾10萬筆的data放在記憶體裡面去,讓 consumer 沒有辦法去消化。 > :cat: 而是說我在 consumer 在 100% loading 的情況下,當 consumer 做完再去跟 producer pull 新的資料下來。 :dog: 那你剛剛提到就是你把那個 global queue 給移除了,但這樣其實就已經造成某種程度的 dependent, > :cat: 哦,對。 :dog: 那這個部分後面有造成什麼維護上的難題嘛? > :cat: 後續維護上的難題好,我必須先承認的就是說這個目前這個情況是還沒有遇到的。 > :cat: 對那我這個地方除了改善就是 Queue 的 dependence 的問題的話,我把原本大概1000多行的程式碼,把它模組化,把它移到下一層;就是說OK,這個 producer 跟這個 consumer,他們就是一對,那他們這他們這一對就在自己的範圍。他們自己的scope裡面去做操作就好,就不要讓外層來去做,所以讓裡面那個偶合度非常高的一個互動模式,在外界不會去打擾他的情況下。我認為不會遇到太多的狀況。 :dog: 那,不過在這個模型下面,每次一定都是 producer 要活著的情況下,你的功能才有辦法運作。萬一 producer 死掉的話就沒有辦法運作了?因為原本是放在一個 global queue 裡面,producer 死掉,東西還可以被 consumer 做處理。 > :cat: 對,如果是 producer 只有一個,那他如果意外 crush,我會怎麼做?好極了,這個不在,畢竟他沒有做 HA。我想我可以試著用其他方法來解決這樣的問題... > :cat: 如果是這個問題的話,我們原本的產品是也是也是會有,也是會有這樣的問題是說一個 producer,然後呢?大量的去產生資料,然後塞在global Queue 假設是無限大可以可以放上去的話,那 producer 爛掉... 吶。確實是不會,哎,對,確實是不會對這個系統造成影響,因為他已經放在 global Q 上面去了,對。 > :cat: 可是這樣即使我把它變成擴張成 multiple producer。這樣子。會有比較好嗎?這樣我會有雞生蛋蛋生機的問題耶,因為變成,我會區要先再有一個 producer-producer 去生產檔案給 producer 去派發任務給 consumer... 這樣並沒有解決問題。 > :cat: 還是說我就騙騙使用者說你會用 producer 的狀況去處理,但是現在找不到 producer,請你重新開啟這個應用程式? :dog: 確實,一般通常比較常用是另外多 supervisor,他如果掛掉的話就是 restart,對,不過因為這個是在分散式系統上比較方便的做法,如果是在客戶端的一般機器上,我其實也沒有類似的這個經驗。 :dog: 嗯?那我們提到有對的房的門透露竟有兩倍的效能優化,可以再講一下這個細節? > :cat: OK,其實我們公司在拼這個快速的市占率的情況下,會有蠻多的需求,是我快速能夠先把程式碼先出來,然後以至於後續要做優化的部分再來做處理這樣子,而且更何況就是說其實防毒軟體掃描半小時跟掃描一小時。其實一模一樣的事情。 > :cat: 對,所以我對在這邊做了當初沒有寫的優化。那個情境是:我們在客戶上面會有方塊字,意思就是說那個 cjk 就是 Chinese Japanese跟 Korean。會用到的寬字型,而不是傳統 C++ 上面的那個一個一個byte就可以表達出。以至於呢,我上面所有的都在產生一個寬字型的部分的時候,要麼就是要麼就是複製一遍,要麼就說一開始就是保持一致性。 > :cat: 而我所作到的改進,第一個就是保持一致性的部分就盡量減少它的沒有必要的轉換。那第二個部分就是說他在傳 parameter 的時候呢,當初的寫法可能沒有考慮到說可以傳這個,而這個屬於比較 C++ 進階的內容,他是傳可以傳的是 rvalue reference 進來對那就不需要去額外的負擔。 > :cat: Copy 成本讓原本就已經在 stack 或是在 heap 的物件,在進入這個 function 的時候又要再產生一次。那我透過網路上 Quick C++ Benchmarks 來評估我改善的 basic routine 是比原本的原本的函數效能快兩倍。 :dog: 這樣那你這兩倍的優化有時什麼 trade-off 嗎? > :cat: 他唯一最最最大最大的問題是,它 ABI 不 compatible。也就是說,沒有辦法讓新版的程式碼去連結到相對應的函式,但是因為這是內部的函式庫,每次在 release 的時候都會重新 compile,所以實際上是感受不到差異的。 :dog: 剛好看到應該是在xxx的實習經驗,那你可不可以簡單講一下最令你印象深刻的事情? > :cat: 因為那是我第一次實習,那時我花兩個禮拜,就做完了整個實習兩個月的工作。這算是我印象最深刻的事情。 :dog: 那可以請你描述更多細節? > :cat: 那時候要做的內容是對 Andoird 應用程式做相關的安全分析。因為這算是苦力活,但是因為分析惡意或是不安全的樣本對資安研究員是相當耗時的,那我就透過 shell script 整合相關分析工具,幫我自動化的做分析。而後我才根據這些分析結果進行審核。 > :cat: 相對於其它工程師,或許我最擅長的就是使用 shell script 幫我把需要重複處理的事項,交給機器幫我完成。 :dog: 那你這邊提到你的分析工具,我好奇他背後的原理是怎麼做? > :cat: 是,我們是靜態。我先用 dex2jar 等相關工具把APK檔做反編譯變成Java byte code,才去給 language server 做分析。 :dog: 嗯,那你覺得這個工具如果哪天那個 Java 的 import 升級 Java 版本之後,你的工具還可以正常運作嗎? > :cat: OK,因為我們這個是在這個 Android 的環境上面,所以第一個就是說,即使你把 Java 的環境做升級,我 compile 出來的 Java 的那個版本會怎麼樣? > :cat: 因為他是背後跑的那個 ART 就是 Android runtime 是一樣的 Fundamental Byte code,所以你的Java的升級。不會影響到我這個這個城市的分析,因為他們畢竟生出來要跑在不同手機上的。 > :cat: 再來就是 Armv7 跟 Armv8 在最近過渡期的關係,在 64 位元跟 32 位元會有不相容的問題。但是在這邊值得慶幸的是因為現在是過度期,所以編譯出來的 APK 通常都會有兩種 for Armv7 跟 Armv8 的 library,所以不會影響到我們的分析。 :dog: 你可不可以講一下你 Facebooc 在 GitHub Pipeline 上面做哪些事情? > :cat: 抱歉我需要確認一下,印象中我在上面做的第一見事情是 formatting 檢查,還有就是 cppcheck 對 C 語言的靜態分析。對了,還有一個東西是我試圖要加入的那個unit test跟integration test的部分,那因為這個部分呢?團隊人手還不沒有相當足夠的關係,所以我只有把對這個test的部分留下一個框架,讓後續的開發者能夠新增對他的函式以及就有函式的 testing 補完這樣。 :dog: 我看你的 Makrfile,好 ... > :cat: 對,沒有加 .PHONY :dog: 看起來沒爆跟CI,還蠻中規中矩。這網路我就不穩了,因為。因為我也不太會。 :dog: 那你這邊有一個 binary staged build...恩,你可以大概描述一下 Docker 跟 VM 的區別是什麼? > :cat: Okay, 基本上 Docker 是 container 麻,那 container 就是我們可以把它想像成就是所謂的 namespace,加上 chroot。 > :cat: 過去我在實做自己的 container 的時候,確實就是這樣讓 container 內部環境跟外部做隔離。至於那個 Cgroup 對於單純 container 的觀念就不太重要,因為那是 for load balancing 的。然後 seccomp 的話也是因為 security 的部份才加進去。 > :cat: 所以簡而言之,所以單純就我只是如果只是,就想要把一個東西封裝起來,在那個東西裡面的話,就是主要就兩個:chroot 跟 namespace。 :dog: 哦,那你這邊有提到你對 container 做編排的時候要用到 docker swarm 跟 docker-compose。嗯是,欸那想問一下這兩個工具的差別? > :cat: Docker swarm 的話,就是告訴說我的 host 說這邊有這個 container 你可以跨裝置調度,中間走 URI 形式。而 docker-compose 的話就是這個 container 的環境要怎麼去跑起來。 > :cat: 一時間忘記他的是 docker swarm 的 master 術語叫什麼東西...? :dog: 我不知道,我沒用過 docker swarm。 > :cat: OK,他就是我會有是要先把這個 docker routine 變成一個 node 節點,然後每個都是一個節點,然後你在這些節點是用人工的方式選出: OK,我哪個節點是 master,或者是說哪個節點是最主要的,那個節點是 slave,然後再去對就它做控制。因為 Docker 跑在 systemd 底下是一個 service 麻,所以可以假設所有 slave 機器上面都有 Docker socket。可以走 URI 形式反向代理到。 :dog: 哦。那你今天有提到誒,你可以設置 5000 個 client。 > :cat: 對 :dog: 那你這個 5000 的時候呢?他還是不斷的在查找VPN的,應該說他他不斷在傳送流量嗎?還是說他就只是掛著而已? > :cat: 好,這是我們比較特殊的做法,她呢其實上是事實上是掛著的。當初我的測試方式是寫 shell script 不斷幫我建連線,我再去做操作。 :dog: 沒有啦,你今天如果要應徵網路,你如果應徵網管,你可以這樣形容。但是如果你今天要來 backend,你不可以這樣寫。 > :cat: 恩對,確實這邊應該做改進。 :dog: 然後VPN又是一個那個秘密存取量非常大量的服務的情況下,這個是會不會沒有辦法那麼有效率運行?因為一個一筆一筆經過加密的資料進來,我始終來說先解密,在在拉出來再送出去,所以這不能靠別的成本非常高,所以在memory上面,這個成本是符合不了的。而且他分散出不同的系統出來,然後分散在不同的這個那個 Matrix 上面,才能做到這樣事情,那你的這個 High scalability 是? > :cat: Ok, 我需要簡介一下當初的情境。 :dog: 好喔 > :cat: 這原本是要 propose 給我們學校,學校原本的解法是:你需要一些新的VPN服務,他就新買一臺機器,然後重新設定整台 vpn server,然後去公告說我們多一臺機器,請學生自己連上去,而不是說我有一個統一的介面,然後就是說OK,我現在後面到底有多少機器不重要,這樣得一層虛擬化。 :dog: 那你怎麼做虛擬化? > :cat: SSO 是綁學校的,所以他當然他可能會有那個 buttleneck 在 SSO 上面,畢竟我們不應該 cache 學生的帳號密碼。而在我拿到 SSO 認證的資料之後,我會配給你一台 VPN Server,讓你拿 key pair 直接跟 VPN server 互動。我中間統一界面就不再介入互動。 :dog: 那你這邊有用到普羅米修斯。去監測所有的container,他們當下的CPU負載量。你普羅米修斯是架設在哪裡? > :cat: 在那個一次性的server上面,因為它需要知道需要配發出去的 end point 當下情況怎麼樣,而且監控這的開銷沒有到很大,所以就放在這機器上。 > :dog: 開銷不大?那你會怎麼解決普羅米修斯是 time series data 他的資料量不斷上漲這個硬碟開銷問題? > :cat: 確實當初是沒有考慮到這問題,沒錯,對,那如果是我現在要解決。資料量世界時間上漲的問題的話,我會比照我過去寫 init.d 的作法,把舊有的 log 做壓縮存放,只 keep 住近期的 log,可能 30 天或是幾天。如果有需要的話,非常久的 log 也可以另外保存。只是我沒有試過普羅米修斯這樣的 api ,或許可以找找看。 :dog: 如果你今天要設計關於這種 distributed system。那你會怎麼設計的東西?都有哪些指標來判斷你這個 VPN 的健康狀態? > :cat: 這種 VPN 的情況,主要是 CPU 跟 memory 之間的 bandwidth 不夠。我要怎麼知道說他當前的情況?就是。當他沒有辦法在上升的時候就是它 congestion 的時候。那我可以去看這個 throughput 然後取一個接近的最大值,就是曾經出現過的最大值,然後算這個percentage 現在到多少了。 :dog: 就這樣嗎? > :cat: 恩,我得理解釋這樣,那想問問你覺得怎麼設計會比較好? :dog: 通常我自己在設計來選上大概會分層。分成5層吧。最下面一層當然就是系統性,就是 cpu memory,然後 io 還有那些底層東西,因為這些東西掛了,你上面都不用講。 :dog: 然後再上面一層就是 application,應該說 programming language runtime,像是 Python 跟 Go 管理記憶體也方式不一樣。對然後還有 Go 觸發 gc 的時候,他 stop the world,一下就佔了幾百毫秒。然後 Python generation 3 個時代到底有多少?他是一直沒有講到。 :dog: 然後再往上一層,會是像是API。那就是哪些 end point 或是說哪些 gRPC 的 function 被 call 了多少次。然後他 return state 是多少?或者 exception rate 到底有多少,然後還有呢,它response time到底是?那一個API特別慢,然後我們會覺察到 :dog: 第4層是 external dependency,其實我們要怎麼去確認,像是你現在如果有擋一些CDN,cloudflare 之類的,你要去監控它,就如果 cloudflare 下去了。那妳有監控他,你就比較及早知道是他們下去,而不是你們的問題。 :dog: 第5層是是商業邏輯方面,像是你今天有個使用者上來,然後連線,那它連線成功率是多少?如果一般藏在狀態下,基本上應該要99趴以上連線成功,那今天如果掉到97趴是有哪裡不對勁? :dog: 大概會分成這五層。 > :cat: 可是我們要怎麼知道說使用者的連線成功率有多少? :dog: 自己寫吧,註冊還是什麼?這的話通常就是一個長期的,像是滾動平均數,對,就是只要有使用的嘗試,連你的服務你就記錄一次。她連線的成功很失敗。所以會需要一個統一的介面,然後讓他去monitor說到底使用者做了什麼樣的事情?你的普羅米修斯應該是透過一些 client side 來為整合。而你只是透過你的這個 service 去 export 一些 matrix 給他跑這個設備 supports,你可以去研究一下普羅米修斯不同程式語言的 client,它裡面會有更豐富的的 matrix 可以使用。 :dog: 那接下來問一下 Multi-Tenancy 的問題,如果你的5000個 client 中,其中一個流量是其他人的100萬倍,那你覺得服務應該怎么做調節才不會被一個卡按把所有單位吃光? > :cat: 我能把 DoS 情況 kill 掉嗎? :dog: 那這個人貢獻你公司 30% 的營收,你不能把他殺掉怎麼辦? > :cat: 如果是 Wireguard 的 VPN service 的話,理論上不可能做到欸。因為 client-server 的 key pair 相關 config 都寫死了,只能派送一個更新請它重新連線到新的機器,請它自己連過去。 :dog: OK好,那接下來再問一下,如果你今天整個 VPN server 倒站,你覺得你要花多少時間才能 recovery? > :cat: 怎麼樣的倒站? :dog: 好,比如說機房直接備斷電。 > :cat: 那我有辦法讀取到硬碟內部的資料嗎?我有備份嗎? :dog: 可以,你可以讀或有備份。 > :cat: 因為我們的服務是用 container 部屬的,除了 VPN key-pair 的部份其他是軟體定義。所以可以直接在複製到需要去搬移的目標上面繼續運行。 :dog: 那大概要多久?你有想過這個時間嗎? > :cat: 好吧,這是一個蠻重要的問題,但是我沒有試過,沒辦法估計。 :dog: 對,需要 server Down time 有多少?應該說有一個概念叫 service level agreement,對它是由 service level objective 這個比較偏 SRE 的概念,通常你會承諾你的客戶說你一個月之內有 99.99% 的時間,你的系統要是啊。當你對於每一每一次不同層級災害發生的機率跟你所需要的 recovery time 去做計算,這算出來就是你能承諾客戶百分之多少啪的 uptime 的一個數字。嗯,這個會使你如果需要商業化,你的系統會需要算。 > :cat: 確實是個蠻重要的問題。 :dog: 那剛剛提到商業化,如果你今天你要把你的服務商轉,那你會怎麼設計收費模式? > :cat: 有沒有相關的所有收費模式可以參考,因為畢竟我對。這個東西沒有概念的話,就算回答也沒辦法特別評估出什麼東西。 :dog: 目前比較常見的就就你在 YouTube 上可能看到廣告那個。可能就是一般流量一下就一般普普流量的你就等下就沒有對吧?然後流量大一點,或者說你要確保它穩定度的話,你可能就給他一個 premium。所以說免費版友每30分鐘段它連線一次之類的。 > :cat: 那可能這還要再討論看看。 :dog: 最後你有沒有看過 Python 3.11? > :cat: 我有看到說他他在那個效能提升上面非常顯著,但我忘記具體數字多少? 60%? :dog: 對,10% 到 60%,那他是怎麼達到? > :cat: 我有瀏覽過 release note 看到過,可是我忘記了。 :dog: 就是稍微說一下,就是它大概是怎麼樣提升?因為我確實也忘記了。那我們直接找那個 release note。 > :cat: 他有提到 frozen import,這影響應該不大吧? :dog: 我覺得是 python runtime 影響比較大。 > :cat: 我記得每個語言對於 string 的優化方式不一樣,比如說 Javascript 會用 string interning 的方式 :dog: Python 也有這樣的東西 > :cat: 可是我記得 Python 的 str 是會重新 new 一塊出來 :dog: Python 的 pymalloc 會在你的 str 小於 20 的時候,自動用 global interning 的方式,它就是一個 singleton object,如果是 20 以上的話,他不會重新利用 immutable str 他是其他記憶體區段。因為 Python 的記憶體配置會是 4 byte, 8 byte, 16 byte ... 一個 pool。這樣是沒有辦法做拼接的。 > :cat: 可是 8 byte pool 內部可以互相拼接嗎? :dog: 不行,這樣 gc 會有問題。因為你拼接的話就會讓它多很多莫名奇妙的 reference count。 :dog: 那大概就這樣吧! > :cat: 謝謝 ### 檢討 1. STAR method interview 不要流水帳 2. 直接告訴面試官,我準備可以回答 xxx yyy zzz 等幾個方向,你要哪一個方向? 3. 履歷資訊密度要高,盡量壓在一頁,多點數字 ## [C/C++ Engineer, NVIDIA](https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/C-C---Engineer_JR1962904) :dog: 你好,因為我們這個 position 有高度的 concurrent performance 需求,所以在你自我介紹之後我會問你關於 concurrency 的問題。這樣可以嗎? > :cat: 好的,沒問題。 :dog: 那就先請你自我介紹一下看看吧 :cat: 我是一個 RD,平常興趣真的就是寫程式。上班的時候寫C++ 寫3個作業系統上的資安產品。 :cat: 那其他平常時候,我手邊業餘會寫的程式有: :cat: 比如說,最近要回去學校對學弟妹分享的東西是一個網站的前後端,透過C++做撰寫。那會去處理一些後端的邏輯以及前端的算繪。語法是 Django 可是呢那只是語法,其中我要拿來做重新 parsing 的語言是用C++,也就是說,一個的 Django 的 C++ renderer。 :cat: 然後我平常也有在寫其他的APP,比如說,做 real time 的藍牙控制 IoT 設備,其中包括我要克服的問題會有跨平臺的問題,有的 client 機器有那個 Linux 機器也有 macOS 機器。 :cat: 那再來就是說,我前陣子有在寫這個 Faceboo"C",也就是說用C語言寫出來的 Facebook 專案。 :cat: 過去也有跟 Jserv 一起貢獻 contribute 一些書,比如說 Linux kernel module programming guide,還有 LKSI 就是Linux kernel schedule internal 這兩本書。平常也會去對那個開源社群做貢獻,比如說 OPass。 :cat: 也有貢獻過 Debian。 :cat: 寫網頁的話,也有碰過 vue.js, Python 的 Flask, Golang,或者是 C 語言直接透過透碰 raw socket 的方式,去寫我們過去社群的產品開發。 :cat: 總之,非常多各式各樣的開發經驗,那看你會想要問哪個方向;然後當然也有跟團隊成員意見不同的時候,我們該如何溝通協調的經驗。 :dog: 好,了解。所以你平常對電腦就很有興趣,然後也會做開源貢獻這樣子? :cat: 是的,因為過去從至少從 2016 年到現在 2022,每年都會參加各大社群、研討會。 :dog: 了解。那平常所在工司的專案大概有哪一些就是有你有興趣的部分?然後可能像或是自己想要改進自己的技術部分? :cat: