電腦科學中抽象的好處與問題—偽共享例項分析
David John Wheeler有一句名言“電腦科學中的任何問題都可以透過加上一層間接層來解決”,一層不夠就再加一層。後半句是我加的,雖然有點玩笑的意思,但是也的確能說明一些問題。電腦科學的確是靠著一層又一層的抽象與封裝解決了巨量的問題。
我們來簡單回顧一下:開始的時候是程式設計師直接輸入二進位制指令來操縱硬體的,不僅效能低下還很耗費使用者時間;於是後來出現了作業系統,用檔案、程式與執行緒、地址空間抽象了磁碟、CPU與記憶體,統一和簡化了硬體訪問方式;機器語言對使用者不友好,於是便出現了組合語言、中級語言(如C)、高階語言(如Java)的包裝,其最終執行還是要轉化為機器語言;裸高階語言大家還用得不爽,覺得開發效率低,於是又出現了各種框架(如Spring、Hibernate)......
這樣一層一層抽象包裝下來,我們要想實現一個功能比如定時寫檔案等已經變成了很簡單的事,只需要幾行程式碼就搞定了。但是抽象層數過多就會導致我們頂層的使用者有時候會出現一些莫名其妙的問題,我們用一個實際的案例偽共享來說明一下
為了避免Java JIT(這也是一層抽象)的影響,我們每次執行都要加引數-Xint來強制使用解釋模式。在我的機器上(4core,8processor,Core-i7),直接執行這段程式碼得到結果1是4594 us,avg這個級別,在結果1基礎上把//*****一行取消註釋得到結果2是3916 us,avg 這個級別,在結果1基礎上執行引數加上-XX:-RestrictContended使得@Contended起作用就能得到結果3是3466 us,avg。
這時候頂層使用者就會莫名奇妙了,怎麼多了幾個欄位執行時間反而減小了?怎麼加上@Contended後時間就更短了?從Java程式碼這一層次的抽象來看,完全是沒有問題的,那麼問題究竟在哪呢?
我們知道一個CPU中的每個核是有自己的Cache的,高階別的L1是自己私有的,更低階別的L2、L3等可能是私有的,也可能是不同核共享的。這些不同級別的快取(一次訪問時間在幾個ns左右)是用來彌補CPU的快速(一個週期通常零點幾個ns)和記憶體訪問的慢速(一次訪問時間在幾十個ns)之間的鴻溝的,而且是以CacheLine Size: N Bytes(Core-i7是64)為基本單位的,依據區域性性原理一次性把記憶體中該訪問變數周圍的N Bytes內容複製到Cache中,如果一個物件不夠N Bytes,就有可能和幾個物件共用一個CacheLine,這樣一個執行緒重新整理Cacheline就會導致其他執行緒的快取失效,要去更低階別的Cache甚至記憶體訪問,就大大降低了訪問速度。
這樣回到剛才的問題,多加幾個欄位能在一定程度上增大該物件所佔空間,減小共用CacheLine的機率,所以訪問時間減少了,而@Contended則使得一個物件一個CacheLine,直接幫我們避免了偽共享,所以訪問時間更少了。要解決這個問題,光知道Java這一層抽象(語法、JDK API等)是不可能的,還得懂作業系統、甚至CPU晶片原理這些層抽象才行。
再比如說,JVM幫我們把C/C++的手動記憶體管理封裝了一層抽象做到記憶體自動管理從而解放了我們,我們當然用得很爽,但是如果我們不懂這一層的抽象與封裝,那麼程式OOM的時候就只能傻眼了。
最後總結一下,電腦科學中的任何問題都可以透過加上一層間接層來解決,這是很正確的,但是也正是因為一層一層的抽象和包裝,導致出了問題後很難定位,你都不知道問題究竟是出現在哪一層。所以要想提高技術水平不僅要知其然(看得見最頂層的包裝)也要知其所以然(看得見底層的包裝),每一層如果都懂或者說了解一些,那麼出了問題很大程度上都可以憑直覺定位,即使不能憑直覺也可以透過各種手段debug,只會最頂層的抽象很多時候就只能望bug興嘆了。
本文轉自:MageekChiu 作者:mageek
原文連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31137683/viewspace-2213173/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 腦機介面例項二:腦電訊號CSP處理腦機介面
- 電腦科學的學科分類
- Java多執行緒開發|volatile與偽共享問題Java執行緒
- Dart - 抽象類的例項化Dart抽象
- 幽默:軟體工程讓你結合上下文解決問題,電腦科學讓你抽象出通用演算法解決問題軟體工程抽象演算法
- 格智學院:電腦科學與技術
- 抽象結合例項 Employee抽象
- guava之ImmutableMap使用例項及好處Guava
- MySQL共享鎖:使用與例項詳解MySql
- 電腦科學自學指南
- 線上問診app開發的好處與注意事項APP
- 【譯】2019年JavaScript中的電腦科學:連結串列JavaScript
- CRLF Injection漏洞的利用與例項分析
- 電腦科學精彩帖子收集
- eventlet 之 monkeypatch 帶來的若干相容性問題例項分析
- 《計算機與電腦科學》摘錄筆記計算機筆記
- 如何自學電腦科學與技術(Teach Yourself Computer Science)
- 06從一個例項看資料抽象與封裝抽象封裝
- Golang中命名引數的高階使用技巧與例項分析Golang
- 遞迴中Return例項分析遞迴
- 電腦更新有什麼好處和壞處,怎麼更新電腦呢
- makefile--偽目標語法與程式設計例項程式設計
- PNAS:美國電腦科學學生CS技能超中國
- 電腦科學名人名言
- nodejs打包問題解決例項NodeJS
- Mac電腦使用imazing過程中遇到的問題Mac
- 中國電子學會:2021全球腦科學發展報告
- 關於電腦科學的50個誤解
- 無法連線windows例項的問題排查Windows
- Navigation問題詳解——Fragment建立新的例項NavigationFragment
- for迴圈的例項分析
- 【電腦科學】演算法——遞迴演算法遞迴
- 電腦科學哲學(史丹佛大學哲學百科全書)
- 電腦共享資料夾怎麼設定 電腦共享文件的辦法
- 利用jstack定位典型效能問題例項JS
- 線上問題排查例項分析|關於Redis記憶體洩漏Redis記憶體
- 線上問題排查例項分析|關於 Redis 記憶體洩漏Redis記憶體
- Spring Cloud Finchley版中Consul多例項註冊的問題處理SpringCloud