成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

不同內存管理方式的聰明程度大 PK

存儲 存儲軟件
代碼要在計算機上跑起來,需要一系列計算機資源:內存、網絡端口、打開的文件等等,這些資源一起被叫做進程。

[[429396]]

代碼要在計算機上跑起來,需要一系列計算機資源:內存、網絡端口、打開的文件等等,這些資源一起被叫做進程。

進程有一個專門的控制塊來記錄這些資源,叫做進程控制塊(PCB)。

這些資源里面最重要的就是內存了,進程啟動的時候會向操作系統申請一些內存。

如果內存是無限的,那么我們在上面放數據、代碼等,不用擔心不夠用,但可惜內存是有限的,我們要把用不到的內存及時的回收掉,用來放別的東西,這樣代碼才能正常的運行。

內存分為代碼區、全局數據區、堆區、棧區等,這是操作系統可執行文件的內存模型,如果是 javascript、java 這種解釋型語言,那還會再做自己的一些劃分。但總體來說,都是分為這幾部分。

代碼區的內容基本不變。

棧區存放隨著函數調用而聲明的局部變量,每個函數一個棧幀,它是有上限的,調用層次過深會棧溢出。

全局數據區存放全局變量。

棧區和全局數據區中的大對象會存放在堆上,只留一個引用。

堆區存放動態分配的大對象,占內存最多,我們內存管理也主要是管理堆內存。

為了管理好這一畝三分地的堆內存,不同的語言有不同的方式,聰明程度各不相同,我們來看一下誰更聰明吧:

C、C++

C、C++ 的內存都是程序員手動管理的,比如 C++ 的 class 有構造函數和析構函數,構造函數里申請內存,析構函數里面就把這些內存釋放掉。

是否漏掉一些內存沒釋放取決于程序員,很看程序員水平。

騰訊之前是大規模用 C++ 做服務端開發的,但是后來也逐漸轉向 go、java 了,因為 C++ 這種手動管理內存的方式,萬一某個程序員漏掉了一些內存沒釋放,那就內存泄漏了。(內存泄漏就是不再使用的內存一直占用著,導致可用內存減少),而服務器是長時間跑的,輕微的內存泄漏逐漸積累最終都會導致進程崩潰。

靠程序員來保證釋放掉不用的內存太難了,如果程序能自己回收這些垃圾內存就好了,那就解放了程序員了,代碼可靠性也更高。所以后來的高級語言基本都有了自動的垃圾回收機制。

java、javascript

c++ 那種手動管理內存的方式太麻煩了,所以 java 和 javascript 設計之初就不讓程序員操作內存,而是自己做了一套垃圾回收機制,定期把沒用的內存釋放下。

怎么檢測哪些內存沒用呢?最開始的思路是對每個對象都記錄下引用數,如果沒有被引用了,那就可以回收了,這種思路叫引用計數。

但是這個思路有個問題,萬一兩個對象你引用我我引用你,并且都沒被別的對象引用,這種循環引用的問題檢查不出來。

看來這種方式還不夠聰明。怎么優化呢?

從全局的對象開始,把所有引用的對象標記一遍,沒被標記的就清掉。這樣不管是沒被引用的,還是循環引用但是都沒被別的對象引用的,都可以檢查出來,這種思路叫做標記清除。

標記清除的思路更聰明些,所以現在的 js 引擎基本都用這個思路。

這樣的內存管理思路其實也是存在問題的,萬一有的不用的對象被放到全局了,那就永遠不會回收了。這種也會內存泄漏。

這個只能靠程序員排查了,通過工具把一些不該放到全局的變量給找出來。

js 的內存泄漏排查一般都是用 chrome devtools 的 memory 工具,他可以取到某個時間點的內存快照,做一些操作后,再取一次內存快照,兩個內存快照對比下就能找出增加了哪些全局變量。然后定位到那段內存泄漏的代碼。

比如這樣一段代碼:

5s 后在全局聲明一個變量 aaa,是正則表達式類型。

我們用 chrome devtools 的 memory 工具分別取兩次快照。

這里有不同的視圖,我們選擇比較視圖來對比兩個快照:

可以看到 delta 那一列,顯示了正則表達式的對象 + 1,這就是我們定時器里聲明的那個全局變量。

通過這種內存快照的對比,就可以定位什么操作導致的內存泄漏,進而定位到代碼。

