1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        編程中的惰性思想

        共 3417字,需瀏覽 7分鐘

         ·

        2021-03-11 00:51

        f34be69d5b25e8c10f3813f69741c797.webp

        6d185f6bfd88d03be68b00cc34cc2f28.webp

        惰性思想

        我想大家在學(xué)習(xí)工作中,一定或多或少有Deadline的經(jīng)歷吧,假期作業(yè)留到最后快開學(xué)了才寫,衣服拖到最后沒衣服換了才洗,這樣做好不好呢?其實(shí)還行,一般Deadline期間寫作業(yè)洗衣服效率挺高的,而換一個(gè)思路來說,在寫作業(yè)洗衣服之前,你都是空閑的,可以盡情做別的事情的,程序設(shè)計(jì)里面,我理解的惰性思想其實(shí)跟Deadline很像,資源分配推遲到不能再推遲為止


        6d185f6bfd88d03be68b00cc34cc2f28.webp

        Linux內(nèi)存動(dòng)態(tài)分配里的惰性思想

        請(qǐng)求調(diào)頁


        術(shù)語"請(qǐng)求調(diào)頁"指的是把頁框(虛擬內(nèi)存調(diào)度單位)的分配推遲到不能再推遲為止,也就是說,一直推遲到進(jìn)程要訪問的頁不在RAM中時(shí)為止,因此引起一個(gè)缺頁異常。


        請(qǐng)求調(diào)頁技術(shù)背后的動(dòng)機(jī)是:進(jìn)程開始運(yùn)行時(shí)并不訪問其地址空間中的全部地址;事實(shí)上,有一部分地址也許永遠(yuǎn)不會(huì)被進(jìn)程使用。此外,程序的局部性原理保證了在程序執(zhí)行的每個(gè)階段,真正引用的進(jìn)程頁只有一小部分,因此臨時(shí)用不著的頁所在的頁框可以由其他進(jìn)程來使用。這樣增加了系統(tǒng)中的空閑頁框的平均數(shù),從而更好的利用空閑內(nèi)存。從另一個(gè)觀點(diǎn)來看,在RAM總數(shù)保持不變的情況下,請(qǐng)求調(diào)頁從總體上使系統(tǒng)有更大的吞吐量。

        寫時(shí)復(fù)制(也就是大名鼎鼎的copy on write)


        第一代??Unix?系統(tǒng)實(shí)現(xiàn)了一種傻瓜式的進(jìn)程創(chuàng)建:當(dāng)?fork()?子進(jìn)程時(shí)候,內(nèi)核原樣復(fù)制父進(jìn)程的整個(gè)地址空間并把復(fù)制的那一份分配給子進(jìn)程。而子進(jìn)程有很多東西和父進(jìn)程一樣且不發(fā)生修改的,沒必要完全復(fù)制,這種做法既浪費(fèi)很多內(nèi)存空間,又消耗許多?CPU?周期。


        現(xiàn)在的?Unix內(nèi)核(包括Linux)采用一種更為有效的方法,稱為寫時(shí)復(fù)制,也就是大名鼎鼎的?Copy On Write。這種思想相當(dāng)簡單:父進(jìn)程和子進(jìn)程共享頁框,只是不能修改,當(dāng)修改的時(shí)候,就產(chǎn)生異常,這時(shí)內(nèi)核再把這個(gè)頁復(fù)制到一個(gè)新的頁框中并標(biāo)記為可寫,原來的頁框仍然是寫保護(hù)的。當(dāng)其他進(jìn)程試圖寫入時(shí),內(nèi)核檢查寫進(jìn)程是否是這個(gè)頁框的唯一屬主,如果是,就把這個(gè)頁框標(biāo)記為對(duì)這個(gè)進(jìn)程可寫。


        其中,頁描述符的?_count?字段用于跟蹤共享當(dāng)前頁框的進(jìn)程數(shù)目,為1時(shí)說明跟其他1個(gè)進(jìn)程共享,為0時(shí)說明只有一個(gè)進(jìn)程可寫,為-1時(shí)說明需要被釋放。


        6d185f6bfd88d03be68b00cc34cc2f28.webp

        舉例子

        JS語言反面教材


        必然很了解JS的深淺拷貝問題,問爛了的面試題了

        let a = {a:1};let b = a;let c = Object.assign({}, a)console.log(a,b,c,a===b,a===c);//{a:1} {a:1} {a:1} true falsea.a = 2;console.log(a,b,c,a===b,a===c);//{a:2}?{a:2}?{a:1}?true?false

        上面的代碼很好理解,b是淺拷貝,故而值跟著變了,c是深拷貝,故而值沒變 而對(duì)應(yīng)的變量內(nèi)存地址的話,因?yàn)?/span>JS并不能像其他語言一樣,顯式的查看變量內(nèi)存地址,但可以借助ChromeMemory工具快照,來查看其相應(yīng)的V8虛擬地址。


        73398cdb7346060a9d9cc288c1bbb1f0.webp


        明顯的,ab有著相同的內(nèi)存地址,而c因?yàn)槭巧羁截?,擁有新的?nèi)存地址;當(dāng)我們給a.a = 2重新寫入后,觀察Snapshot 12,ab的內(nèi)存地址依然相同,這是因?yàn)?/span>JS這門語言并沒有實(shí)現(xiàn)寫時(shí)復(fù)制。

        python寫時(shí)復(fù)制


        講完JS反面教材,我們?cè)賮碛^察一個(gè)實(shí)現(xiàn)了寫時(shí)復(fù)制的語言。

        terence@k8s-master:/mydata$ python3Python 3.6.9 (default, Oct  8 2020, 12:12:24) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> a = "qwer">>> print(a)qwer>>> id(a)140662197387536>>> b = a;>>> print(b)qwer>>> id(b)140662197387536//跟a的內(nèi)存地址一致>>> b = "qwert">>> id(b)140662197387592//寫時(shí)復(fù)制,內(nèi)存地址發(fā)生了變化>>>?


        PHP寫時(shí)復(fù)制


        PHP對(duì)數(shù)組實(shí)現(xiàn)了寫時(shí)復(fù)制,普通變量是沒有寫時(shí)復(fù)制的,通過下面的例子能夠清楚的看到內(nèi)存占用量的變化,只是修改了$b[0],然后整個(gè)都被復(fù)制了。(當(dāng)然也可以安裝xdebug拓展,進(jìn)一步可以觀察到數(shù)組refcount引用計(jì)數(shù)的變化)

        $a = [];for ($i=0; $i < 10000; $i++) {   $a[] = rand(0,10000);}var_dump(memory_get_usage());//9438664$b = $a;var_dump(memory_get_usage());//9438664$b[0] = 99999;var_dump(memory_get_usage());//9967104


        Rust寫時(shí)復(fù)制


        fn main() {
        let s1 = String::from("hello");
        println!("s1 heap address: {:p}", s1.as_ptr());//0x5645e759d9e0 println!("s1 stack address: {:p}", &s1);//0x7fff6a964bb8
        let mut s2 = s1;
        println!("s2 heap address: {:p}", s2.as_ptr());//0x5645e759d9e0 println!("s2 stack address: {:p}", &s2);//0x7fff6a964c70
        b = String::from("world");
        println!("s2 heap address: {:p}", s2.as_ptr());//0x5645e759da70 println!("s2 stack address: {:p}", &s2);//0x7fff6a964c70}

        對(duì)于Rust這種系統(tǒng)級(jí)語言,我們能更直觀的觀察到進(jìn)程棧中的局部變量是如何跟堆中的實(shí)際內(nèi)存地址關(guān)聯(lián)起來的。

        以了解?String?的底層會(huì)發(fā)生什么。String?由三部分組成,如下圖左側(cè)所示:一個(gè)指向存放字符串內(nèi)容內(nèi)存的指針,一個(gè)長度,和一個(gè)容量。這一組數(shù)據(jù)存儲(chǔ)在棧上。右側(cè)則是堆上存放內(nèi)容的內(nèi)存部分。

        76c223c75b616b99db717ceb2f1f4767.webp

        長度表示?String?的內(nèi)容當(dāng)前使用了多少字節(jié)的內(nèi)存。容量是?String?從操作系統(tǒng)總共獲取了多少字節(jié)的內(nèi)存。長度與容量的區(qū)別是很重要的,不過在當(dāng)前上下文中并不重要,所以現(xiàn)在可以忽略容量。

        當(dāng)我們將?s1?賦值給?s2,String?的數(shù)據(jù)被復(fù)制了,這意味著我們從棧上拷貝了它的指針、長度和容量。我們并沒有復(fù)制指針指向的堆上數(shù)據(jù)。換句話說,內(nèi)存中數(shù)據(jù)的表現(xiàn)如下圖

        9af11f60691a57229b25c4654320d8b8.webp

        當(dāng)我們修改s2時(shí),寫時(shí)復(fù)制,變成了如下所示

        5fd793aa0b0c62a68ce579e93bd5a7d0.webp


        6d185f6bfd88d03be68b00cc34cc2f28.webp

        其他例子

        前端開發(fā)場景里有懶加載,節(jié)流防抖,其實(shí)都是惰性思想的體現(xiàn),不到萬不得已,不去分配資源。

        「?? 感謝大家」

        如果你覺得這篇內(nèi)容對(duì)你挺有有幫助的話:

        1. 點(diǎn)贊支持下吧,讓更多的人也能看到這篇內(nèi)容(收藏不點(diǎn)贊,都是耍流氓 -_-)
        2. 歡迎在留言區(qū)與我分享你的想法,也歡迎你在留言區(qū)記錄你的思考過程。
        3. 覺得不錯(cuò)的話,也可以閱讀近期梳理的文章(感謝鼓勵(lì)與支持??????):

        老鐵,三連支持一下,好嗎?↓↓↓


        f6dd9c051df380a9b41a03f264a156e2.webp71a738235b7d832a04a5a19394b13b0b.webp

        3c439d22fc39c8b8265774fb2ba2a02e.webp

        點(diǎn)分享

        36b25596ba0a12edd48497d95343a945.webp

        點(diǎn)點(diǎn)贊

        5f3c0774c539434bb3ea6b492a4b2da4.webp

        點(diǎn)在

        瀏覽 93
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            久久精品女人18毛片水多国产 | 高潮免费视频 | 日产乱码一区二区三区在线观看 | 免费肏逼 | 丁香五月婷婷亚洲 | 青娱乐成人 | 健身教练被cao的嗷嗷乱叫 | 蜜臀av在线一区二区三区 | 99久久人妻无码中文字幕系列 | 人人操夜夜操 |