摘要:有一句名言計(jì)算機(jī)科學(xué)中的任何問(wèn)題都可以通過(guò)加上一層間接層來(lái)解決,一層不夠就再加一層。計(jì)算機(jī)科學(xué)的確是靠著一層又一層的抽象與封裝解決了巨量的問(wèn)題。
David John Wheeler有一句名言“計(jì)算機(jī)科學(xué)中的任何問(wèn)題都可以通過(guò)加上一層間接層來(lái)解決”,一層不夠就再加一層。后半句是我加的 (* ̄︶ ̄) ,雖然有點(diǎn)玩笑的意思,但是也的確能說(shuō)明一些問(wèn)題。計(jì)算機(jī)科學(xué)的確是靠著一層又一層的抽象與封裝解決了巨量的問(wèn)題。
我們來(lái)簡(jiǎn)單回顧一下:
開(kāi)始的時(shí)候是程序員直接輸入二進(jìn)制指令來(lái)操縱硬件的,不僅性能低下還很耗費(fèi)用戶時(shí)間;
于是后來(lái)出現(xiàn)了操作系統(tǒng),用文件、進(jìn)程與線程、地址空間抽象了磁盤(pán)、CPU與內(nèi)存,統(tǒng)一和簡(jiǎn)化了硬件訪問(wèn)方式;
機(jī)器語(yǔ)言對(duì)用戶不友好,于是便出現(xiàn)了匯編語(yǔ)言、中級(jí)語(yǔ)言(如C)、高級(jí)語(yǔ)言(如Java)的包裝,其最終執(zhí)行還是要轉(zhuǎn)化為機(jī)器語(yǔ)言;
裸高級(jí)語(yǔ)言大家還用得不爽,覺(jué)得開(kāi)發(fā)效率低,于是又出現(xiàn)了各種框架(如Spring、Hibernate)
......
這樣一層一層抽象包裝下來(lái),我們要想實(shí)現(xiàn)一個(gè)功能比如定時(shí)寫(xiě)文件等已經(jīng)變成了很簡(jiǎn)單的事,只需要幾行代碼就搞定了。
但是抽象層數(shù)過(guò)多就會(huì)導(dǎo)致我們頂層的用戶有時(shí)候會(huì)出現(xiàn)一些莫名其妙的問(wèn)題,我們用一個(gè)實(shí)際的案例偽共享來(lái)說(shuō)明一下
public class FalseSharing { private static AtomicLong time = new AtomicLong(0); public static void main(String... args) throws InterruptedException { int testNum = 50; for (int i = 0 ; i< testNum;i++){// 測(cè)試50次 Thread thread = new Thread(new Job()); thread.start(); thread.join(); } System.out.println(time.get()/1000/testNum + " us,avg"); } static class Job implements Runnable{ @Override public void run() { int number = 8; int iterationNumber = 20000; CountDownLatch countDownLatch = new CountDownLatch(number); Obj[] objArray = new Obj[number]; for (int i = 0;i < number;i++) { objArray[i] = new Obj(); } long start = System.nanoTime(); for (int i = 0;i < number;i++){ int ii = i; Thread thread = new Thread(new Runnable() { int iterationNumberInner = iterationNumber; @Override public void run() { while (iterationNumberInner-->0){ objArray[ii].aLong+=1L; } countDownLatch.countDown(); } }); thread.start(); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } long end = System.nanoTime(); time.getAndAdd(end-start); } } @Contended private static final class Obj{ private volatile long aLong = 8L;//8Bytes // private volatile long a=2L,b=2L,c=2L,d=2L,e=2L,f=2L,g=2L;//***** } }
全部代碼在此,為了避免Java JIT(這也是一層抽象)的影響,我們每次執(zhí)行都要加參數(shù)-Xint來(lái)強(qiáng)制使用解釋模式。
在我的機(jī)器上(4core,8processor,Core-i7),直接運(yùn)行這段代碼得到結(jié)果1是4594 us,avg這個(gè)級(jí)別,在結(jié)果1基礎(chǔ)上把//*****一行取消注釋得到結(jié)果2是3916 us,avg 這個(gè)級(jí)別,在結(jié)果1基礎(chǔ)上運(yùn)行參數(shù)加上-XX:-RestrictContended使得@Contended起作用就能得到結(jié)果3是3466 us,avg。
這時(shí)候頂層用戶就會(huì)莫名奇妙了,怎么多了幾個(gè)字段運(yùn)行時(shí)間反而減小了?怎么加上@Contended后時(shí)間就更短了?
從Java代碼這一層次的抽象來(lái)看,完全是沒(méi)有問(wèn)題的,那么問(wèn)題究竟在哪呢?
我們知道一個(gè)CPU中的每個(gè)核是有自己的Cache的,高級(jí)別的L1是自己私有的,更低級(jí)別的L2、L3等可能是私有的,也可能是不同核共享的。這些不同級(jí)別的緩存(一次訪問(wèn)時(shí)間在幾個(gè)ns左右)是用來(lái)彌補(bǔ)CPU的快速(一個(gè)周期通常零點(diǎn)幾個(gè)ns)和內(nèi)存訪問(wèn)的慢速(一次訪問(wèn)時(shí)間在幾十個(gè)ns)之間的鴻溝的,而且是以CacheLine Size: N Bytes(Core-i7是64)為基本單位的,依據(jù)局部性原理一次性把內(nèi)存中該訪問(wèn)變量周?chē)?strong>N Bytes內(nèi)容拷貝到Cache中,如果一個(gè)對(duì)象不夠N Bytes,就有可能和幾個(gè)對(duì)象共用一個(gè)CacheLine,這樣一個(gè)線程刷新Cacheline就會(huì)導(dǎo)致其他線程的緩存失效,要去更低級(jí)別的Cache甚至內(nèi)存訪問(wèn),就大大降低了訪問(wèn)速度。
這樣回到剛才的問(wèn)題,多加幾個(gè)字段能在一定程度上增大該對(duì)象所占空間,減小共用CacheLine的幾率,所以訪問(wèn)時(shí)間減少了,而@Contended則使得一個(gè)對(duì)象一個(gè)CacheLine,直接幫我們避免了偽共享,所以訪問(wèn)時(shí)間更少了。要解決這個(gè)問(wèn)題,光知道Java這一層抽象(語(yǔ)法、JDK API等)是不可能的,還得懂操作系統(tǒng)、甚至CPU芯片原理這些層抽象才行。
再比如說(shuō),JVM幫我們把C/C++的手動(dòng)內(nèi)存管理封裝了一層抽象做到內(nèi)存自動(dòng)管理從而解放了我們,我們當(dāng)然用得很爽,但是如果我們不懂這一層的抽象與封裝,那么程序OOM的時(shí)候就只能傻眼了。
最后總結(jié)一下,計(jì)算機(jī)科學(xué)中的任何問(wèn)題都可以通過(guò)加上一層間接層來(lái)解決,這是很正確的,但是也正是因?yàn)橐粚右粚拥某橄蠛桶b,導(dǎo)致出了問(wèn)題后很難定位,你都不知道問(wèn)題究竟是出現(xiàn)在哪一層。所以要想提高技術(shù)水平不僅要知其然(看得見(jiàn)最頂層的包裝)也要知其所以然(看得見(jiàn)底層的包裝),每一層如果都懂或者說(shuō)了解一些,那么出了問(wèn)題很大程度上都可以憑直覺(jué)定位,即使不能憑直覺(jué)也可以通過(guò)各種手段debug,只會(huì)最頂層的抽象很多時(shí)候就只能望bug興嘆了。
訪問(wèn)原文,來(lái)自MageekChiu。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69638.html
摘要:是一個(gè)典型的模式架構(gòu),用戶通過(guò)終端將字符流傳遞給。仿照的工作原理,我們?cè)趨f(xié)議之上設(shè)計(jì)了,見(jiàn)下圖真實(shí)實(shí)現(xiàn)中,是應(yīng)用層的通訊協(xié)議。僵尸進(jìn)程問(wèn)題我們知道由于缺少而導(dǎo)致僵尸進(jìn)程無(wú)法回收的問(wèn)題迄今存在。進(jìn)入構(gòu)建環(huán)境執(zhí)行命令。 Coding WebIDE 做個(gè)國(guó)內(nèi)首個(gè)基于 Docker 技術(shù)的云端開(kāi)發(fā)平臺(tái)于4月1日正式上線。本文主要和大家分享和探討 Docker 在 Web IDE 中運(yùn)用的一些經(jīng)...
摘要:只能在不同的時(shí)候選用不同的假設(shè)和不同的理論來(lái)解釋問(wèn)題,許來(lái)西的文章講到科學(xué)一定程度上通過(guò)放棄一貫性換取了實(shí)用性,放棄自洽性換取了它洽性。然而遺憾的是本身只提供了模塊和洋蔥模型的最小封裝。 在寫(xiě)干貨之前,我想先探(qiang)討(diao)兩個(gè)問(wèn)題,模式的局限性?模式有什么用? 最近看到一篇文章對(duì)我啟發(fā)很大,許來(lái)西在知乎的回答《哲學(xué)和科學(xué)有什么關(guān)聯(lián)?》,全篇較長(zhǎng),這里摘錄我要引出的一點(diǎn):...
摘要:首先是最頂層的抽象,這個(gè)里面最基礎(chǔ)的就是和,記憶中和的抽象是類(lèi)似的,將計(jì)算結(jié)果和偏導(dǎo)結(jié)果用一個(gè)抽象類(lèi)來(lái)表示了。不過(guò),本身并沒(méi)有像其它兩個(gè)庫(kù)一樣提供,等模型的抽象類(lèi),因此往往不會(huì)直接使用去寫(xiě)模型。 本文將從deep learning 相關(guān)工具庫(kù)的使用者角度來(lái)介紹下github上stars數(shù)排在前面的幾個(gè)庫(kù)(tensorflow, keras, torch, theano, skflow, la...
摘要:李飛飛花名飛刀,阿里巴巴集團(tuán)副總裁,高級(jí)研究員,達(dá)摩院首席數(shù)據(jù)庫(kù)科學(xué)家,阿里云智能事業(yè)群數(shù)據(jù)庫(kù)產(chǎn)品事業(yè)部負(fù)責(zé)人,杰出科學(xué)家。是阿里云的云原生數(shù)據(jù)庫(kù),目前已有非常深厚的技術(shù)積累。 阿里妹導(dǎo)讀:云計(jì)算大潮來(lái)襲,傳統(tǒng)數(shù)據(jù)庫(kù)市場(chǎng)正面臨重新洗牌的情境,包括云數(shù)據(jù)庫(kù)在內(nèi)的一批新生力量崛起,動(dòng)搖了傳統(tǒng)數(shù)據(jù)庫(kù)的壟斷地位,而由云廠商主導(dǎo)的云原生數(shù)據(jù)庫(kù)則將這種改變推向了高潮。 云時(shí)代的數(shù)據(jù)庫(kù)將面臨怎樣的...
閱讀 1850·2023-04-26 00:59
閱讀 3142·2021-11-15 18:10
閱讀 3088·2021-09-22 16:02
閱讀 772·2021-09-02 15:15
閱讀 3726·2019-08-30 15:56
閱讀 1925·2019-08-30 15:54
閱讀 2869·2019-08-29 16:31
閱讀 2044·2019-08-29 16:10