自動的垃圾回收避免了程序員沒有釋放一些內存導致的泄漏,但是仍然會有把沒用的對象放到全局導致的泄漏。這種方案比較聰明,但也是有問題的。

rust

rust 也不需要程序員手動管理內存,但也沒有垃圾回收,卻把內存管理的更好,而且能避免 99% 的內存泄漏問題。它是怎么做到的呢?

rust 覺得堆中的對象之所以難管理就是因為被太多地方引用了,如果限制了對象只能屬于某個函數,只能有一個引用,別的引用自己復制一份去,這樣函數調用結束就可以把用到的堆中的對象全部回收了,根本不會留下垃圾。這種思路叫做所有權機制。

所有權機制通過限制對象的引用的方式來做到了不需要垃圾回收器也能很好的管理內存。而且也沒有 js 那種不小心把對象放到全局就會內存泄漏的問題。

rust 的所有權機制是更聰明的一種內存管理方式,也是因為這個原因,rust 正變得越來越火。

總結

進程的可用內存是有限的,需要及時把不再用到的變量的內存釋放掉,不同語言對內存管理的方式不同,聰明程度不同:

c、c++ 是靠程序員自己管理內存的,萬一不小心某個內存沒釋放就泄漏了。

java、javascript 則是不讓程序員自己管理,有專門的垃圾回收器,最開始通過引用計數,后來改成了標記清除,通過這種方式來找到沒用的內存釋放掉。

但萬一把沒用的對象放到了全局,那就回收不了了,這種就是內存泄漏,需要用 chrome devtools 的 memory 工具記錄兩次快照,然后做 diff,通過看內存是否增加來定位到導致內存泄漏的代碼。

rust 也不用程序員手動管理內存,但也沒有垃圾回收器,它限制了對象只能有一個引用,這樣函數調用結束就可以把對象回收掉,根本不會留下垃圾,而且也避免了把沒用的對象放到全局的那種內存泄漏(因為只允許一個引用)。

 

語言的發展規律就是這樣,讓程序員做的事情更少,也讓程序的健壯性更高。這需要更聰明的語言設計,更強大的編譯器/解釋器。

 

責任編輯:武曉燕 來源: 神光的編程秘籍
相關推薦

2009-12-25 17:15:03

Linux內存

2025-04-15 06:00:00

2013-03-14 10:28:52

管理人才管理管理方式

2015-03-16 12:49:56

虛擬化

2019-03-14 15:00:48

混合云云計算管理

2011-02-25 14:00:15

ProFTPD

2010-09-30 11:55:03

DB2表空間

2010-02-04 15:41:10

C++內存管理

2010-03-18 10:45:43

網管交換機

2010-01-21 17:15:22

可網管交換機

2017-01-04 13:27:43

SD-WANSDN網絡

2009-07-29 09:29:33

無線網絡接入方式

2024-11-27 09:58:41

Spring模塊化管理方式

2012-03-12 09:39:38

大數據IT資源

2021-02-24 14:26:05

人工智能機器學習數據

2012-05-23 11:31:09

瀏覽器帳號管理

2010-01-05 14:38:36

網管交換機

2011-11-04 16:13:53

IT管理

2011-01-27 10:57:54

北塔網絡管理運維管理
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美综合久久 | 国产精品成人一区二区三区 | 女女爱爱视频 | 亚洲欧洲在线看 | 国产成人在线一区二区 | 亚洲国产精品激情在线观看 | 成人综合一区 | 国产在线1区 | 亚洲色图网址 | 99福利在线观看 | 欧美区日韩区 | 特级特黄特色的免费大片 | xnxx 日本免费 | 成人无遮挡毛片免费看 | 淫片一级国产 | 亚洲天堂成人在线视频 | 久久精品久久综合 | 久久精品欧美一区二区三区不卡 | 日韩免费1区二区电影 | 岛国一区| 国产日韩一区 | 欧美不卡一区二区 | 91日韩| 亚洲一区二区久久 | 狠狠干天天干 | 91视频91| 欧美日韩国产一区二区三区 | 亚洲另类自拍 | 精品网 | 在线观看免费av网站 | 在线成人免费视频 | 一区二区在线不卡 | 亚洲精品久久久久久一区二区 | 日韩不卡视频在线观看 | 午夜爽爽爽男女免费观看 | 在线免费观看黄色 | 精品免费视频 | 国产精品久久久久久久久久 | 亚洲成年人免费网站 | 国产精品成人一区二区 | 特黄av|