當前位置:首頁 > 內存
  • 你不好奇內存耗盡後Redis會發生什麼?

    作者:雙子孤狼 原文地址://www.cnblogs.com/lonely-wolf/p/14403264.html 作為一台服務器來説,內存並不是無限的,所以總會存在內存耗盡的情況,那麼當 Redis 服務器的內存耗盡後,如果繼續執行請求命令,Redis 會如何處理呢? 設置有效期 使用Redis 服務時,很多情況下某些鍵值對只會在特定的時間內有效,為了防止這種類型的數據一直佔有內存,我們可以給鍵值對設置有效期。Redis 中可以通過 4 個獨立的命令來給一個鍵設置過期時間: expire key ttl:將  key 值的過期時間設置為  ttl  秒。 pexpire key ttl:將  key 值的過期時間設置為  ttl  毫秒。 expireat key timestamp:將  key 值的過期時間設置為指定的  timestamp  秒數。 pexpireat key timestamp:將  key 值的過期時間設置為指定的  timestamp  毫秒數。 PS:不管使用哪一個命令,最終 Redis 底層都是使用 pexpireat 命令來實現的。另外,set 等命令也可以設置 key 的同時加上過期時間,這樣可以保證設值和設過期時間的原子性。 設置了有效期後,可以通過 ttl 和 pttl 兩個命令來查詢剩餘過期時間(如果未設置過期時間則下面兩個命令返回 -1,如果設置了一個非法的過期時間,則都返回 -2): ttl key 返回  key 剩餘過期秒數。 pttl key 返回  key 剩餘過期的毫秒數。 過期策略 如果將一個過期的鍵刪除,我們一般都會有三種策略: 定時刪除 :為每個鍵設置一個定時器,一旦過期時間到了,則將鍵刪除。這種策略對內存很友好,但是對  CPU 不友好,因為每個定時器都會佔用一定的  CPU 資源。 惰性刪除 :不管鍵有沒有過期都不主動刪除,等到每次去獲取鍵時再判斷是否過期,如果過期就刪除該鍵,否則返回鍵對應的值。這種策略對內存不夠友好,可能會浪費很多內存。 定期掃描 :系統每隔一段時間就定期掃描一次,發現過期的鍵就進行刪除。這種策略相對來説是上面兩種策略的折中方案,需要注意的是這個定期的頻率要結合實際情況掌控好,使用這種方案有一個缺陷就是可能會出現已經過期的鍵也被返回。 在 Redis 當中,其選擇的是策略 2 和策略 3 的綜合使用。不過 Redis 的定期掃描只會掃描設置了過期時間的鍵,因為設置了過期時間的鍵 Redis 會單獨存儲,所以不會出現掃描所有鍵的情況: typedef struct redisDb {    dict *dict; //所有的鍵值對    dict *expires; //設置了過期時間的鍵值對   dict *blocking_keys; //被阻塞的key,如客户端執行BLPOP等阻塞指令時   dict *watched_keys; //WATCHED keys   int id; //Database ID   //... 省略了其他屬性} redisDb; 8 種淘汰策略 假如 Redis 當中所有的鍵都沒有過期,而且此時內存滿了,那麼客户端繼續執行 set 等命令時 Redis 會怎麼處理呢?Redis 當中提供了不同的淘汰策略來處理這種場景。 首先 Redis 提供了一個參數 maxmemory 來配置 Redis 最大使用內存: maxmemory  或者也可以通過命令 config set maxmemory 1GB 來動態修改。 如果沒有設置該參數,那麼在 32 位的操作系統中 Redis 最多使用 3GB 內存,而在 64 位的操作系統中則不作限制。 Redis 中提供了 8 種淘汰策略,可以通過參數 maxmemory-policy 進行配置: 淘汰策略 説明 volatile-lru 根據 LRU 算法刪除設置了過期時間的鍵,直到騰出可用空間。如果沒有可刪除的鍵對象,且內存還是不夠用時,則報錯 allkeys-lru 根據 LRU 算法刪除所有的鍵,直到騰出可用空間。如果沒有可刪除的鍵對象,且內存還是不夠用時,則報錯 volatile-lfu 根據 LFU 算法刪除設置了過期時間的鍵,直到騰出可用空間。如果沒有可刪除的鍵對象,且內存還是不夠用時,則報錯 allkeys-lfu 根據 LFU 算法刪除所有的鍵,直到騰出可用空間。如果沒有可刪除的鍵對象,且內存還是不夠用時,則報錯 volatile-random 隨機刪除設置了過期時間的鍵,直到騰出可用空間。如果沒有可刪除的鍵對象,且內存還是不夠用時,則報錯 allkeys-random 隨機刪除所有鍵,直到騰出可用空間。如果沒有可刪除的鍵對象,且內存還是不夠用時,則報錯 volatile-ttl 根據鍵值對象的 ttl 屬性, 刪除最近將要過期數據。如果沒有,則直接報錯 noeviction 默認策略,不作任何處理,直接報錯 PS:淘汰策略也可以直接使用命令 config set maxmemory-policy  來進行動態配置。 LRU 算法 LRU 全稱為:Least Recently Used。即:最近最長時間未被使用。這個主要針對的是使用時間。 Redis 改進後的 LRU 算法 在 Redis 當中,並沒有採用傳統的 LRU 算法,因為傳統的 LRU 算法存在 2 個問題: 需要額外的空間進行存儲。 可能存在某些  key 值使用很頻繁,但是最近沒被使用,從而被  LRU 算法刪除。 為了避免以上 2 個問題,Redis 當中對傳統的 LRU 算法進行了改造,通過抽樣的方式進行刪除。 配置文件中提供了一個屬性 maxmemory_samples 5,默認值就是 5,表示隨機抽取 5 個 key 值,然後對這 5 個 key 值按照 LRU 算法進行刪除,所以很明顯,key 值越大,刪除的準確度越高。 對抽樣 LRU 算法和傳統的 LRU 算法,Redis 官網當中有一個對比圖: 淺灰色帶是被刪除的對象。 灰色帶是未被刪除的對象。 綠色是添加的對象。 左上角第一幅圖代表的是傳統 LRU 算法,可以看到,當抽樣數達到 10 個(右上角),已經和傳統的 LRU 算法非常接近了。 Redis 如何管理熱度數據 前面我們講述字符串對象時,提到了 redisObject 對象中存在一個 lru 屬性: typedef struct redisObject {    unsigned type:4;//對象類型(4位=0.5字節)    unsigned encoding:4;//編碼(4位=0.5字節)    unsigned lru:LRU_BITS;//記錄對象最後一次被應用程序訪問的時間(24位=3字節)    int refcount;//引用計數。等於0時表示可以被垃圾回收(32位=4字節)    void *ptr;//指向底層實際的數據存儲結構,如:SDS等(8字節)} robj; lru 屬性是創建對象的時候寫入,對象被訪問到時也會進行更新。正常人的思路就是最後決定要不要刪除某一個鍵肯定是用當前時間戳減去 lru,差值最大的就優先被刪除。但是 Redis 裏面並不是這麼做的,Redis 中維護了一個全局屬性 lru_clock,這個屬性是通過一個全局函數 serverCron 每隔 100 毫秒執行一次來更新的,記錄的是當前 unix 時間戳。 最後決定刪除的數據是通過 lru_clock 減去對象的 lru 屬性而得出的。那麼為什麼 Redis 要這麼做呢?直接取全局時間不是更準確嗎? 這是因為這麼做可以避免每次更新對象的 lru 屬性的時候可以直接取全局屬性,而不需要去調用系統函數來獲取系統時間,從而提升效率(Redis 當中有很多這種細節考慮來提升性能,可以説是對性能儘可能的優化到極致)。 不過這裏還有一個問題,我們看到,redisObject 對象中的 lru 屬性只有 24 位,24 位只能存儲 194 天的時間戳大小,一旦超過 194 天之後就會重新從 0 開始計算,所以這時候就可能會出現 redisObject 對象中的 lru 屬性大於全局的 lru_clock 屬性的情況。 正因為如此,所以計算的時候也需要分為 2 種情況: 當全局  lruclock >  lru,則使用  lruclock -  lru 得到空閒時間。 當全局  lruclock   now 時,默認為過了一個週期( 16 位,最大  65535),則取差值  65535-ldt+now:當  lru 

    時間:2021-03-11 關鍵詞: Redis 內存 服務器

  • 全球內存價格暴漲,國產芯片能否實現彎道超車?

    全球內存價格暴漲,國產芯片能否實現彎道超車?

    長期以來,中國在芯片市場缺少話語權和定價權,這導致國內一直被海外國際大廠壟斷。雖然我國已經在盡力追趕,但技術上仍然與國際大廠有不小的差距。 國內4px集運由於仍處於起步階段,存儲器的研發能否成功,未來幾年將是關鍵期;研發成功後,良率能否提升到較高水平,成本控制是否能夠達到預期,知識產權能否做到有效保護等,仍然有一定的不確定性;從研發成功至量產並形成銷售,仍然需要長達幾年時間。 存儲器是半導體行業的重要分支,在經歷了2015和2016年的持續走低後,2017年,全球存儲器市場迎來了爆發,增長率達到60%,銷售額超過1200億美元,佔全球半導體市場總值的30.1%。 20年下半年以來,全球汽車行業遭到芯片短缺的嚴重影響,不少一二線車企的部分工廠都已經因為“無芯可用”而被迫停工停產。 令人意想不到的是,汽車行業的缺芯現象已經逐漸蔓延至智能手機行業以及遊戲機行業。全球芯片短缺的狀況在2021年或將持續存在。 從去年底開始,DRAM內存市場價格下滑趨勢已經止住了,在停電、火災等意外因素影響下開始漲價,2021年全球內存漲價已經是定局。截止2月3日,8GB DDR4內存顆粒的報價來到3.93美元。要知道,在2020年8月,相關產品的報價僅為2.54美元。這短短六個月的時間,價格漲幅就達到54.7%。威剛DDR4-3200 16GB單條,去年11月是399元,截稿前已經漲到了569元。實際上,按照華邦電子的説法,DRAM和閃存價格的上揚將有助於公司在3、4月份實現營收增長。 內存接口芯片集成於DRAM內存模組(存儲介質)中,是服務器內存模組的核心邏輯器件,其主要作用是提升內存數據訪問的速度和穩定性,以匹配CPU日益提高的運行速度和性能。內存接口芯片具有較高的技術門檻,認證過程嚴格,尤以CPU4px集運認證最為關鍵,按功能劃分,內存接口芯片主要分為:寄存緩衝器(RCD)、數據緩衝器(DB)、內存緩衝器(MB/AMB)三類。 DDR是21世紀初主流內存規範,內存接口芯片技術經歷了DDR2、DDR3、DDR4世代,目前DDR4內存技術處於成熟期,隨着內存接口芯片的不斷升級,內存技術逐漸由DDR4向DDR5升級迭代,相比於前一代內存接口芯片,DDR5可以支持更低電壓工作環境及更高的運行速率。 其實,全球半導體目前正經歷着大缺貨,雪上加霜的是,美國得州遭遇重大自然災害,日本福島發生7.3級地震,導致部分半導體4px集運暫時停產,比如三星的S2晶圓廠。 由於市場供不應求、供需狀況得到控制,再加上智能手機、服務器市場的迅速增長,2020年的內存行業還是十分賺錢的內存行業的寡頭現象也是越來越明顯,前五大4px集運拿走了81%毛利潤,前十大4px集運則佔了總收入的92%。但這對於國產芯片而言,卻是一個不可多得的機遇。 在全球內存版圖中,三星、SK海力士及美光是三大巨頭,合計佔據全球95%以上的產能,其他4px集運的份額非常小,後來的競爭者面臨着強大的壓力。 相比三星等4px集運進軍第三代、第四代10nm級內存工藝(1Znm之後),國產內存的19nm工藝還是第一代的,好在合肥長鑫之前已經表態會攻克17nm工藝,達到第二代10nm級工藝的水平,同時還會推出DDR5、LPDDR5等新標準內存。 以內存芯片為例。時至今日,三星等頭部4px集運已經在進軍第三代、第四代(10nm級別)內存工藝。反觀國產內存芯片的工藝依然停留在19nm,而且還是第一代。 對國產4px集運來説,2021年內存漲價是個極好的機遇,但面臨的挑戰也不少,主要來自於技術及產能上的。近年來,中國芯片產業的崛起之勢全球有目共睹。由於美國芯片出口的規則改變,全球芯片出口格局也在發生重大變化。為此,中國也在加快步伐,試圖儘快實現芯片國產化,其中最為典型的就是中科院,該院上週已經宣佈,要將光刻機等關鍵設備列入科研清單。最後也希望屬於我們自己的光刻機早日可以研發出來,製造出屬於我們自己的核心芯片,不再受外國力量的制裁和牽制。

    時間:2021-02-26 關鍵詞: 國產芯片 內存

  • 美光發佈面向汽車安全應用的低功耗內存

    美光發佈面向汽車安全應用的低功耗內存

    2021 年 2 月 25 日,中國上海 — 內存與存儲解決方案領先供應商Micron Technology Inc.(美光科技股份有限公司)今日宣佈,已開始出樣業內首款車用低功耗 DDR5 DRAM (LPDDR5) 內存。該款內存經過硬件評估,滿足最高級別的汽車安全完整性等級 (ASIL) 標準,即 ASIL D。此外,美光還有一系列符合國際標準化組織 (ISO) 26262 標準、面向汽車安全的內存和存儲新品。 該款 LPDDR5 DRAM 已通過功能安全評估,可用於高級駕駛輔助系統 (ADAS) 技術,包括自適應巡航控制系統、自動緊急剎車系統、車道偏離警告系統以及盲區偵測系統。它同時具備高性能、低功耗和低延遲特性,為滿足日益增長的下一代汽車系統帶寬需求提供了性能保障和發展空間。 美光嵌入式產品事業部企業副總裁兼總經理 Kris Baxter 表示:“自動駕駛能讓我們的道路更加安全,但自動駕駛技術需要倚賴功能強大且可靠的內存,才能在極端環境下實時做出決策。為了滿足不斷增長的市場需求,我們優化了車用 LPDDR5,為未來的智能安全汽車提供優異的性能、質量和可靠性。” 隨着電子元件成為保障行車安全的必要零部件,汽車製造商必須遵循嚴格的功能安全標準,確保安全機制能夠在汽車發生故障時減輕風險。美光深諳功能安全與日俱增的重要意義,在公司內設立專項部門,根據汽車安全系統設計的內存要求與客户進行緊密協作。為了幫助客户履行復雜的合規義務,該部門在美光內部主導了 LPDDR5 上市,隨附安全應用説明,併發布了行業首份由供應商提供的 DRAM 硬件評估報告。美光的硬件評估報告還由汽車安全領域的知名專業公司 exida 進行了獨立評估和驗證。通過在公司內部進行此項嚴格評估,美光旨在幫助汽車領域的客户簡化系統設計,加快其產品上市。 exida 首席運營官兼首席安全專家 Alexander Griessing 表示:“功能安全是先進汽車系統開發過程中至關重要的一環,但到目前為止,內存在某種程度上受到了忽視,只被當作一種即買即用的商品。美光推出了領先業界的車用 LPDDR5,精準符合 ISO 26262 標準,為內存行業樹立了新的標杆。提升對功能安全的關注將惠及各方,包括汽車製造商和需要先進、安全車輛的消費者。” 美光低功耗內存推動汽車創新和綠色出行 隨着 ADAS 和自動駕駛技術應用的日益普及,數據採集和高效處理能力正逐漸成為汽車創新的關鍵所在。Gartner預測汽車內存的市場規模將在 2020 年 24 億美元的基礎上翻番,成長至 2024 年的 63 億美元。伴隨數據密集型汽車技術的崛起,如今配備 ADAS 的車輛運行超過 1 億行代碼,每秒需進行高達數百萬億次的數據處理,可匹敵數據中心。LPDDR5 能將數據訪問速度提高 50%,將能效提升 20% 以上,從而有效應對這些需求。這使智能汽車能夠近乎實時地處理和決策來自多個傳感器和數據源的數據,例如雷達、激光雷達、高分辨率成像、5G 網絡和光學圖像識別等。 LPDDR5 的高能效可助力實現汽車的高性能計算,同時大幅降低電動汽車和傳統汽車的能耗,從而實現更加環保的交通出行,減少尾氣排放。美光的車用 LPDDR5 還加強了穩固性,可應用於極端温度範圍,符合多種汽車可靠性標準,包括美國汽車電子協會的 AEC-Q100 規範和國際汽車工作組的 IATF 16949 標準。 通過功能安全評估的獨特 DRAM,加快智能安全汽車上市 美光 LPDDR5 附帶詳細的功能安全説明文件,可在系統配置期間幫助客户開展全面的安全分析。美光提供硬件評估報告,嚴格依照 ISO 26262 標準,對廣泛的功能安全分析進行了核驗。為了滿足更高的安全要求,LPDDR5 包含穩健的安全機制,可在運行期間檢測和控制內存錯誤,系統集成商還可選擇部署更多機制,從而進一步降低風險。 憑藉高質量內存和存儲解決方案,美光服務汽車市場 30 年,廣受領先汽車製造商的青睞,累計行駛里程達萬億英里 [5] 。 美光深厚的專業知識源自與汽車領域客户的緊密協作,共同將內存設計集成到系統架構中,為 ADAS、車載信息娛樂系統、數字化座艙和機器學習提供支持。美光是汽車行業排名首位的內存供應商。

    時間:2021-02-25 關鍵詞: 低功耗 美光 內存

  • 美光發佈1α DRAM 製程技術,引領DRAM技術革新

    美光發佈1α DRAM 製程技術,引領DRAM技術革新

    內存和存儲領域仍將保持高速增長勢頭 據Sumit分享,目前已經有多個成長動能因素交織在一起:汽車業需求逐步反彈,5G手機數量今年將實現翻倍增長,疫情帶來的線上業務增多同樣也發揮巨大推動作用。旺盛的內存和存儲市場需求對於製造商的生產能力也提出了更高的要求,而這一部分的壓力主要是集中在DRAM這邊。據Sumit先生觀察,在當前第一季度已經可以看到某些DRAM產品的價格有所上漲,並且隨着全球經濟復甦這種供給緊俏的現象還會持續下去。而在NAND端目前雖然市場供應充足,隨着價格浮動市場會自行進行調節,在年底有望達到產能穩定。 在此次媒體會上,美光發佈了其最新的1α DRAM 製程技術,這代表着業界DRAM技術的最高水平。對於美光上一代1z DRAM 製程,1α 技術將內存密度提升了 40%。採用該製程技術的LPDDR5產品將在實現更高性能同時達到更好的功耗表現,為一共行業提供15%節能的DRAM平台,幫助5G手機實現更長續航表現。1α 工藝製程提供了從8Gb~16Gb的密度,DDR4和LPDDR4產品也可以使用該新工藝來生產。所以針對有着存量市場的客户而言,可以採用更低成本實現系統性能提升,例如數據中心等。 從美光科技最新公佈的財報信息來看,在截至去年12月3日的2021財年第一財季,美光科技營收較上一財年同期增12.23%。而隨着2021年全球經濟復甦、5G手機普及以及中國雙循環和新基建的開啓,美光在2021年的有着強勁的增長機會。在2021年作為NAND和DRAM技術先驅者的美光又將給我們帶來哪些突破性的技術革新,讓我們拭目以待。

    時間:2021-02-02 關鍵詞: DRAM 美光 內存

  • 弄懂這些指針基礎知識,再遇C指針咱就不慌了

    一、前言 二、變量與指針的本質 三、指針的幾個相關概念 四、指向不同數據類型的指針 五、總結 一、前言 如果問C語言中最重要、威力最大的概念是什麼,答案必將是指針!威力大,意味着使用方便、高效,同時也意味着語法複雜、容易出錯。指針用的好,可以極大的提高代碼執行效率、節約系統資源;如果用的不好,程序中將會充滿陷阱、漏洞。 這篇文章,我們就來聊聊指針。從最底層的內存存儲空間開始,一直到應用層的各種指針使用技巧,循序漸進、抽絲剝繭,以最直白的語言進行講解,讓你一次看過癮。 説明:為了方便講解和理解,文中配圖的內存空間的地址是隨便寫的,在實際計算機中是要遵循地址對齊方式的。 二、變量與指針的本質 1. 內存地址 我們編寫一個程序源文件之後,編譯得到的二進制可執行文件存放在電腦的硬盤上,此時它是一個靜態的文件,一般稱之為程序。 當這個程序被啓動的時候,操作系統將會做下面幾件事情: 把程序的內容(代碼段、數據段)從硬盤複製到內存中; 創建一個數據結構PCB(進程控制塊),來描述這個程序的各種信息(例如:使用的資源,打開的文件描述符...); 在代碼段中定位到入口函數的地址,讓CPU從這個地址開始執行。 當程序開始被執行時,就變成一個動態的狀態,一般稱之為進程。 內存分為:物理內存和虛擬內存。操作系統對物理內存進行管理、包裝,我們開發者面對的是操作系統提供的虛擬內存。 這2個概念不妨礙文章的理解,因此就統一稱之為內存。 在我們的程序中,通過一個變量名來定義變量、使用變量。變量本身是一個確確實實存在的東西,變量名是一個抽象的概念,用來代表這個變量。就比如:我是一個實實在在的人,是客觀存在與這個地球上的,道哥是我給自己起的一個名字,這個名字是任意取得,只要自己覺得好聽就行,如果我願意還可以起名叫:鳥哥、龍哥等等。 那麼,我們定義一個變量之後,這個變量放在哪裏呢?那就是內存的數據區。內存是一個很大的存儲區域,被操作系統劃分為一個一個的小空間,操作系統通過地址來管理內存。 內存中的最小存儲單位是字節(8個bit),一個內存的完整空間就是由這一個一個的字節連續組成的。在上圖中,每一個小格子代表一個字節,但是好像大家在書籍中沒有這麼來畫內存模型的,更常見的是下面這樣的畫法: 也就是把連續的4個字節的空間畫在一起,這樣就便於表述和理解,特別是深入到代碼對齊相關知識時更容易理解。(我認為根本原因應該是:大家都這麼畫,已經看順眼了~~) 2. 32位與64位系統 我們平時所説的計算機是32位、64位,指的是計算機的CPU中寄存器的最大存儲長度,如果寄存器中最大存儲32bit的數據,就稱之為32位系統。 在計算機中,數據一般都是在硬盤、內存和寄存器之間進行來回存取。CPU通過3種總線把各組成部分聯繫在一起:地址總線、數據總線和控制總線。地址總線的寬度決定了CPU的尋址能力,也就是CPU能達到的最大地址範圍。 剛才説了,內存是通過地址來管理的,那麼CPU想從內存中的某個地址空間上存取一個數據,那麼CPU就需要在地址總線上輸出這個存儲單元的地址。假如地址總線的寬度是8位,能表示的最大地址空間就是256個字節,能找到內存中最大的存儲單元是255這個格子(從0開始)。即使內存條的實際空間是2G字節,CPU也沒法使用後面的內存地址空間。如果地址總線的寬度是32位,那麼能表示的最大地址就是2的32次方,也就是4G字節的空間。 【4px集運】:這裏只是描述地址總線的概念,實際的計算機中地址計算方式要複雜的多,比如:虛擬內存中採用分段、分頁、偏移量來定位實際的物理內存,在分頁中還有大頁、小頁之分,感興趣的同學可以自己查一下相關資料。 3. 變量 我們在C程序中使用變量來“代表”一個數據,使用函數名來“代表”一個函數,變量名和函數名是程序員使用的助記符。變量和函數最終是要放到內存中才能被CPU使用的,而內存中所有的信息(代碼和數據)都是以二進制的形式來存儲的,計算機根據就不會從格式上來區分哪些是代碼、哪些是數據。CPU在訪問內存的時候需要的是地址,而不是變量名、函數名。 問題來了:在程序代碼中使用變量名來指代變量,而變量在內存中是根據地址來存放的,這二者之間如何映射(關聯)起來的? 答案是:編譯器!編譯器在編譯文本格式的C程序文件時,會根據目標運行平台(就是編譯出的二進制程序運行在哪裏?是x86平台的電腦?還是ARM平台的開發板?)來安排程序中的各種地址,例如:加載到內存中的地址、代碼段的入口地址等等,同時編譯器也會把程序中的所有變量名,轉成該變量在內存中的存儲地址。 變量有2個重要屬性:變量的類型和變量的值。 示例:代碼中定義了一個變量 int a = 20; 類型是int型,值是20。這個變量在內存中的存儲模型為: 我們在代碼中使用變量名a,在程序執行的時候就表示使用0x11223344地址所對應的那個存儲單元中的數據。因此,可以理解為變量名a就等價於這個地址0x11223344。換句話説,如果我們可以提前知道編譯器把變量a安排在地址0x11223344這個單元格中,我們就可以在程序中直接用這個地址值來操作這個變量。 在上圖中,變量a的值為20,在內存中佔據了4個格子的空間,也就是4個字節。為什麼是4個字節呢?在C標準中並沒有規定每種數據類型的變量一定要佔用幾個字節,這是與具體的機器、編譯器有關。 比如:32位的編譯器中: char: 1個字節; short int: 2個字節; int: 4個字節; long: 4個字節。 比如:64位的編譯器中: char: 1個字節; short int: 2個字節; int: 4個字節; long: 8個字節。 為了方便描述,下面都以32位為例,也就是int型變量在內存中佔據4個字節。 另外,0x11223344,0x11223345,0x11223346,0x11223347這連續的、從低地址到高地址的4個字節用來存儲變量a的數值20。在圖示中,使用十六進制來表示,十進制數值20轉成16進制就是:0x00000014,所以從開始地址依次存放0x00、0x00、0x00、0x14這4個字節(存儲順序涉及到大小端的問題,不影響文本理解)。 根據這個圖示,如果在程序中想知道變量a存儲在內存中的什麼位置,可以使用取地址操作符&,如下: printf("&a = 0x%x \n", &a); 這句話將會打印出:&a = 0x11223344。 考慮一下,在32位系統中:指針變量佔用幾個字節? 4. 指針變量 指針變量可以分2個層次來理解: 指針變量首先是一個變量,所以它擁有變量的所有屬性:類型和值。它的類型就是指針,它的值是其他變量的地址。 既然是一個變量,那麼在內存中就需要為這個變量分配一個存儲空間。在這個存儲空間中,存放着其他變量的地址。 指針變量所指向的數據類型,這是在定義指針變量的時候就確定的。例如:int *p; 意味着指針指向的是一個int型的數據。 首先回答一下剛才那個問題,在32位系統中,一個指針變量在內存中佔據4個字節的空間。因為CPU對內存空間尋址時,使用的是32位地址空間(4個字節),也就是用4個字節就能存儲一個內存單元的地址。而指針變量中的值存儲的就是地址,所以需要4個字節的空間來存儲一個指針變量的值。 示例: int a = 20; int *pa; pa = &a; printf("value = %d \n", *pa); 在內存中的存儲模型如下: 對於指針變量pa來説,首先它是一個變量,因此在內存中需要有一個空間來存儲這個變量,這個空間的地址就是0x11223348; 其次,這個內存空間中存儲的內容是變量a的地址,而a的地址為0x11223344,所以指針變量pa的地址空間中,就存儲了0x11223344這個值。 這裏對兩個操作符&和*進行説明: &:取地址操作符,用來獲取一個變量的地址。上面代碼中&a就是用來獲取變量a在內存中的存儲地址,也就是0x11223344。 *:這個操作符用在2個場景中:定義一個指針的時候,獲取一個指針所指向的變量值的時候。 int pa; 這個語句中的表示定義的變量pa是一個指針,前面的int表示pa這個指針指向的是一個int類型的變量。不過此時我們沒有給pa進行賦值,也就是説此刻pa對應的存儲單元中的4個字節裏的值是沒有初始化的,可能是0x00000000,也可能是其他任意的數字,不確定; printf語句中的*表示獲取pa指向的那個int類型變量的值,學名叫解引用,我們只要記住是獲取指向的變量的值就可以了。 5. 操作指針變量 對指針變量的操作包括3個方面: 操作指針變量自身的值; 獲取指針變量所指向的數據; 以什麼樣數據類型來使用/解釋指針變量所指向的內容。 5.1 指針變量自身的值 int a = 20;這個語句是定義變量a,在隨後的代碼中,只要寫下a就表示要操作變量a中存儲的值,操作有兩種:讀和寫。 printf("a = %d \n", a);這個語句就是要讀取變量a中的值,當然是20; a = 100;這個語句就是要把一個數值100寫入到變量a中。 同樣的道理,int *pa;語句是用來定義指針變量pa,在隨後的代碼中,只要寫下pa就表示要操作變量pa中的值: printf("pa = %d \n", pa);這個語句就是要讀取指針變量pa中的值,當然是0x11223344; pa = &a;這個語句就是要把新的值寫入到指針變量pa中。再次強調一下,指針變量中存儲的是地址,如果我們可以提前知道變量a的地址是 0x11223344,那麼我們也可以這樣來賦值:pa = 0x11223344; 思考一下,如果執行這個語句printf("&pa =0x%x \n", &pa);,打印結果會是什麼? 上面已經説過,操作符&是用來取地址的,那麼&pa就表示獲取指針變量pa的地址,上面的內存模型中顯示指針變量pa是存儲在0x11223348這個地址中的,因此打印結果就是:&pa = 0x11223348。 5.2 獲取指針變量所指向的數據 指針變量所指向的數據類型是在定義的時候就明確的,也就是説指針pa指向的數據類型就是int型,因此在執行printf("value = %d \n", *pa);語句時,首先知道pa是一個指針,其中存儲了一個地址(0x11223344),然後通過操作符*來獲取這個地址(0x11223344)對應的那個存儲空間中的值;又因為在定義pa時,已經指定了它指向的值是一個int型,所以我們就知道了地址0x11223344中存儲的就是一個int類型的數據。 5.3 以什麼樣的數據類型來使用/解釋指針變量所指向的內容 如下代碼: int a = 30000; int *pa = &a; printf("value = %d \n", *pa); 根據以上的描述,我們知道printf的打印結果會是value = 30000,十進制的30000轉成十六進制是0x00007530,內存模型如下: 現在我們做這樣一個測試: char *pc = 0x11223344; printf("value = %d \n", *pc); 指針變量pc在定義的時候指明:它指向的數據類型是char型,pc變量中存儲的地址是0x11223344。當使用*pc獲取指向的數據時,將會按照char型格式來讀取0x11223344地址處的數據,因此將會打印value = 0(在計算機中,ASCII碼是用等價的數字來存儲的)。 這個例子中説明了一個重要的概念:在內存中一切都是數字,如何來操作(解釋)一個內存地址中的數據,完全是由我們的代碼來告訴編譯器的。剛才這個例子中,雖然0x11223344這個地址開始的4個字節的空間中,存儲的是整型變量a的值,但是我們讓pc指針按照char型數據來使用/解釋這個地址處的內容,這是完全合法的。 以上內容,就是指針最根本的心法了。把這個心法整明白了,剩下的就是多見識、多練習的問題了。 三、指針的幾個相關概念 1. const屬性 const標識符用來表示一個對象的不可變的性質,例如定義: const int b = 20; 在後面的代碼中就不能改變變量b的值了,b中的值永遠是20。同樣的,如果用const來修飾一個指針變量: int a = 20; int b = 20; int * const p = &a; 內存模型如下: 這裏的const用來修飾指針變量p,根據const的性質可以得出結論:p在定義為變量a的地址之後,就固定了,不能再被改變了,也就是説指針變量pa中就只能存儲變量a的地址0x11223344。如果在後面的代碼中寫p = &b;,編譯時就會報錯,因為p是不可改變的,不能再被設置為變量b的地址。 但是,指針變量p所指向的那個變量a的值是可以改變的,即:*p = 21;這個語句是合法的,因為指針p的值沒有改變(仍然是變量c的地址0x11223344),改變的是變量c中存儲的值。 與下面的代碼區分一下: int a = 20; int b = 20; const int *p = &a; p = &b; 這裏的const沒有放在p的旁邊,而是放在了類型int的旁邊,這就説明const符號不是用來修飾p的,而是用來修飾p所指向的那個變量的。所以,如果我們寫p = &b;把變量b的地址賦值給指針p,就是合法的,因為p的值可以被改變。 但是這個語句*p = 21就是非法了,因為定義語句中的const就限制了通過指針p獲取的數據,不能被改變,只能被用來讀取。這個性質常常被用在函數參數上,例如下面的代碼,用來計算一塊數據的CRC校驗,這個函數只需要讀取原始數據,不需要(也不可以)改變原始數據,因此就需要在形參指針上使用const修飾符: short int getDataCRC(const char *pData, int len) { short int crc = 0x0000; // 計算CRC return crc; } 2. void型指針 關鍵字void並不是一個真正的數據類型,它體現的是一種抽象,指明不是任何一種類型,一般有2種使用場景: 函數的返回值和形參; 定義指針時不明確規定所指數據的類型,也就意味着可以指向任意類型。 指針變量也是一種變量,變量之間可以相互賦值,那麼指針變量之間也可以相互賦值,例如: int a = 20; int b = a; int *p1 = &a; int *p2 = p1; 變量a賦值給變量b,指針p1賦值給指針p2,注意到它們的類型必須是相同的:a和b都是int型,p1和p2都是指向int型,所以可以相互賦值。那麼如果數據類型不同呢?必須進行強制類型轉換。例如: int a = 20; int *p1 = &a; char *p2 = (char *)p1; 內存模型如下: p1指針指向的是int型數據,現在想把它的值(0x11223344)賦值給p2,但是由於在定義p2指針時規定它指向的數據類型是char型,因此需要把指針p1進行強制類型轉換,也就是把地址0x11223344處的數據按照char型數據來看待,然後才可以賦值給p2指針。 如果我們使用void *p2來定義p2指針,那麼在賦值時就不需要進行強制類型轉換了,例如: int a = 20; int *p1 = &a; void *p2 = p1; 指針p2是void*型,意味着可以把任意類型的指針賦值給p2,但是不能反過來操作,也就是不能把void*型指針直接賦值給其他確定類型的指針,而必須要強制轉換成被賦值指針所指向的數據類型,如下代碼,必須把p2指針強制轉換成int*型之後,再賦值給p3指針: int a = 20; int *p1 = &a; void *p2 = p1; int *p3 = (int *)p2; 我們來看一個系統函數: void* memcpy(void* dest, const void* src, size_t len); 第一個參數類型是void*,這正體現了系統對內存操作的真正意義:它並不關心用户傳來的指針具體指向什麼數據類型,只是把數據挨個存儲到這個地址對應的空間中。 第二個參數同樣如此,此外還添加了const修飾符,這樣就説明了memcpy函數只會從src指針處讀取數據,而不會修改數據。 3. 空指針和野指針 一個指針必須指向一個有意義的地址之後,才可以對指針進行操作。如果指針中存儲的地址值是一個隨機值,或者是一個已經失效的值,此時操作指針就非常危險了,一般把這樣的指針稱作野指針,C代碼中很多指針相關的bug就來源於此。 3.1 空指針:不指向任何東西的指針 在定義一個指針變量之後,如果沒有賦值,那麼這個指針變量中存儲的就是一個隨機值,有可能指向內存中的任何一個地址空間,此時萬萬不可以對這個指針進行寫操作,因為它有可能指向內存中的代碼段區域、也可能指向內存中操作系統所在的區域。 一般會將一個指針變量賦值為NULL來表示一個空指針,而C語言中,NULL實質是 ((void*)0) , 在C++中,NULL實質是0。在標準庫頭文件stdlib.h中,有如下定義: #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif 3.2 野指針:地址已經失效的指針 我們都知道,函數中的局部變量存儲在棧區,通過malloc申請的內存空間位於堆區,如下代碼: int *p = (int *)malloc(4); *p = 20; 內存模型為: 在堆區申請了4個字節的空間,然後強制類型轉換為int*型之後,賦值給指針變量p,然後通過*p設置這個地址中的值為14,這是合法的。如果在釋放了p指針指向的空間之後,再使用*p來操作這段地址,那就是非常危險了,因為這個地址空間可能已經被操作系統分配給其他代碼使用,如果對這個地址裏的數據強行操作,程序立刻崩潰的話,將會是我們最大的幸運! int *p = (int *)malloc(4); *p = 20; free(p); // 在free之後就不可以再操作p指針中的數據了。 p = NULL; // 最好加上這一句。 四、指向不同數據類型的指針 1. 數值型指針 通過上面的介紹,指向數值型變量的指針已經很明白了,需要注意的就是指針所指向的數據類型。 2. 字符串指針 字符串在內存中的表示有2種: 用一個數組來表示,例如:char name1[8] = "zhangsan"; 用一個char *指針來表示,例如:char *name2 = "zhangsan"; name1在內存中佔據8個字節,其中存儲了8個字符的ASCII碼值;name2在內存中佔據9個字節,因為除了存儲8個字符的ASCII碼值,在最後一個字符'n'的後面還額外存儲了一個'\0',用來標識字符串結束。 對於字符串來説,使用指針來操作是非常方便的,例如:變量字符串name2: char *name2 = "zhangsan"; char *p = name2; while (*p != '\0') { printf("%c ", *p); p = p + 1; } 在while的判斷條件中,檢查p指針指向的字符是否為結束符'\0'。在循環體重,打印出當前指向的字符之後,對指針比那裏進行自增操作,因為指針p所指向的數據類型是char,每個char在內存中佔據一個字節,因此指針p在自增1之後,就指向下一個存儲空間。 也可以把循環體中的2條語句寫成1條語句: printf("%c ", *p++); 假如一個指針指向的數據類型為int型,那麼執行p = p + 1;之後,指針p中存儲的地址值將會增加4,因為一個int型數據在內存中佔據4個字節的空間,如下所示: 思考一個問題:void*型指針能夠遞增嗎?如下測試代碼: int a[3] = {1, 2, 3}; void *p = a; printf("1: p = 0x%x \n", p); p = p + 1; printf("2: p = 0x%x \n", p); 打印結果如下: 1: p = 0x733748c0 2: p = 0x733748c1 説明void*型指針在自增時,是按照一個字節的跨度來計算的。 3. 指針數組與數組指針 這2個説法經常會混淆,至少我是如此,先看下這2條語句: int *p1[3]; // 指針數組 int (*p2)[3]; // 數組指針 3.1 指針數組 第1條語句中:中括號[]的優先級高,因此與p1先結合,表示一個數組,這個數組中有3個元素,這3個元素都是指針,它們指向的是int型數據。可以這樣來理解:如果有這個定義char p[3],很容易理解這是一個有3個char型元素的數組,那麼把char換成int*,意味着數組裏的元素類型是int*型(指向int型數據的指針)。內存模型如下(注意:三個指針指向的地址並不一定是連續的): 如果向指針數組中的元素賦值,需要逐個把變量的地址賦值給指針元素: int a = 1, b = 2, c = 3; char *p1[3]; p1[0] = &a; p1[1] = &b; p1[2] = &c; 3.2 數組指針 第2條語句中:小括號讓p2與*結合,表示p2是一個指針,這個指針指向了一個數組,數組中有3個元素,每一個元素的類型是int型。可以這樣來理解:如果有這個定義int p[3],很容易理解這是一個有3個char型元素的數組,那麼把數組名p換成是*p2,也就是p2是一個指針,指向了這個數組。內存模型如下(注意:指針指向的地址是一個數組,其中的3個元素是連續放在內存中的): 在前面我們説到取地址操作符&,用來獲得一個變量的地址。凡事都有特殊情況,對於獲取地址來説,下面幾種情況不需要使用&操作符: 字符串字面量作為右值時,就代表這個字符串在內存中的首地址; 數組名就代表這個數組的地址,也等於這個數組的第一個元素的地址; 函數名就代表這個函數的地址。 因此,對於一下代碼,三個printf語句的打印結果是相同的: int a[3] = {1, 2, 3}; int (*p2)[3] = a; printf("0x%x \n", a); printf("0x%x \n", &a); printf("0x%x \n", p2); 思考一下,如果對這裏的p2指針執行p2 = p2 + 1;操作,p2中的值將會增加多少? 答案是12個字節。因為p2指向的是一個數組,這個數組中包含3個元素,每個元素佔據4個字節,那麼這個數組在內存中一共佔據12個字節,因此p2在加1之後,就跳過12個字節。 4. 二維數組和指針 一維數組在內存中是連續分佈的多個內存單元組成的,而二維數組在內存中也是連續分佈的多個內存單元組成的,從內存角度來看,一維數組和二維數組沒有本質差別。 和一維數組類似,二維數組的數組名錶示二維數組的第一維數組中首元素的首地址,用代碼來説明: int a[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; // 二維數組 int (*p0)[3] = NULL; // p0是一個指針,指向一個數組 int (*p1)[3] = NULL; // p1是一個指針,指向一個數組 int (*p2)[3] = NULL; // p2是一個指針,指向一個數組 p0 = a[0]; p1 = a[1]; p2 = a[2]; printf("0: %d %d %d \n", *(*p0 + 0), *(*p0 + 1), *(*p0 + 2)); printf("1: %d %d %d \n", *(*p1 + 0), *(*p1 + 1), *(*p1 + 2)); printf("2: %d %d %d \n", *(*p2 + 0), *(*p2 + 1), *(*p2 + 2)); 打印結果是: 0: 1 2 3 1: 4 5 6 2: 7 8 9 我們拿第一個printf語句來分析:p0是一個指針,指向一個數組,數組中包含3個元素,每個元素在內存中佔據4個字節。現在我們想獲取這個數組中的數據,如果直接對p0執行加1操作,那麼p0將會跨過12個字節(就等於p1中的值了),因此需要使用解引用操作符*,把p0轉為指向int型的指針,然後再執行加1操作,就可以得到數組中的int型數據了。 5. 結構體指針 C語言中的基本數據類型是預定義的,結構體是用户定義的,在指針的使用上可以進行類比,唯一有區別的就是在結構體指針中,需要使用->箭頭操作符來獲取結構體中的成員變量,例如: typedef struct { int age; char name[8]; } Student; Student s; s.age = 20; strcpy(s.name, "lisi"); Student *p = &s; printf("age = %d, name = %s \n", p->age, p->name); 看起來似乎沒有什麼技術含量,如果是結構體數組呢?例如: Student s[3]; Student *p = &s; printf("size of Student = %d \n", sizeof(Student)); printf("1: 0x%x, 0x%x \n", s, p); p++; printf("2: 0x%x \n", p); 打印結果是: size of Student = 12 1: 0x4c02ac00, 0x4c02ac00 2: 0x4c02ac0c 在執行p++操作後,p需要跨過的空間是一個結構體變量在內存中佔據的大小(12個字節),所以此時p就指向了數組中第2個元素的首地址,內存模型如下: 6. 函數指針 每一個函數在經過編譯之後,都變成一個包含多條指令的集合,在程序被加載到內存之後,這個指令集合被放在代碼區,我們在程序中使用函數名就代表了這個指令集合的開始地址。 函數指針,本質上仍然是一個指針,只不過這個指針變量中存儲的是一個函數的地址。函數最重要特性是什麼?可以被調用!因此,當定義了一個函數指針並把一個函數地址賦值給這個指針時,就可以通過這個函數指針來調用函數。 如下示例代碼: int add(int x,int y) { return x+y; } int main() { int a = 1, b = 2; int (*p)(int, int); p = add; printf("%d + %d = %d\n", a, b, p(a, b)); } 前文已經説過,函數的名字就代表函數的地址,所以函數名add就代表了這個加法函數在內存中的地址。int (*p)(int, int);這條語句就是用來定義一個函數指針,它指向一個函數,這個函數必須符合下面這2點(學名叫:函數簽名): 有2個int型的參數; 有一個int型的返回值。 代碼中的add函數正好滿足這個要求,因此,可以把add賦值給函數指針p,此時p就指向了內存中這個函數存儲的地址,後面就可以用函數指針p來調用這個函數了。 在示例代碼中,函數指針p是直接定義的,那如果想定義2個函數指針,難道需要像下面這樣定義嗎? int (*p)(int, int); int (*p2)(int, int); 這裏的參數比較簡單,如果函數很複雜,這樣的定義方式豈不是要煩死?可以用typedef關鍵字來定義一個函數指針類型: typedef int (*pFunc)(int, int); 然後用這樣的方式pFunc p1, p2;來定義多個函數指針就方便多了。注意:只能把與函數指針類型具有相同簽名的函數賦值給p1和p2,也就是參數的個數、類型要相同,返回值也要相同。 注意:這裏有幾個小細節稍微瞭解一下: 在賦值函數指針時,使用p = &a;也是可以的; 使用函數指針調用時,使用(*p)(a, b);也是可以的。 這裏沒有什麼特殊的原理需要講解,最終都是編譯器幫我們處理了這裏的細節,直接記住即可。 函數指針整明白之後,再和數組結合在一起:函數指針數組。示例代碼如下: int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int divide(int a, int b) { return a / b; } int main() { int a = 4, b = 2; int (*p[4])(int, int); p[0] = add; p[1] = sub; p[2] = mul; p[3] = divide; printf("%d + %d = %d \n", a, b, p[0](a, b)); printf("%d - %d = %d \n", a, b, p[1](a, b)); printf("%d * %d = %d \n", a, b, p[2](a, b)); printf("%d / %d = %d \n", a, b, p[3](a, b)); } 這條語句不太好理解:int (*p[4])(int, int);,先分析中間部分,標識符p與中括號[]結合(優先級高),所以p是一個數組,數組中有4個元素;然後剩下的內容表示一個函數指針,那麼就説明數組中的元素類型是函數指針,也就是其他函數的地址,內存模型如下: 如果還是難以理解,那就回到指針的本質概念上:指針就是一個地址!這個地址中存儲的內容是什麼根本不重要,重要的是你告訴計算機這個內容是什麼。如果你告訴它:這個地址裏存放的內容是一個函數,那麼計算機就去調用這個函數。那麼你是如何告訴計算機的呢,就是在定義指針變量的時候,僅此而已! 五、總結 我已經把自己知道的所有指針相關的概念、語法、使用場景都作了講解,就像一個小酒館的掌櫃,把自己的美酒佳餚都呈現給你,但願你已經酒足飯飽! 如果以上的內容太多,一時無法消化,那麼下面的這兩句話就作為飯後甜點為您奉上,在以後的編程中,如果遇到指針相關的困惑,就想一想這兩句話,也許能讓你茅塞頓開。 指針就是地址,地址就是指針。 指針就是指向內存中的一塊空間,至於如何來解釋/操作這塊空間,由這個指針的類型來決定。 另外還有一點囑咐,那就是學習任何一門編程語言,一定要弄清楚內存模型,內存模型,內存模型! 祝您好運! 免責聲明:本文內容由21ic獲得授權後發佈,版權歸原作者所有,本平台僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平台立場,如有問題,請聯繫我們,謝謝!

    時間:2021-01-30 關鍵詞: 指針 C語言 內存

  • 美光率先於業界推出1α DRAM製程技術

    2021年1月27日,中國上海——內存與存儲解決方案領先供應商Micron Technology Inc.(美光科技股份有限公司)今日宣佈批量出貨基於1α(1-alpha)節點的DRAM產品。該製程是目前世界上最為先進的DRAM技術,在密度、功耗和性能等各方面均有重大突破。這是繼最近首推全球最快顯存和176層NAND產品後,美光實現的又一突破性里程碑,進一步加強了公司在業界的競爭力。 美光技術與產品執行副總裁Scott DeBoer先生表示:“1α節點印證了美光在DRAM領域的領先成就,同時也是我們對前沿設計和技術不懈追求的成果。對比我們上一代的1z DRAM製程,1α技術將內存密度提升了40%,為將來的產品和內存創新提供了堅實的基礎。” 美光計劃於今年將1α節點全面導入其DRAM產品線,從而更好地支持廣泛的DRAM應用領域——為包括移動設備和智能車輛在內的各種應用提供更強的性能。 美光繼續領跑多個內存應用市場 美光執行副總裁兼首席商務官Sumit Sadana先生表示:“我們全新的1α技術將為手機行業帶來最低功耗的DRAM,同時也使美光於數據中心、客户端、消費領域、工業和汽車領域的DRAM客户受益匪淺。內存和存儲預計是未來十年增長最快的半導體市場,美光憑藉領先業界的DRAM和NAND技術,將在這個快速增長的市場中立於不敗之地。” 美光的1α技術節點使內存解決方案更節能、更可靠,併為需要最佳低功耗DRAM產品的移動平台帶來運行速度更快的LPDDR5。美光為移動行業提供最低功耗的DRAM平台,實現了15%的節能,使5G用户在不犧牲續航的同時能在手機上進行更多任務操作。 美光的1α先進內存節點提供8Gb至16Gb的密度,將助力美光現有的DDR4和LPDDR4系列產品延長生命週期,並能為美光在服務器、客户端、網絡和嵌入式領域的客户提供更低功耗、更可靠的產品及更全面的產品支持,從而降低客户再次驗證的成本。對於具備較長產品生命週期的汽車嵌入式解決方案、工業PC和邊緣服務器等應用場景而言,1α製程同樣保證了在整個系統生命週期內更具優勢的總體擁有成本。 供應情況 美光位於台灣地區的工廠已開始批量生產1α節點DRAM,首先出貨的是面向運算市場的DDR4內存以及英睿達(Crucial)消費級PC DRAM產品。美光同時也已開始向移動客户提供LPDDR4樣片進行驗證。公司將在2021自然年內推出基於該技術的更多新產品。

    時間:2021-01-27 關鍵詞: DRAM 美光 內存

  • 一個產品級MCU內存管理方案

    前面已經將所有的硬件驅動實現,驗證了硬件功能。但是每一個硬件都是單獨測試的,而且並不完善。下一步,我們需要對各個驅動進行整合完善。在整合之前,需要做一些基礎工作。其中之一就是實現內存管理。什麼叫內存管理呢?為什麼要做內存管理?前面我們已經大概瞭解了程序中的變量現在我們複習一下:局部變量、全局變量。 局部變量在進入函數時從棧空間分配,退出函數前釋放。全局變量則在整個程序運行其中一直使用。在程序編譯時就已經分配了RAM空間。 那還有沒有第三種變量呢?可以説沒有。但是如果從生存週期上看,是有的:一個變量,在多個函數內使用,但是又不是整個程序運行期間都使用。或:一個變量,在一段時間內使用,不是整個程序運行生命週期都要用,但是用這個變量的函數會退出,然後重複進入(用static定義的局部變量相當於全局變量) 如果不使用動態內存管理,這樣的變量就只能定義為全局變量。如果將這些變量定義為指針,當要使用時,通過內存管理分配,使用完後就釋放,這就叫做動態分配。舉個實際的例子: 一個設備,有三種通信方式:串口,USB,網絡,在通信過程每個通信方式需要1K RAM。經過分析,3種通信方式不會同時使用。那麼,如果不使用動態內存,則需要3K變量。如果使用內存管理動態分配,則只需要1K內存就可以了。(這個只是舉例,如果簡單的系統,確定三種方式不同時使用,可以直接複用內存) 通信方式只是舉例,其實一個系統中,並不是所有設備都一直使用,如果使用動態內存管理,RAM的峯值用量將會大大減少。 內存管理方案 不發明車輪,只優化輪胎。 內存管理是編程界的一個大話題,有很多經典的方案。很多人也在嘗試寫新的方案。內存分配模塊我們使用K&R C examples作為基礎,然後進行優化。K&R是誰?就是寫《C程序設計語言》的兩個傢伙。如果你沒有這本書,真遺憾。這本書的8.7章節,<實例--存儲分配程序>,介紹了一種基本的存儲分配方法。代碼見alloc.c,整個代碼只有120行,而且結構很美。 K&R 內存管理方案分析 下面我們結合代碼分析這種內存分配方案。代碼在wujique\Utilities\alloc文件夾。 內存分析 初始化 在malloc函數中,如果是第一次調用就會初始化內存鏈表。代碼原來是通過獲取堆地址,在堆上建立內存池。我們把他改為更直觀的數組定義方式。內存建立後的內存視圖如下: 內存分配的最小單元是: typedef struct ALLOC_HDR {  struct {    struct ALLOC_HDR *ptr;    unsigned int size;/*本塊內存容量*/ } s;  unsigned int align;  unsigned int pad; } ALLOC_HDR; 這也就是內存管理結構體。在32位ARM系統上,這個結構體是16字節。 第一次分配 每次分配,就是在一塊可以分配的空間尾部切割一塊出來,切割的大小是16字節的倍數,而且會比需要的內存多一塊頭。這塊頭在內存釋放時需要使用。這一塊,也就是內存管理的開銷。 分配釋放後 經過多次分配釋放後,內存可能如下圖,綠色是兩塊不連續的空閒塊,黃色是分配出去的塊。分配出去的塊,已經不在內存鏈表裏面。 缺點 一般情況上面的代碼已經能滿足需求。但是,有以下缺陷: 缺點1:容易碎片化 分配使用首次適應法,也即是找到一塊大於等於要分配內存的空閒塊,立刻進行分配。這種方法的優點是速度較快,缺點是容易內存碎片化,分配時將很多大塊內存切割成小內存了。經過多次分配後,很可能出現以下情況: 空閒內存總量還有10K,但是卻被分散在10個塊內,而且沒有大容量的內存塊,再申請2K內存就出現失敗。如果對時間並不是那麼敏感,我們可以使用最適合法,也即是遍歷空閒鏈表,查找一個最合適的內存(大於要分配內存且容量最小的空閒塊),減少大內存被切碎的概率。需要注意的是,最適合法,除了會增加分配時間,不會減少內存碎片數量,只是增加了空閒內存的集中度。假設經過多次分配後,空閒總量還是10K,也是分散在10個空閒塊,但是在這10個空閒塊中,會有5K的大塊,再申請2K的時候,就可以申請到2K內存了。 缺點2:內存消耗 內存分配方案使用了一個結構體,每次分配的最小單位就是這個結構體的大小16字節。 typedef struct ALLOC_HDR {  struct {    struct ALLOC_HDR *ptr;    unsigned int size;/*本塊內存容量*/ } s;  unsigned int align;  unsigned int pad; } ALLOC_HDR; 一次分配,最少就是2個結構體(一個結構體用於管理分配出去的內存,其餘結構體做為申請內存),也就是32字節。如果代碼有大量小內存申請,例如申請100次8個字節 需求內存:100X8=800字節實際消耗內存100X32 = 3200字節利用率只有800/3200 =25% 如果內存分配只有25%的使用率,對於小內存嵌入式設備來説,是致命的方案缺陷。 如何解決呢?我們可以參考LINUX內存分配方案SLAB。在LINUX中,有很多模塊需要申請固定大小的內存(例如node結構體),為了加快分配速度,系統會使用malloc先從大內存池中申請一批node結構體大小的內存,作為一個slab內存池。當需要分配node結構體時,就直接從slab內存池申請。同理,可以將內存分配優化為:需要小內存時,從大塊內存池分配一塊大內存,例如512,使用新算法管理,用於小內存分配。當512消耗盡,再從大內存池申請第二塊512字節大內存。當小內存釋放時,判斷小塊內存池是否為空,如為空,將小塊內存池釋放回大內存池。那如何管理這個小內存池呢? 缺點3:沒有管理已分配內存 內存分配沒有將已分配內存管理起來。我們可以對已分配內存進行統一管理: 1 已分配內存在頭部有原來的結構體,通過ptr指針,將所有已分配內存連接在已分配鏈表上。2 利用不使用的align跟pad成員,記錄分配時間跟分配對象(記錄哪個驅動申請的內存) 通過上面優化後,就可以統計已經分配了多少內存,還有多少空閒內存,哪個模塊申請了最多內存等數據。 使用 1 將代碼中的所有free改為為wjq_free,malloc改為wjq_malloc。 串口緩衝用了free跟malloc.fatfs的syscall.c 用了lwip的mem.h用了。 2 修改啓動代碼, 棧跟堆改小。不用庫的malloc,堆可以完全不要。棧,還是要保留,但是不需要那麼大,如果函數內用到比較大的局部變量,改為動態申請。 Stack_Size      EQU     0x00002000 AREA    STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem       SPACE   Stack_Size __initial_sp ;Heap Configuration ;Heap Size (in Bytes);Heap_Size       EQU     0x00000010        AREA    HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem        SPACE   Heap_Size __heap_limit 3 內存池開了80K,編譯不過 linking... .\Objects\wujique.axf: Error: L6406E: No space in execution regions with .ANY selector matching dev_touchscreen.o(.bss). .\Objects\wujique.axf: Error: L6406E: No space in execution regions with .ANY selector matching mcu_uart.o(.bss). .\Objects\wujique.axf: Error: L6406E: No space in execution regions with .ANY selector matching etharp.o(.bss). .\Objects\wujique.axf: Error: L6406E: No space in execution regions with .ANY selector matching mcu_can.o(.bss). .\Objects\wujique.axf: Error: L6406E: No space in execution regions with .ANY selector matching netconf.o(.bss). 先把內存池改小,編譯通過之後,分析 map文件,用了較多全局變量的統統改小或者改為動態申請。分析map文件,還可以檢查還有沒有使用庫裏面的malloc。 Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name    124         32          0          4      40976       1658   alloc.o     16          0          0          0          0       2474   def.o     96         34       8640          4          0       1377   dev_dacsound.o    300         36          0          0          0       2751   dev_esp8266.o    204         38          0          1          0       1446   dev_key.o    436         98          0         10         16       3648   dev_touchkey.o    310         18          0         14       3000       3444   dev_touchscreen.o    932         18          0          4          0      15981   dhcp.o      0          0          0          0       3964       5933   dual_func_demo.o    280         14         12          0        200       5963   etharp.o      0          0          0          0          0      35864   ethernetif.o      0          0          0          0          0       3820   inet.o     98          0          0          0          0       2022   inet_chksum.o      0          0          0          0          0       4163   init.o    168          4          0         20          0       4763   ip.o      0          0          4          0          0       6463   ip_addr.o    386          4          0          0          0       4118   ip_frag.o    264         38          0          8         16     383399   main.o     84          8          0          0          0       1410   mcu_adc.o     60         32          0          1         68       1511   mcu_can.o     12          0          0          0          0        521   mcu_dac.o    128         14          0          0          0       2352   mcu_i2c.o     28          8          0          1          0        630   mcu_i2s.o    336         92          0          0          0       2689   mcu_rtc.o    430         86          0          1          0       4396   mcu_timer.o   1564         82          0          0        328       9072   mcu_uart.o    504         20          0         12          0       4510   mem.o     56         10          0          0       9463       3250   memp.o    120         14          0          0          0       1651   misc.o      0          0          0          0         56       1066   netconf.o    118          0          0          0          0       4267   netif.o    684          0          0          0          0       6971   pbuf.o     36          8        392          0       8192        824   startup_stm32f40_41xxx.o alloc.o 內存池dev_touchscreen.o 觸摸屏緩衝dual_func_demo.o USB,應該能優化memp.o 什麼鬼?又一個內存池?應該是要優化掉startup_stm32f40_41xxx.o 啓動代碼,是棧跟堆用的RAM. 由於編譯器的優化,項目沒用到的代碼沒有編譯進來,上面的map數據並不完整。等後面我們做完全部測試程序,所有用到的代碼都會參與連接,到時還需要優化一次。 總結 內存管理暫時到此,等後面所有功能都完成後,再進行一次優化。如果對內存分配時間有更高要求,可使用夥伴內存分配法。大家可以參考《都江堰操作系統與嵌入式系統設計》,這個文檔裏面的一些軟件設計策略非常好。//www.djyos.com/?page_id=50 免責聲明:本文內容由21ic獲得授權後發佈,版權歸原作者所有,本平台僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平台立場,如有問題,請聯繫我們,謝謝!

    時間:2021-01-23 關鍵詞: MCU 內存

  • 內存隨機也比順序訪問慢,帶你深入理解內存IO過程

    平時大家都知道內存訪問很快,今天來讓我們來思考兩個問題: 問題1: 內存訪問一次延時到底是多少?你是否會進行大概的估算? 例如筆者的內存條的Speed顯示是1066MHz,那是否可以推算出內存IO延時是1s/1066MHz=0.93ns? 這種算法大錯特錯。 問題2: 內存存在隨機IO比順序IO慢的問題嗎?我們都知道磁盤的隨機IO要比順序IO慢的多(操作系統底層還專門實現了電梯調度算法來緩解這個問題),那麼內存的隨機IO會比順序IO慢嗎? 要想徹底弄明白以上兩個問題,我想我們得從內存IO的物理過程中來尋找答案。 1先給你講個圖書管理員的故事 在開始介紹枯燥的內存工作原理之前。我想先給你講一個故事,並帶你去認識一個人,圖書館的管理員。 在我們的這個故事中,你是故事的主角。你有一所房子,房子裏有一個僕人,他每天幫你處理各種各樣的圖書數據。但是北京房價太貴,所以你的這個房子很小,只能放的下64本書。你家的馬路對面,就是北京圖書館(你家房子雖然小但是地段還不錯),你所需要的所有的圖書在那裏都可以找到。圖書館有個管理員,他負責幫你把你想要的書找出來。 圖1 圖書管理員的故事 好接下來,故事開始進行! 場景1: 你發現你需要編號為0的書的計算結果,你的僕人穿過馬路告訴了圖書管理員,告訴他請幫我把第0-63本書取出來。圖書管理員幫你在電腦前查得該書在二樓。於是他,花了點時間坐電梯到了二樓。等到了二樓,他又花了點時間幫你找了出來。然後你的僕人抱着64本書放到了客廳,拿起第0本書幫你處理了起來。 場景2: 你發現你需要編號為1的書的計算結果,告訴你的僕人。你的僕人直接從客廳拿出來就可以處理了,這次你等的時間最短。 場景3: 你發現需要編號為65的書,你又告訴你的僕人。你的僕人穿過馬路又去找了圖書管理員。圖書管理員還在二樓呢,聽説這次需要65-127,這次他不用再花時間找樓層了。只是花時間找書就可以了。你的僕人把65-127的書放到了客廳(以前的0-63就都扔了),並幫你開始處理起65號書來。 場景4: 你發現你需要編號為10000的書,你告訴了你的僕人。你的僕人穿過馬路去圖書館,找到了管理員。這次管理員查得你需要的書是在10樓,他得花點時間坐電梯過去。去了之後,他又得花點時間幫你找出來。 這四個場景裏,我覺得你一定發現了不同情形下耗時的差異。 場景1和場景4花費的時間最多。因為圖書管理員需要花時間坐電梯找樓層,需要花時間在樓內找書。 場景3次之,因為圖書管理員直接就在樓層內,只需要花時間在樓內找書既可 場景2最快,因為只需要僕人幫你從客廳拿過來就好,連馬路都不需要過。 之所以編造這麼一個例子,是因為內存的工作方式和它太像了。接下來我們進入內存的實際分析。 2內存物理結構 在《帶你理解內存對齊最底層原理》中我們瞭解了內存顆粒的物理構造以及IO過程,今天我們再來複習一下。 內存是由chip構成。每個chip內部,是由8個bank組成的。其構造如下圖: 圖2 內存顆粒chip內部結構 而每一個bank是一個二維平面上的矩陣,前面文章中我們説到過。矩陣中每一個元素中都是保存了1個字節,也就是8個bit。 圖3 bank內部物理結構 每當CPU向內存請求數據的時候,內存芯片總是8個bank並行一起工作。每個bank在定位到行地址後,把對應的行copy到row buffer。再根據列地址把對應的元素中的數據取出來,8個bank把數據拼接一下,一個64位寬的數據就可以返回給CPU了。 圖4 一次內存IO的過程示意 根據上面幾張圖我們可以大致瞭解內存的IO過程,在這個過程中每一步操作之間都有一些延遲,讓我們來繼續瞭解這些延遲。 3內存IO延遲 在《從DDR發展到DDR4,內存核心頻率指標其實基本上就沒太大的進步》裏我們提到內存的延遲很大程度是受核心頻率制約的,你也應該記得我們提到了內存延遲一般是通過CL-tRCD-tRP-tRAS四個參數來標識的。我們今天來詳細理解一下這四個參數的含義: CL(Column Address Latency):發送一個列地址到內存與數據開始響應之間的週期數 tRCD(Row Address to Column Address Delay):打開一行內存並訪問其中的列所需的最小時鐘週期數 tRP(Row Precharge Time):發出預充電命令與打開下一行之間所需的最小時鐘週期數。 tRAS(Row Active Time):行活動命令與發出預充電命令之間所需的最小時鐘週期數。也就是對下一次預充電時間進行限制。 要注意除了CL是固定週期數以外,其它的三個都是最小週期。另外上面的參數都是以時鐘週期為單位的。因為現代的內存都是一個時鐘週期上下沿分別各傳輸一次數據,所以用Speed/2就可以得出,例如筆者的機器的Speed是1066MHz,則時鐘週期為533MHz。你自己的機器可以通過dmidecode命令查看: # dmidecode | grep -P -A16 "Memory Device" Memory Device ...... Speed: 1067 MHz ...... 和“圖書管理員”類似,內存芯片也有類似的工作場景: 場景1: 你的進程需要內存地址0x0000為的一個字節的數據,CPU這時候向內存控制器發出請求,內存控制器進行行地址的預充電,需要等待tRP個時鐘週期。再發出打開一行內存的命令,又需要等待tRCD個時鐘週期。接着發送列地址,再等待CL個週期。最終將0x0000-0x0007的數據全部返回給了CPU。CPU把這些數據放入到了自己的cache裏,並幫你開始對0x0000的數據進行運算。 場景2: 你的進程需要內存地址0x0003的一個字節數據,CPU發現發現它在自己的cache裏存在,直接使用就好了。這個場景裏其實根本就沒有內存IO發生。 場景3: 你的進程需要內存地址0x0008的一個字節數據,CPU的cache並沒有命中,於是向內存控制器請求。內存控制器發現行地址和上一次工作的行地址一致,這次只需要發送列地址後等待CL個週期,就可以拿到0x0008-0x0015的數據並返回給CPU了。 場景4: 你的進程需要內存地址0xf000的一個字節數據,同樣CPU的cache並不命中,向內存控制器請求。內存控制器一看(內心有些許的鬱悶),這次行w地址又變了,得,和場景1一樣。繼續等待tRP+tRCD+CL個週期後,才能夠取到數據並返回。 實際的計算機的內存IO過程中還需要進行邏輯地址和物理地址的轉換,這裏忽略不表。 4結論其中場景1和場景4是隨機IO的情況,場景2無內存IO發生,場景3是順序IO,。通過上面的過程描述我們可以得到結論。內存也存在和磁盤一樣,隨機IO比順序IO要慢的問題。如果行地址同上一次訪問的不一致,則需要重新拷貝row buffer,延遲週期需要tRP+tRCD+CL。而如果是順序IO的話(行地址不變),只需要CL個週期既可完成。 我們接着估算下內存的延時,筆者的機器上的內存參數Speed為1066MHz(通過dmidecode查得),該值除以2就是時鐘週期的頻率=1066/2=533Mhz。其延遲週期為7-7-7-24。 隨機IO:這種狀況下需要tRP+tRCD+CL個時鐘週期,7+7+7=21個週期。但是還有個tRAS的限制,兩次行地址預充電不得小於24。所以我們得按24來計算,24*(1s/533Mhz) = 45ns 順序IO:這種狀況下只需要CL個時鐘週期 7*(1s/533Mhz)=13ns 5擴展,CPU的cache line虛擬內存概念因為對於內存來説,隨機IO一次開銷比順序IO高好幾倍。所以操作系統在工作的時候,會盡量讓內存通過順序IO的方式來進行。做法關鍵就是Cache Line。當CPU發現緩存不命中的時候,實際上從來不會向內存去請求1個字節,8個字節這種。而是一次性就要64字節,然後放到自己的Cache中存起來。 用上面的例子來看, 如果隨機請求8字節:耗時是45ns 如果隨機請求64字節:耗時是45+7*13 = 136ns 開銷也沒貴多少,因為只有第一個字節是隨機IO,後面的7個字節都是順序IO。數據是8倍,但是IO耗時只有3倍,而且取出來的數據後面大概率要用,所以計算機內部就這麼搞了,通過這種方式幫你避免一些隨機IO! 另外,內存也支持burst(突發傳輸)模式,在這種模式下可以只傳入一次行列地址,就命令內存返回該內存開頭的連續字節數據,比如64字節。這種模式下,只有第一次的8字節需要真正的行列訪問延遲,後面的7個字節可以直接按內存的數據頻率給吐出來。 免責聲明:本文內容由21ic獲得授權後發佈,版權歸原作者所有,本平台僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平台立場,如有問題,請聯繫我們,謝謝!

    時間:2021-01-21 關鍵詞: 計算機 IO 內存

  • 乾貨 | 常見的C編程段錯誤及對策

    時間:2021-01-19 關鍵詞: 指針 C編程 內存

  • 如何查詢OS、CPU、內存、硬盤信息

    編排 | strongerHuang 微信公眾號 | 嵌入式專欄 本文描述 linux 查詢操作系統信息,CPU物理個數,CPU核心數,邏輯CPU數,內存信息查詢,硬盤信息查詢。 前言 當我們接手了一台或者幾台服務器的時候,首先我們有必要對服務器的基本配置有所認識,這樣才可以對症下藥,對以後的軟件部署,系統運維會有事半功倍的效果。 關於服務器基本配置 查詢服務器的基本配置一般查詢操作系統,CPU,內存,硬盤,下面進行逐一講解。 2.1 操作系統基本配置查詢 查看操作系統版本 #cat /etc/redhat-release這個命令主要是查看紅帽發行的操作系統的版本號 [root@node5 ~]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) #cat /etc/issue這個命令適用於大多數linux發行版 [root@node5 ~]# cat /etc/issue \S Kernel \r on an \m 查看操作系統內核版本 [root@node5 ~]# uname -r 3.10.0-693.el7.x86_64 查看操作系統詳細信息 [root@node5 ~]# uname -a Linux node5 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux #從上面這段輸出可以看出,該服務器主機名是node5,linux內核版本是3.10.0-693.el7.x86_64,CPU是x86架構 #該命令可以查看更多信息 [root@node5 ~]# more /etc/*release :::::::::::::: /etc/centos-release :::::::::::::: CentOS Linux release 7.4.1708 (Core) :::::::::::::: /etc/os-release :::::::::::::: NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="//www.centos.org/" BUG_REPORT_URL="//bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7" :::::::::::::: /etc/redhat-release :::::::::::::: CentOS Linux release 7.4.1708 (Core) :::::::::::::: /etc/system-release :::::::::::::: CentOS Linux release 7.4.1708 (Core) 2.2 CPU基本配置查詢 名詞解釋 名詞 含義 CPU物理個數 主板上實際插入的cpu數量 CPU核心數 單塊CPU上面能處理數據的芯片組的數量,如雙核、四核等 (cpu cores) 邏輯CPU數/線程數 一般情況下,邏輯cpu=物理CPU個數×每顆核數,如果不相等的話,則表示服務器的CPU支持超線程技術 查看 CPU 物理個數 [root@node5 ~]# grep 'physical id' /proc/cpuinfo | sort -u | wc -l 1 查看 CPU 核心數量 [root@node5 ~]# grep 'core id' /proc/cpuinfo | sort -u | wc -l 4 查看 CPU 線程數 #邏輯cpu數:一般情況下,邏輯cpu=物理CPU個數×每顆核數,如果不相等的話,則表示服務器的CPU支持超線程技術(HT:簡單來説,它可使處理#器中的1 顆內核如2 顆內核那樣在操作系統中發揮作用。這樣一來,操作系統可使用的執行資源擴大了一倍,大幅提高了系統的整體性能,此時邏#輯cpu=物理CPU個數×每顆核數x2) [root@node5 ~]# cat /proc/cpuinfo| grep "processor"|wc -l 4 [root@node5 ~]# grep 'processor' /proc/cpuinfo | sort -u | wc -l 4 查看 CPU 型號 [root@node5 ~]# cat /proc/cpuinfo | grep name | sort | uniq model name : Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz [root@node5 ~]# dmidecode -s processor-version | uniq #使用uniq進行去重 Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz 查看 CPU 的詳細信息 #CPU有幾個核,就會輸出幾個重複的信息 [root@node5 ~]# cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz stepping : 10 microcode : 0x96 cpu MHz : 2000.921 cache size : 8192 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 4 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec arat bogomips : 4002.00 clflush size : 64 cache_alignment : 64 address sizes : 43 bits physical, 48 bits virtual power management: 查看CPU的詳細信息 [root@node5 ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 142 Model name: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz Stepping: 10 CPU MHz: 2000.921 BogoMIPS: 4002.00 Virtualization: VT-x Hypervisor vendor: VMware Virtualization type: full L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 8192K NUMA node0 CPU(s): 0-3 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec arat CPU配置總結 通過以上的查詢,我們可以知道該服務器是1路4核的CPU ,CPU型號是Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz,該CPU沒有超線程 2.3 內存基本配置查詢 名詞解釋 名詞 含義 Mem 內存的使用情況總覽表 Swap 虛擬內存。即可以把數據存放在硬盤上的數據,當物理內存不足時,拿出部分硬盤空間當SWAP分區(虛擬成內存)使用,從而解決內存容量不足的情況。SWAP意思是交換,顧名思義,當某進程向OS請求內存發現不足時,OS會把內存中暫時不用的數據交換出去,放在SWAP分區中,這個過程稱為SWAP OUT。當某進程又需要這些數據且OS發現還有空閒物理內存時,又會把SWAP分區中的數據交換回物理內存中,這個過程稱為SWAP IN。當然,swap大小是有上限的,一旦swap使用完,操作系統會觸發OOM-Killer機制,把消耗內存最多的進程kill掉以釋放內存。 shared 共享內存,即和普通用户共享的物理內存值, 主要用於進程間通信 buffers 用於存放要輸出到disk(塊設備)的數據的 cached 存放從disk上讀出的數據 total 總的物理內存,total=used+free used 使用掉的內存 free 空閒的內存 查詢服務器內存 [root@node5 ~]# free -m total used free shared buff/cache available Mem: 3941 286 3446 19 208 3407 Swap: 2047 0 2047 #註釋 #linux的內存管理機制的思想包括(不敢説就是)內存利用率最大化。內核會把剩餘的內存申請為cached,而cached不屬於free範疇。當系統運#行時間較久,會發現cached很大,對於有頻繁文件讀寫操作的系統,這種現象會更加明顯。直觀的看,此時free的內存會非常小,但並不代表可##用的內存小,當一個程序需要申請較大的內存時,如果free的內存不夠,內核會把部分cached的內存回收,回收的內存再分配給應用程序。所以#對於linux系統,可用於分配的內存不只是free的內存,還包括cached的內存(其實還包括buffers)。 #對於操作系統: #MemFree=total-used #MemUsed = MemTotal - MemFree #對於應用程序: #MemFree=buffers+cached+free 每隔3秒查詢一下內存 [root@node5 ~]# free -s 3 total used free shared buff/cache available Mem: 4036316 361144 3458272 19536 216900 3419776 Swap: 2097148 0 2097148 total used free shared buff/cache available Mem: 4036316 361144 3458272 19536 216900 3419776 Swap: 2097148 0 2097148 total used free shared buff/cache available Mem: 4036316 361144 3458272 19536 216900 3419776 Swap: 2097148 0 2097148 2.4 硬盤基本配置查詢 查詢磁盤整體使用情況 [root@node5 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 17G 4.1G 13G 24% / devtmpfs 2.0G 0 2.0G 0% /dev tmpfs 2.0G 8.0K 2.0G 1% /dev/shm tmpfs 2.0G 8.7M 2.0G 1% /run tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup /dev/sda1 1014M 125M 890M 13% /boot tmpfs 395M 0 395M 0% /run/user/0 #命令拓展 #df -a 顯示全部的文件系統的使用情況 #df -i顯示inode信息 #df -k 已字節數顯示區塊佔用情況 #df -T 顯示文件系統的類型 查詢某個目錄磁盤佔用情況 #命令拓展 #du -s 指定目錄大小彙總 #du -h帶計量單位 #du -a 含文件 #du --max-depth=1 子目錄深度 #du -c 列出明細的同時,增加彙總值 [root@node5 ~]# du -sh /home/ 1.7G /home/ [root@node5 ~]# du -ach --max-depth=2 /home/ 4.0K /home/www/.bash_logout 4.0K /home/www/.bash_profile 4.0K /home/www/.bashrc 4.0K /home/www/web 16K /home/www 4.0K /home/nginx/.bash_logout 4.0K /home/nginx/.bash_profile 4.0K /home/nginx/.bashrc 12K /home/nginx 4.0K /home/esnode/.bash_logout 4.0K /home/esnode/.bash_profile 4.0K /home/esnode/.bashrc 4.0K /home/esnode/.oracle_jre_usage 4.3M /home/esnode/elasticsearch-analysis-ik-6.2.2.zip 80M /home/esnode/kibana-6.2.2-linux-x86_64.tar.gz 300M /home/esnode/x-pack-6.2.2.zip 28M /home/esnode/elasticsearch-6.2.2.tar.gz 4.0K /home/esnode/.bash_history 294M /home/esnode/elasticsearch-6.2.2 4.0K /home/esnode/.ssh 4.0K /home/esnode/x-pack生成的祕鑰.txt 1014M /home/esnode/kibana-6.2.2-linux-x86_64 8.0K /home/esnode/.viminfo 1.7G /home/esnode 1.7G /home/ 1.7G total 查看目錄結構 #tree命令默認沒有安裝,需要手動安裝一下 [root@node5 ~]# yum -y install tree #-L指定目錄深度 [root@node5 ~]# tree -L 2 /home/ /home/ ├── esnode │   ├── elasticsearch-6.2.2 │   ├── elasticsearch-6.2.2.tar.gz │   ├── elasticsearch-analysis-ik-6.2.2.zip │   ├── kibana-6.2.2-linux-x86_64 │   ├── kibana-6.2.2-linux-x86_64.tar.gz │   ├── x-pack-6.2.2.zip │   └── x-pack\347\224\237\346\210\220\347\232\204\347\247\230\351\222\245.txt ├── nginx └── www └── web 6 directories, 5 files 以樹狀的格式顯示所有可用的塊設備信息 [root@node5 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 20G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 19G 0 part ├─centos-root 253:0 0 17G 0 lvm / └─centos-swap 253:1 0 2G 0 lvm [SWAP] sdb 8:16 0 1G 0 disk └─sdb1 8:17 0 200M 0 part sr0 11:0 1 1024M 0 rom #註釋 #NAME —— 設備的名稱 #MAJ:MIN —— Linux 操作系統中的每個設備都以一個文件表示,對塊(磁盤)設備來説,這裏用主次設備編號來描述設備。 #RM —— 可移動設備。如果這是一個可移動設備將顯示 1,否則顯示 0。 #TYPE —— 設備的類型 #MOUNTPOINT —— 設備掛載的位置 #RO —— 對於只讀文件系統,這裏會顯示 1,否則顯示 0。 #SIZE —— 設備的容量 列出所有可用的設備、通用唯一識別碼(UUID)、文件系統類型以及卷標 [root@node5 ~]# blkid /dev/sda1: UUID="6503b4ad-2975-4152-a824-feb7bea1b622" TYPE="xfs" /dev/sda2: UUID="nqZ4uJ-ksnN-KzYS-N42b-00m3-Ohc2-BJXunP" TYPE="LVM2_member" /dev/sdb1: UUID="94396e17-4821-4957-aa76-d41f33958ff5" TYPE="xfs" /dev/mapper/centos-root: UUID="c1d38b37-821d-48e7-8727-3937ccc657a4" TYPE="xfs" /dev/mapper/centos-swap: UUID="c2fcaf11-42d8-4e4c-bf9e-6464f0777198" TYPE="swap" 免責聲明:本文內容由21ic獲得授權後發佈,版權歸原作者所有,本平台僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平台立場,如有問題,請聯繫我們,謝謝!

    時間:2021-01-19 關鍵詞: CPU 硬盤 內存

  • 聯想拯救者R9000X 2021遊戲本磁盤、內存速度測評

    聯想拯救者R9000X 2021遊戲本磁盤、內存速度測評

    在這篇文章中,小編將對聯想拯救者R9000X 2021遊戲本進行磁盤讀寫速度測評和內存讀取速度磁測評。如果你對聯想拯救者R9000X遊戲本,抑或是對它的性能具有興趣,不妨繼續往下閲讀哦。 一、聯想拯救者R9000X遊戲本基本介紹 聯想拯救者R9000X遊戲本搭載了 AMD 8 核 16 線程的 R7 4800H 處理器,配以 RTX 2060 顯卡,內存為 16GB DDR4-3200。此外,聯想拯救者R9000X遊戲本的SSD 為 512GB,雙 M.2 SSD 槽,還有 2.5 英寸硬盤位。與此同時,聯想拯救者R9000X遊戲本配備了NVIDIA GeForce RTX2060 Max-Q 獨立顯卡,1920個流處理器,6GB 192bit GDDR6顯存,性能釋放可達75W,並且支持實時光線追蹤和DLSS 2.0,這樣的配置可以為玩家帶來堪比真實世界般的光線視覺感受,這使得聯想拯救者R9000X遊戲本足以應對任何3A大作和大型網遊。 二、聯想拯救者R9000X遊戲本性能測評 通過上面對聯想拯救者R9000X遊戲本的簡單介紹,想必大家對聯想拯救者R9000X遊戲本已經具備一定的瞭解。在這裏,小編將對聯想拯救者R9000X遊戲本進行磁盤讀寫速度測評和內存讀取速度測評。 (一)聯想拯救者R9000X遊戲本磁盤讀寫測試 AS SSD Benchmark是一款SSD固態硬盤傳輸速度測速工具。此軟件可以測出固態硬盤持續讀寫等的性能,讓您只要使用此軟件來測試就可以評估這個固態硬盤的傳輸速度好與不好。 在AS SSD Benchmark中,聯想拯救者R9000X遊戲本的固態連續讀取速度、連續寫入速度、隨機讀取速度、隨機寫入速度分別為2620MB/s、2460MB/s、51.98MB/s和116.65MB/s。 CrystalDiskMark是一個測試電腦硬盤檢測工具,簡單易於操作的界面隨時可以測試存儲設備,測試存儲設備大小和測試數字都可以選擇,還可測試可讀和可寫的速度。在CrystalDiskMark中,聯想拯救者R9000X遊戲本的連續讀取速度、連續寫入速度、隨機讀取速度、隨機寫入速度分別為3569MB/s、2821MB/s、41.8MB/s和90.14MB/s。 (二)聯想拯救者R9000X遊戲本內存讀取速度測試 拯救者R9000X搭載了兩根8GB 3200MHz DDR4內存,DDR4內存是新一代的內存規格。DDR4相比DDR3最大的區別有三點:16bit預取機制(DDR3為8bit),同樣內核頻率下理論速度是DDR3的兩倍;更可靠的傳輸規範,數據可靠性進一步提升;工作電壓降為1.2V,更節能。 通過測試我們可以知道,聯想拯救者R9000X遊戲本的讀取速度、寫入速度、拷貝速度和延遲分別為37902MB/s、36739MB/s、32229MB/s和84.8ns。 以上所有內容便是小編此次為大家帶來的有關聯想拯救者R9000X遊戲本的所有介紹,如果你想了解更多有關聯想拯救者R9000X遊戲本的內容,不妨在我們網站或者百度、google進行探索哦。

    時間:2021-01-06 關鍵詞: 磁盤 R9000X 內存

  • 戴爾Precision 7750工作站磁盤、內存測評

    戴爾Precision 7750工作站磁盤、內存測評

    在這篇文章中,小編將對戴爾Precision 7750工作站進行磁盤速度測評和內存速度測評。如果你對戴爾Precision 7750工作站或者對戴爾Precision 7750工作站的性能具有興趣,不妨繼續往下閲讀哦。 一、戴爾Precision 7750工作站基本介紹 戴爾Precision 7750工作站配備了17.3英寸的大屏幕,屏幕左右邊框控制得不錯,上下邊框會寬一點,視野開闊。此外,戴爾Precision 7750工作站上邊框配備了一個攝像頭,擁有一個物理滑動裝置,可以隱藏攝像頭,在這樣的設置下,我們的隱私能夠很大程度上得到保護。 而在接口方面,戴爾Precision 7750工作站提供三個USB-A 3.0、兩個USB-C 3.1、一個HDMI 2.0、一個miniDP 1.4。除此以外,戴爾Precision 7750工作站還為我們提供了一個3.5mm耳麥一體、一個SD卡槽、一個智能卡槽、一個microSIM卡槽。 二、戴爾Precision 7750工作站性能測評 通過上面對戴爾Precision 7750工作站的簡單介紹,想必大家對戴爾Precision 7750工作站已經具有初步瞭解。在這裏,小編將對戴爾Precision 7750工作站的磁盤、內存性能加以測評。 (一)戴爾Precision 7750工作站硬盤速度測試 固態驅動器,俗稱固態硬盤,也即SSD。固態硬盤是用固態電子存儲芯片陣列而製成的硬盤,因為台灣英語裏把固體電容稱之為Solid而得名。SSD由控制單元和存儲單元(FLASH芯片、DRAM芯片)組成。固態硬盤在接口的規範和定義、功能及使用方法上與普通硬盤的完全相同,在產品外形和尺寸上也完全與普通硬盤一致。被廣泛應用於軍事、車載、工控、視頻監控、網絡監控、網絡終端、電力、醫療、航空、導航設備等諸多領域。 戴爾Precision 7750工作站的機身內部共有4個M.2硬盤位,目前插有3條海力士PC601A NVMe固態。在AS SSD Benchmark中,戴爾Precision 7750工作站的磁盤持續讀取速度、持續寫入速度、隨機讀取速度和隨機寫入速度分別為2836MB/s、738MB/s、43.62MB/s和110.78MB/s。 在 CrystalDiskMark中,戴爾Precision 7750工作站磁盤的持續讀取速度、持續寫入速度、隨機讀取速度和隨機寫入速度分別為3200MB/s、2669MB/s、48.47MB/s和144.7MB/s。 (二)戴爾Precision 7750工作站內存速度測試 DDR4內存是新一代的內存規格,DDR4相比DDR3最大的區別有三點:16bit預取機制(DDR3為8bit),同樣內核頻率下理論速度是DDR3的兩倍;更可靠的傳輸規範,數據可靠性進一步提升;工作電壓降為1.2V,更節能。 戴爾Precision 7750工作站搭載了4根 32GB 2666MHz DDR4內存,讀取速度、寫入速度、拷貝速度和延遲分別為39192MB/s、 41017MB/s、39525MB/s和62.6ns。 經由小編的介紹,不知道你對戴爾Precision 7750工作站是否充滿了興趣?如果你想對戴爾Precision 7750工作站有更多的瞭解,不妨嘗試度娘更多信息或者在我們的網站裏進行搜索哦。

    時間:2021-01-04 關鍵詞: 戴爾 工作站 內存

  • 首長,Redis性能優化十三條軍規立好了,請過目~

    前言 Redis作為高性能的內存數據庫,在大數據量的情況下也會遇到性能瓶頸,日常開發中只有時刻謹記優化鐵則,才能使得Redis性能發揮到極致。 本文將會介紹十三條性能優化軍規,開發過程中只要按照執行,性能必能質的飛躍。 1. 避免慢查詢命令 慢查詢命令指的是執行較慢的命令,Redis自身提供了許多的命令,並不是所有的命令都慢,這和命令的操作複雜度有關,因此必須知道Redis不同命令的複雜度。 如説,Value 類型為 String 時,GET/SET 操作主要就是操作 Redis 的哈希表索引。這個操作複雜度基本是固定的,即 O(1)。但是,當 Value 類型為 Set 時,SORT、SUNION/SMEMBERS 操作複雜度分別為 O(N+M*log(M)) 和 O(N)。其中,N 為 Set 中的元素個數,M 為 SORT 操作返回的元素個數。這個複雜度就增加了很多。Redis 官方文檔中對每個命令的複雜度都有介紹,當你需要了解某個命令的複雜度時,可以直接查詢。 當你發現 Redis 性能變慢時,可以通過 Redis 日誌,或者是 latency monitor 工具,查詢變慢的請求,根據請求對應的具體命令以及官方文檔,確認下是否採用了複雜度高的慢查詢命令。 如果確實存在大量的慢查詢命令,建議如下兩種方式: 用其他高效的命令代替:比如説,如果你需要返回一個 SET 中的所有成員時,不要使用 SMEMBERS 命令,而是要使用 SSCAN 多次迭代返回,避免一次返回大量數據,造成線程阻塞。 當你需要執行排序、交集、並集操作時,可以在客户端完成,而不要用 SORT、SUNION、SINTER 這些命令,以免拖慢 Redis 實例。 2. 生產環境禁用keys命令 keys這個命令是最容易忽略的慢查詢命令,因為keys命令需要遍歷存儲的鍵值對,所以操作延時很高,在生產環境使用很可能導致Redis阻塞;因此不建議在生產環境中使用keys命令。 3. keys需要設置過期時間 Redis作為內存數據庫,一切的數據都是在內存中,一旦內存佔用過大則會大大影響性能,因此需要對有時間限制的數據需要設置過期時間,這樣Redis能夠定時的刪除過期的數據。 4. 禁止批量的給keys設置相同的過期時間 默認情況下,Redis 每 100 毫秒會刪除一些過期 key,具體的算法如下: 採樣 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 個數的 key,並將其中過期的 key 全部刪除; 如果超過 25% 的 key 過期了,則重複刪除的過程,直到過期 key 的比例降至 `25%`` 以下。 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 是 Redis 的一個參數,默認是 20,那麼,一秒內基本有 200 個過期 key 會被刪除。這一策略對清除過期 key、釋放內存空間很有幫助。如果每秒鐘刪除 200 個過期 key,並不會對 Redis 造成太大影響。 但是,如果觸發了上面這個算法的第二條,Redis 就會一直刪除以釋放內存空間。注意,刪除操作是阻塞的(Redis 4.0 後可以用異步線程機制來減少阻塞影響)。所以,一旦該條件觸發,Redis 的線程就會一直執行刪除,這樣一來,就沒辦法正常服務其他的鍵值操作了,就會進一步引起其他鍵值操作的延遲增加,Redis 就會變慢。 頻繁使用帶有相同時間參數的 EXPIREAT 命令設置過期 key 將會觸發算法第二條,這就會導致在一秒內存在大量的keys過期。 因此開發中一定要禁止批量的給keys設置過期時間。 5. 謹慎選擇數據結構 Redis 常用的數據結構一共有五種:string、hash、list、set、zset(sorted set)。可以發現,大多數場景下使用 string 都可以去解決問題。但是,這並不一定是最優的選擇。下面,簡單説明下它們各自的適用場景: string:單個的緩存結果,不與其他的 KV 之間有聯繫 hash:一個 Object 包含有很多屬性,且這些屬性都需要單獨存儲。注意:這種情況不要使用 string,因為 string 會佔據更多的內存 list:一個 Object 包含很多數據,且這些數據允許重複、要求有順序性 set:一個 Object 包含很多數據,不要求數據有順序,但是不允許重複 zset:一個 Object 包含很多數據,且這些數據自身還包含一個權重值,可以利用這個權重值來排序 另外Redis還提供了幾種的擴展類型,如下: HyperLogLog:適合用於 基數統計,比如PV,UV的統計,存在 誤差問題,不適合精確統計。 BitMap:適合 二值狀態的統計,比如簽到打卡,要麼打卡了,要麼未打卡。 6. 檢查持久化策略 Redis4.0之後使用瞭如下三種持久化策略: AOF日誌:一種採用文件追加的方式將命令記錄在日誌中的策略,針對同步和異步追加還提供了三個配置項,有興趣的可以查看官方文檔。 RDB快照:以快照的方式,將某一個時刻的內存數據,以二進制的方式寫入磁盤。 AOF和 RDB混用:Redis4.0新增的方式,為了採用兩種方式各自的優點,在RDB快照的時間段內使用的AOF日誌記錄這段時間的操作的命令,這樣一旦發生宕機,將不會丟失兩段快照中間的數據。 由於寫入磁盤有IO性能瓶頸,因此不是將Redis作為數據庫的話(可以從後端恢復),建議禁用持久化或者調整持久化策略。 7. 採用高速的固態硬盤作為日誌寫入設備 由於AOF日誌的重寫對磁盤的壓力較大,很可能會阻塞,如果需要使用到持久化,建議使用高速的固態硬盤作為日誌寫入設備。 8. 使用物理機而非虛擬機 由於虛擬機增加了虛擬化軟件層,與物理機相比,虛擬機本身就存在性能的開銷,可以使用如下命令來分別測試下物理機和虛擬機的基線性能: ./redis-cli --intrinsic-latency 120 測試結果可以知道,使用物理機的基線性能明顯比虛擬機的基線性能更好。 9. 增加機器內存或者使用Redis集羣 物理機器的內存不足將會導致操作系統內存的Swap。 內存 swap 是操作系統裏將內存數據在內存和磁盤間來回換入和換出的機制,涉及到磁盤的讀寫,所以,一旦觸發 swap,無論是被換入數據的進程,還是被換出數據的進程,其性能都會受到慢速磁盤讀寫的影響。 Redis 是內存數據庫,內存使用量大,如果沒有控制好內存的使用量,或者和其他內存需求大的應用一起運行了,就可能受到 swap 的影響,而導致性能變慢。 這一點對於 Redis 內存數據庫而言,顯得更為重要:正常情況下,Redis 的操作是直接通過訪問內存就能完成,一旦 swap 被觸發了,Redis 的請求操作需要等到磁盤數據讀寫完成才行。而且,和我剛才説的 AOF 日誌文件讀寫使用 fsync 線程不同,swap 觸發後影響的是 Redis 主 IO 線程,這會極大地增加 Redis 的響應時間。 因此增加機器的內存或者使用Redis集羣能夠有效的解決操作系統內存的Swap,提高性能。 10. 使用 Pipeline 批量操作數據 Pipeline (管道技術) 是客户端提供的一種批處理技術,用於一次處理多個 Redis 命令,從而提高整個交互的性能。 11. 客户端使用優化 在客户端的使用上我們除了要儘量使用 Pipeline 的技術外,還需要注意要儘量使用 Redis 連接池,而不是頻繁創建銷燬 Redis 連接,這樣就可以減少網絡傳輸次數和減少了非必要調用指令。 12. 使用分佈式架構來增加讀寫速度 Redis 分佈式架構有三個重要的手段: 主從同步 哨兵模式 Redis Cluster 集羣 使用主從同步功能我們可以把寫入放到主庫上執行,把讀功能轉移到從服務上,因此就可以在單位時間內處理更多的請求,從而提升的 Redis 整體的運行速度。 而哨兵模式是對於主從功能的升級,但當主節點奔潰之後,無需人工干預就能自動恢復 Redis 的正常使用。 Redis Cluster 是 Redis 3.0 正式推出的,Redis 集羣是通過將數據分散存儲到多個節點上,來平衡各個節點的負載壓力。 Redis Cluster 採用虛擬哈希槽分區,所有的鍵根據哈希函數映射到 0 ~ 16383整數槽內,計算公式:slot = CRC16(key) & 16383,每一個節點負責維護一部分槽以及槽所映射的鍵值數據。這樣 Redis 就可以把讀寫壓力從一台服務器,分散給多台服務器了,因此性能會有很大的提升。 在這三個功能中,我們只需要使用一個就行了,毫無疑問 Redis Cluster 應該是首選的實現方案,它可以把讀寫壓力自動的分擔給更多的服務器,並且擁有自動容災的能力。 13. 避免內存碎片 頻繁的新增修改會導致內存碎片的增多,因此需要時刻的清理內存碎片。 Redis提供了INFO memory可以查看內存的使用信息,如下: INFO memory# Memoryused_memory:1073741736used_memory_human:1024.00Mused_memory_rss:1997159792used_memory_rss_human:1.86G…mem_fragmentation_ratio:1.86 這裏有一個 mem_fragmentation_ratio 的指標,它表示的就是 Redis 當前的內存碎片率。那麼,這個碎片率是怎麼計算的呢?其實,就是上面的命令中的兩個指標 used_memory_rss 和 used_memory 相除的結果。 mem_fragmentation_ratio = used_memory_rss/ used_memory used_memory_rss 是操作系統實際分配給 Redis 的物理內存空間,裏面就包含了碎片;而 used_memory 是 Redis 為了保存數據實際申請使用的空間。 那麼,知道了這個指標,我們該如何使用呢?在這兒,我提供一些經驗閾值: mem_fragmentation_ratio 大於 1 但小於 1.5。這種情況是合理的。這是因為,剛才我介紹的那些因素是難以避免的。畢竟,內因的內存分配器是一定要使用的,分配策略都是通用的,不會輕易修改;而外因由 Redis 負載決定,也無法限制。所以,存在內存碎片也是正常的。 mem_fragmentation_ratio 大於 1.5 。這表明內存碎片率已經超過了 50%。一般情況下,這個時候,我們就需要採取一些措施來降低內存碎片率了。 一旦內存碎片率過高了,此時就應該採用手段清理內存碎片了,具體如何清理,參考文章:Redis清理內存碎片 總結 本文着重介紹了13條性能優化軍規,在開發過程中還是需要針對性的具體問題具體分析,希望作者這篇文章能夠幫助到你。 特別推薦一個分享架構+算法的優質內容,還沒關注的小夥伴,可以長按關注一下: 長按訂閲更多精彩▼如有收穫,點個在看,誠摯感謝 免責聲明:本文內容由21ic獲得授權後發佈,版權歸原作者所有,本平台僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平台立場,如有問題,請聯繫我們,謝謝!

    時間:2020-12-23 關鍵詞: 嵌入式 內存

  • 全面解讀操作系統中的內存管理,你懂幾點?

    轉自 | 程序喵大人 今天分享關於內存的幾點內容: 什麼是物理內存 使用物理內存有什麼缺點? 什麼是虛擬內存? 虛擬內存如何映射到物理內存 什麼是分頁內存管理? 什麼是缺頁中斷? 頁面置換算法都有哪些? 什麼是分段內存管理? 01什麼是物理內存? 我們常説的物理內存大小就是指內存條的大小,一般買電腦時都會看下內存條是多大容量的,話説如果內存條大小是100G,那這100G就都能夠被使用嗎?不一定的,更多的還是要看CPU地址總線的位數,如果地址總線只有20位,那麼它的尋址空間就是1MB,即使可以安裝100G的內存條也沒有意義,也只能視物理內存大小為1MB。 02使用物理內存有什麼缺點? 這種方式下每個程序都可以直接訪問物理內存,有兩種情況: 1.系統中只有一個進程在運行:如果用户程序可以操作物理地址空間的任意地址,它們就很容易在不經意間破壞了操作系統,使系統出現各種奇奇怪怪的問題; 2.系統有多個進程同時在運行:如圖,理想情況下可以使進程A和進程B各佔物理內存的一邊,兩者互不干擾,但這只是理想情況下,誰能確保程序沒有bug呢,進程B在後台正常運行着,程序員在調試進程A時有可能就會誤操作到進程B正在使用的物理內存,導致進程B運行出現異常,兩個程序操作了同一地址空間,第一個程序在某一地址空間寫入某個值,第二個程序在同一地址又寫入了不同值,這就會導致程序運行出現問題,所以直接使用物理內存會使所有進程的安全性得不到保證。 如何解決上述問題? 可以考慮為存儲器創造新的抽象概念:地址空間,地址空間為程序創造了一種抽象的內存,是進程可用於尋址內存的一套地址集合,同時每個進程都有一套自己的地址空間,一個進程的地址空間獨立於其它進程的地址空間。 如何為程序創造獨立的地址空間? 最簡單的辦法就是把每個進程的地址空間分別映射到物理內存的不同部分。這樣就可以保證不同進程使用的是獨立的地址空間。 實現 給每個進程提供一個基址A和界限B,進程內使用的空間為x,則對應的物理地址為A + x,同時需要保證A + x < B,如果訪問的地址超過的界限,需要產生錯誤並中止訪問。為了達到目的CPU配置了兩個特殊硬件寄存器:基址寄存器和界限寄存器,當一個進程運行時,程序的起始物理地址和長度會分別裝入到基址寄存器和界限寄存器裏,進程訪問內存,在每個內存地址送到內存之前,都會先加上基址寄存器的內容。 缺點:每次訪問內存都需要進行加法和比較運算,比較運算很快,但是加法運算由於進位傳遞事件的問題,在沒有使用特殊電路的情況下會顯得很慢。 此外,每個進程運行都會佔據一定的物理內存,如果物理內存足夠大到可以容納許多個進程同時運行還好,但現實中物理內存的大小是有限的,可能會出現內存不夠用的情況,怎麼辦? 方法一:如果是因為程序太大,大到超過了內存的容量,可以採用手動覆蓋技術,只把需要的指令和數據保存在內存中。 方法二:如果是因為程序太多,導致超過了內存的容量,可以採用自動交換技術,把暫時不需要執行的程序移動到外存中。 覆蓋技術 把程序按照自身邏輯結構,劃分成多個功能相互獨立的程序模塊,那些不會同時執行的模塊可以共享到同一塊內存區域,按時間順序來運行: 將常用功能需要的代碼和數據常駐在內存中; 將不常用的功能劃分成功能相互獨立的程序模塊,平時放到外存中,在需要的時候將對應的模塊加載到內存中; 那些沒有調用關係的模塊平時不需要裝入到內存,它們可以共用一塊內存區,需要時加載到內存,不需要時換出到外存中; 如圖: 交換技術 多個程序同時運行,可以將暫時不能運行的程序送到外存,獲得更多的空閒內存,操作系統將一個進程的整個地址空間內容換出到外存中,再將外存中某個進程的整個地址空間信息換入到內存中,換入換出內容的大小是整個程序的地址空間。 交換技術在實現上有很多困難: 需要確定什麼時候發生交換:簡單的辦法是可以在內存空間不夠用時換出一些程序; 交換區必須足夠大:多個程序運行時,交換區(外存)必須足夠大,大到可以存放所有程序所需要的地址空間信息; 程序如何換入:一個程序被換出後又重新換入,換入的內存位置可能不會和上一次程序所在的內存位置相同,這就需要動態地址映射機制。 覆蓋技術和交換技術的比較 覆蓋只能發生在那些相互之間沒有調用關係的程序模塊之間,因此程序員必須給出程序內的各個模塊之間的邏輯覆蓋結構。 交換技術是以在內存中的程序大小為單位來進行的,它不需要程序員給出各個模塊之間的邏輯覆蓋結構。 通俗來説:覆蓋發生在程序的內部,交換髮生在程序與程序之間。 但是這兩種技術都有缺點: 覆蓋技術:需要程序員自己把整個程序劃分為若干個小的功能模塊,並確定各個模塊之間的覆蓋關係,增加了程序員的負擔,很少有程序員擅長這種技術; 交換技術:以進程作為交換的單位,需要把進程的整個地址空間都換進換出,增加了處理器的開銷,還需要足夠大的外存。 那有沒有更好的解決上述問題的方法呢?答案是虛擬內存技術。 03什麼是虛擬內存? 虛擬內存,那就是虛擬出來的內存,它的基本思想就是確保每個程序擁有自己的地址空間,地址空間被分成多個塊,每一塊都有連續的地址空間,同時物理空間也分成多個塊,塊大小和虛擬地址空間的塊大小一致,操作系統會自動將虛擬地址空間映射到物理地址空間,程序所關注的只是虛擬內存,請求的也是虛擬內存,其實真正使用的是物理內存。 虛擬內存技術有覆蓋技術的功能,但它不是把程序的所有內容都放在內存中,因而能夠運行比當前的空閒內存空間還要大的程序。它比覆蓋技術做的更好,整個過程由操作系統自動來完成,無需程序員的干涉; 虛擬內存技術有交換技術的功能,能夠實現進程在內存和外存之間的交換,因而獲得更多的空閒內存空間。它比交換技術做的更好,它只對進程的部分內容在內存和外存之間進行交換。 虛擬內存技術的具體實現: 虛擬內存技術一般是在頁式管理(下面介紹)的基礎上實現 在裝入程序時,不必將其全部裝入到內存,而只需將當前需要執行的部分頁面裝入到內存,就可讓程序開始執行; 在程序執行過程中,如果需執行的指令或訪問的數據尚未在內存(稱為缺頁)。則由處理器通知操作系統將相應的頁面調入到內存,然後繼續執行程序; 另一方面,操作系統將內存中暫時不使用的頁面調出保存在外存上,從而騰出更多空閒空間存放將要裝入的程序以及將要調入的頁面。 虛擬內存技術的特點 : 大的用户空間:通過把物理內存與外存相結合,提供給用户的虛擬內存空間通常大於實際的物理內存,即實現了兩者的分離。如32位的虛擬地址理論上可以訪問4GB,而可能計算機上僅有256M的物理內存,但硬盤容量大於4GB; 部分交換:與交換技術相比較,虛擬存儲的調入和調出是對部分虛擬地址空間進行的; 連續性:程序可以使用一系列相鄰連續的虛擬地址來映射物理內存中不連續的大內存緩衝區; 安全性:不同進程使用的虛擬地址彼此隔離。一個進程中的代碼無法更改正在由另一進程或操作系統使用的物理內存。 04虛擬內存如何映射到物理內存? 如圖,CPU裏有一個內存管理單元(Memory Management Unit),簡稱MMU,虛擬內存不是直接送到內存總線,而是先給到MMU,由MMU來把虛擬地址映射到物理地址,程序只需要管理虛擬內存就好,映射的邏輯自然有其它模塊自動處理。 操作系統如何表示的內存被佔用還是空閒? 05分頁內存管理 將虛擬地址空間分成若干個塊,每個塊都有固定的大小,物理地址空間也被劃分成若干個塊,每個塊也都有固定的大小,物理地址空間的塊和虛擬地址空間的塊大小相等,虛擬地址空間這些塊就被稱為頁面,物理地址空間這些塊被稱為幀。 關於分頁這裏有個問題,頁面的大小是多少合適呢?頁面太大容易產生空間浪費,程序假如只使用了1個字節卻被分配了10M的頁面,這豈不是極大的浪費,頁面太小會導致頁表(下面介紹)佔用空間過大,所以頁面需要折中選擇合適的大小,目前大多數系統都使用4KB作為頁的大小。 上面關於虛擬內存如何映射到物理內存程序喵只介紹了MMU,但是MMU是如何工作的還沒有介紹,MMU通過頁表這個工具將虛擬地址轉換為物理地址。32位的虛擬地址分成兩部分(虛擬頁號和偏移量),MMU通過頁表找到了虛擬頁號對應的物理頁號,物理頁號+偏移量就是實際的物理地址。 具體如圖: 圖只表示了頁表的大體功能,頁表的結構其實還很複雜,下面會具體介紹。 頁表的目的就是虛擬頁面映射為物理內存的頁框,頁表可以理解為一個數學函數,函數的輸入是虛擬頁號,函數的輸出是物理頁號,通過這個函數可以把虛擬頁面映射到物理頁號,從而確定物理地址。不同機器的頁表結構不同,通常頁表的結構如下: 頁框號:最主要的一項,頁表最主要的目的就是找到物理頁號; 有效位:1表示有效,表示該表項是有效的,如果為0,表示該表項對應的虛擬頁面現在不在內存中,訪問該頁面會引起缺頁中斷,缺頁中斷後會去物理空間找到一個可用的頁框填回到頁表中; 保護位:表示一個頁允許什麼類型的訪問,可讀可寫還是可執行; 修改位:該位反應了頁面的狀態,在操作系統重新分配頁框時有用,在寫入一頁時由硬件自動設置該位,重新分配頁框時,如果一個頁面已經被修改過,則必須把它這個髒頁寫回磁盤,如果沒有被修改過,表示該頁是乾淨的,它在磁盤上的副本依然是有效的,直接丟棄該頁面即可。 訪問位:該位主要用於幫助操作系統在發生缺頁中斷時選擇要被淘汰的頁面,不再使用的頁面顯然比正在使用的頁面更適合被淘汰,該位在頁面置換算法中發揮重要作用。 高速緩存禁止位:該位用於禁止該頁面被高速緩存。 如何加快地址映射速度? 每次訪問內存都需要進行虛擬地址到物理地址的映射,每次映射都需要訪問一次頁表,所有的指令執行都必須通過內存,很多指令也需要訪問內存中的操作數,因此每條指令執行基本都會進行多次頁表查詢,為了程序運行速度,指令必須要在很短的時間內執行完成,而頁表查詢映射不能成為指令執行的瓶頸,所以需要提高頁表查詢映射的速度。 如何才能提高速度呢?可以為頁表提供一個緩存,通過緩存進行映射比通過頁表映射速度更快,這個緩存是一個小型的硬件設備,叫快表(TLB),MMU每次進行虛擬地址轉換時,首先去TLB中查找,找到了有效的物理頁框則直接返回,如果沒有找到則進行正常的頁表訪問,頁表中找到後則更新TLB,從TLB中淘汰一個表項,然後用新找到的表項替代它,這樣下次相同的頁面過來時可以直接命中TLB找到對應的物理地址,速度更快,不需要繼續去訪問頁表。 這裏之所以認為TLB能提高速度主要依靠程序局部性原理,程序局部性原理是指程序在執行過程中的一個較短時間,所執行的指令地址和要訪問的數據通常都侷限在一塊區域內,這裏可分為時間局部性和空間局部性: 時間局部性:一條指令的一次執行和下次執行,一個數據的一次訪問和下次訪問都集中在一個較短時間內; 空間局部性:當前指令和鄰近的幾條指令,當前訪問的數據和鄰近的幾個數據都集中在一個較小區域內。 通過TLB可以加快虛擬地址到物理地址的轉換速度,還有個問題,現在都是64位操作系統啦,有很大的虛擬地址空間,虛擬地址空間大那對應的頁表也會非常大,又加上多個進程多個頁表,那計算機的大部分空間就都被拿去存放頁表,有沒有更好的辦法解決頁表大的問題呢?答案是多級頁表。 tips:頁表為什麼大?32位環境下,虛擬地址空間有4GB,一個頁大小是4KB,那麼整個頁表就需要100萬頁,而每個頁表項需要4個字節,那整個頁表就需要4MB的內存空間,又因為每個進程都有一個自己的頁表,多個進程情況下,這簡直就是災難。 如圖,以一個32位虛擬地址的二級頁表為例,將32位虛擬地址劃分為10位的PT1域,10位的PT2域,以及12位的offset域,當一個虛擬地址被送入MMU時,MMU首先提取PT1域並把其值作為訪問第一級頁表的索引,之後提取PT2域把把其值作為訪問第二級頁表的索引,之後再根據offset找到對應的頁框號。 32位的虛擬地址空間下:每個頁面4KB,且每條頁表項佔4B: 一級頁表:進程需要1M個頁表項(4GB / 4KB = 1M, 2^20個頁表項),即頁表(每個進程都有一個頁表)佔用4MB(1M * 4B = 4MB)的內存空間。 二級頁表:一級頁表映射4MB(2^22)、二級頁表映射4KB,則需要1K個一級頁表項(4GB / 4MB = 1K, 2^10個一級頁表項)、每個一級頁表項對應1K個二級頁表項(4MB / 4KB = 1K),這樣頁表佔用4.004MB(1K * 4B + 1K * 1K * 4B = 4.004MB)的內存空間。 二級頁表佔用空間看着貌似變大了,為什麼還説多級頁表省內存呢? 每個進程都有4GB的虛擬地址空間,而顯然對於大多數程序來説,其使用到的空間遠未達到4GB,何必去映射不可能用到的空間呢? 也就是説,一級頁表覆蓋了整個4GB虛擬地址空間,但如果某個一級頁表的頁表項沒有被用到,也就不需要創建這個頁表項對應的二級頁表了,即可以在需要時才創建二級頁表。做個簡單的計算,假設只有20%的一級頁表項被用到了,那麼頁表佔用的內存空間就只有0.804MB(1K*4B+0.2*1K*1K*4B=0.804MB),對比單級頁表的4M是不是一個巨大的節約? 那麼為什麼不分級的頁表就做不到這樣節約內存呢?我們從頁表的性質來看,保存在主存中的頁表承擔的職責是將虛擬地址翻譯成物理地址。假如虛擬地址在頁表中找不到對應的頁表項,計算機系統就不能工作了。所以頁表一定要覆蓋全部虛擬地址空間,不分級的頁表就需要有1M個頁表項來映射,而二級頁表則最少只需要1K個頁表項(此時一級頁表覆蓋到了全部虛擬地址空間,二級頁表在需要時創建)。 二級頁表其實可以不在內存中:其實這就像是把頁表當成了頁面。當需要用到某個頁面時,將此頁面從磁盤調入到內存;當內存中頁面滿了時,將內存中的頁面調出到磁盤,這是利用到了程序運行的局部性原理。我們可以很自然發現,虛擬內存地址存在着局部性,那麼負責映射虛擬內存地址的頁表項當然也存在着局部性了!這樣我們再來看二級頁表,根據局部性原理,1024個第二級頁表中,只會有很少的一部分在某一時刻正在使用,我們豈不是可以把二級頁表都放在磁盤中,在需要時才調入到內存? 我們考慮極端情況,只有一級頁表在內存中,二級頁表僅有一個在內存中,其餘全在磁盤中(雖然這樣效率非常低),則此時頁表佔用了8KB(1K*4B+1*1K*4B=8KB),對比上一步的0.804MB,佔用空間又縮小了好多倍!(這裏參考的下面知乎鏈接中大佬的回答) 06 什麼是缺頁中斷? 缺頁中斷就是要訪問的頁不在主存中,需要操作系統將頁調入主存後再進行訪問,此時會暫時停止指令的執行,產生一個頁不存在的異常,對應的異常處理程序就會從選擇一頁調入到內存,調入內存後之前的異常指令就可以繼續執行。 缺頁中斷的處理過程如下: 如果內存中有空閒的物理頁面,則分配一物理頁幀r,然後轉第4步,否則轉第2步; 選擇某種頁面置換算法,選擇一個將被替換的物理頁幀r,它所對應的邏輯頁為q,如果該頁在內存期間被修改過,則需把它寫回到外存; 將q所對應的頁表項進行修改,把駐留位置0; 將需要訪問的頁p裝入到物理頁面r中; 修改p所對應的頁表項的內容,把駐留位置1,把物理頁幀號置為x; 重新運行被中斷的指令。 07頁面置換算法都有哪些? 當缺頁中斷髮生時,需要調入新的頁面到內存中,而內存已滿時,選擇內存中哪個物理頁面被置換是個學問,由此引入了多種頁面置換算法,致力於儘可能減少頁面的換入換出次數(缺頁中斷次數)。儘量把未來不再使用的或短期內較少使用的頁面換出,通常在程序局部性原理指導下依據過去的統計數據來進行預測。 最優頁面置換算法:當一個缺頁中斷髮生時,對於保存在內存當中的每一個邏輯頁面,計算在它的下一次訪問之前,還需等待多長時間,從中選擇等待時間最長的那個,作為被置換的頁面。注意這只是一種理想情況,在實際系統中是無法實現的,因為操作系統不可能預測未來,不知道每一個頁面要等待多長時間以後才會再次被訪問。該算法可用作其它算法的性能評價的依據(在一個模擬器上運行某個程序,並記錄每一次的頁面訪問情況,在第二遍運行時即可使用最優算法)。 先進先出算法:最先進入的頁面最先被淘汰,這種算法很簡單,就不過多介紹啦。 最近最久未使用算法:傳説中的LUR算法,當發生缺頁中斷時,選擇最近最久沒有使用過的頁面淘汰,該算法會給每個頁面一個字段,用於記錄自上次訪問以來所經歷的時間T,當需要淘汰一個頁面時,選擇已有頁面中T值最大的頁面進行淘汰。 第二次機會頁面置換算法:先進先出算法的升級版,只是在先進先出算法的基礎上做了一點點改動,因為先進先出算法可能會把經常使用的頁面置換出去,該方法會給這些頁面多一次機會,給頁面設置一個修改位R,每次淘汰最老頁面時,檢查最老頁面的R位,如果R位是0,那麼代表這個頁面又老又沒有被二次使用過,直接淘汰,如果這個頁面的R位是1,表示該頁面被二次訪問過,將R位置0,並且把該頁面放到鏈表的尾端,像該頁面是最新進來的一樣,然後繼續按這種方法淘汰最老的頁面。 時鐘頁面置換算法:第二次機會頁面算法的升級版,儘管二次機會頁面算法是比較合理的算法,但它需要在鏈表中經常移動頁面,效率比較低,時鐘頁面置換算法如圖,該算法把所有的頁面都保存在一個類似時鐘的環形鏈表中,一個錶針指向最老的頁面,當發生缺頁中斷時,算法首先檢查錶針指向的頁面,如果它的R位是0就淘汰該頁面,並且把新的頁面插入這個位置,然後錶針移動到下一個位置,如果R位是1就將R位置0並把錶針移動到下一個位置,重複這個過程直到找到一個R位是0的頁面然後淘汰。 時鐘頁面置換算法 最不常用算法:當發生缺頁中斷時,選擇訪問次數最少的那個頁面去淘汰。該算法可以給每個頁面設置一個計數器,被訪問時,該頁面的訪問計數器+1,在需要淘汰時,選擇計數器值最小的那個頁面。 這裏有個問題:一個頁面如果在開始的時候訪問次數很多,但之後就再也不用了,那它可能永遠都不會淘汰,但它又確實需要被淘汰,怎麼辦呢?可以定期把減少各個頁面計數器的值,常見的方法是定期將頁面計數器右移一位。 tips:最不常用算法(LFU)和最近最久未使用算法(LRU)的區別:LRU考察的是最久未訪問,時間越短越好,而LFU考察的是訪問的次數或頻度,訪問次數越多越好。 工作集頁面置換算法 介紹該算法時首先介紹下什麼是工作集。 工作集是指一個進程當前正在使用的頁面的集合,可以用二元函數W(t, s)表示: t表示當前的執行時刻)s表示工作集窗口,表示一個固定的時間段 W(t, s)表示在當前時刻t之前的s時間段中所有訪問頁面所組成的集合 不同時間下的工作集會有所變化,如圖: 進程開始執行後隨着訪問新頁面逐步建立較穩定的工作集 當內存訪問的局部性區域的位置大致穩定時(只訪問那幾個頁面 沒有大的改變時) 工作集大小也大致穩定 局部性區域的位置改變時(進程前一項事情做完 去做下一項事情時) 工作集快速擴張和快速收縮過渡到下一個穩定值 工作集置換算法主要就是換出不在工作集中的頁面,示例如圖: 第0次訪問e:缺頁,裝入e 第1次訪問d:缺頁,裝入d 第2次訪問a:缺頁,裝入a 第3次訪問c:缺頁,裝入c 第4次訪問c:命中,時間窗口【4px集運】,淘汰e 第5次訪問d:命中,時間窗口【4px集運】 第6次訪問b:缺頁,時間窗口【4px集運】,淘汰a,裝入b 第7次訪問c:命中,時間窗口【4px集運】 第8次訪問e:缺頁,時間窗口【4px集運】,裝入e 第9次訪問c:命中,時間窗口【4px集運】,淘汰d,裝入c 第10次訪問e:命中,時間窗口【4px集運】,淘汰b 第11次訪問a:缺頁,時間窗口【4px集運】,裝入a 第12次訪問d:缺頁,時間窗口【4px集運】,裝入d 工作集時鐘頁面置換算法 在工作集頁面置換算法中,當缺頁中斷髮生後,需要掃描整個頁表才能直到頁面的狀態,進而才能確定被淘汰的是哪個頁面,因此比較耗時,所以引入了工作集時鐘頁面算法。與時鐘算法改進了先進先出算法類似,工作集頁面置換算法+時鐘算法=工作集時鐘頁面置換算法。避免了每次缺頁中斷都需要掃描整個頁表的開銷。 0 8 什麼是分段內存管理? 關於分段內存管理我們平時見的最多的應該就是Linux可執行程序的代碼段數據段之類的啦,要了解分段最好的方式就是了解它的歷史。分段起源於8086CPU,那時候程序訪問內存還是直接給出相應單元的物理地址,為了方便多道程序併發執行,需要支持對各個程序進行重定位,如果不支持重定位,涉及到內存訪問的地方都需要將地址寫死,進而把某個程序加載到物理內存的固定區間。通過分段機制,程序中只需要使用段的相對地址,然後更改段的基址,就方便對程序進行重定位。而且8086CPU的地址線寬度是20位,可尋址範圍可以達到1MB,但是它們的寄存器都是16位,直接使用1個16位寄存器不可能訪存達到1MB,因此引入了段,引入了段寄存器,段寄存器左移4位+偏移量就可以生成20位的地址,從而達到1MB的尋址範圍。 以如今的科技水平,其實已經不再需要這種段移位加偏移的方式來訪存,分段更多的是一種歷史包袱,沒有多大實際作用,而且我們經常見到的可執行程序中代碼段數據段這些更多是為了在邏輯上能夠更清晰有序的構造程序的組織結構。Linux實際上沒有使用分段而只使用了分頁管理,這樣會更加簡單,現在的分段其實更多是為了使邏輯更加清晰。一個公司,為了方便管理都會劃分為好多個部門,這其實和分段邏輯相似,沒有什麼物理意義但是邏輯更加清晰。 關於操作系統的內存知識點就介紹到這裏,希望對大家有所幫助! 參考資料 //www.zhihu.com/question/50796850 //www.zhihu.com/question/63375062 //yuerer.com/操作系統之-虛擬存儲頁面置換算法/ 《現代操作系統》 《B站清華操作系統教學視頻》 《B站哈工大操作系統教學視頻》 ------------ END ------------ 關注

    時間:2020-12-22 關鍵詞: 嵌入式 內存

  • 讓數據實現更快更安全的傳輸,Rambus峯會展示業界領先接口和安全IP解決方案

    讓數據實現更快更安全的傳輸,Rambus峯會展示業界領先接口和安全IP解決方案

    科技發展一直在加速,隨着人工智能、5G和自動駕駛等演進,數據的生產節點數和吞吐量都在激增,節點激增同樣帶來數據安全轉換的需求增加。算力和數據傳輸能力都要一同演進才能保證終端應用滿足用户需求,但現在如何讓數據高效安全的傳輸已經成為了諸多應用升級的一個瓶頸。如何讓數據實現安全快速的傳輸是行業共同關心的話題,接口和安全IP的領先4px集運Rambus近期召開了峯會,向業界展示了其領先的接口和安全IP解決方案。 接口IP向更高速率演進 “從IP接口整體大趨勢來看,速度上向高速接口的方向發展。現在我們發現整個業界新推出的中速接口IP越來越少,低速的基本上沒有了,大家都把注意力放在高速接口IP上。“Rambus大中華區總經理 蘇雷先生分享到。從2012年到 2019年,人工智能訓練集增長了30萬倍,平均每3.43個月翻一番。人工智能和數據中心發展正在加速推動接口IP市場的發展。例如數據中心的主內存大約從明年開始將會逐漸從DDR4過渡到DDR5,最大容量提升了4倍左右。數據容量的提升也對內存系統提出更高的性能要求。高速內存控制器不斷出現,比如GDDR6、HBM、PCIe5等;各種支持小芯片互聯的技術也不斷的出現,比如用於並行傳輸的HBI,用於串行傳輸的SerDes等。   Rambus針對各種不同的傳輸協議都有相應的業界領先解決方案。例如在HBM方面,Rambus的HBM2E接口提供了最佳性能與最小面積的特點和高效率,可以達到業界最快4Gbps的速率,已經超越HBM2E DRAM 當前最高的3.6Gbps。而在GDDR6方面,Rambus的GDDR6接口每個引腳支持高達18 Gbps。這都是行業領先的水平。另外Rambus最新也推出了PCIe 5.0接口IP,該協議支持32Gbps的最高傳輸速率,非常適合AI、服務器、5G 基礎設施等應用。蘇雷表示,達到業界最頂峯水平可以幫客户的設計方案提供足夠裕量空間,保證整個系統的穩定性。   能夠達到行業頂尖的接口傳輸速率,得益於芯片工藝的演進,但更重要的是Rambus的團隊在對信號完整性和電源完整性方面有着深刻理解和豐富的專業知識積累。蘇雷先生表示,Rambus在過去的30年中積累了大量的這方面的經驗, 包括從建模到設計一整套的方法學,這些都是Rambus可以在接口IP領域保持領先的重要支撐,同時也是Rambus的核心優勢所在。另一個重要的優勢在於,Rambus的優勢在於並不僅僅是提供一些單品,而是可以提供基於接口IP的全套的解決方案。Rambus資深應用工程師曹汪洋先生分享到,這些方案都通過了完整的軟件仿真和硬件驗證。因此可以大大簡化用户設計的複雜度,用户在設計時不需要考慮不同4px集運IP之間的配合兼容的問題。 用硬件安全IP加速安全協議 在數據傳輸的安全方面,這首先是一個安全的問題,同時在保證安全的基礎上也還是是一個數據轉換速率的問題。物聯網、邊緣計算、V2X等等將會帶來越來越多的節點,需要大量的數據轉換;同時在數據中心和AI訓練中,也需要大量的數據在接口中心讀取和搬遷,所以數據安全性的問題變得愈發重要,而且如何快速地進行安全協議的轉換和確認也是影響系統整體性能的重要參數之一。   據Rambus資深現場工程師 張巖先生分享,雖然目前在不同的網絡層次的協議上都有對應的一些加密方案,但是如果單純使用軟件實現安全協議就沒法實現高速率。Rambus的方案,就是用硬件的安全IP去加速各種的安全協議。對於安全問題的共性在於對密鑰算法的要求和密鑰策略的要求以及傳輸協議的要求。也就是針對數據流轉性的保護,Rambus提出了一套叫做secure data in motion的概念,通過運用MACsec技術來保護流動數據。 針對靜態數據的保護(secure data at rest),Rambus有一個CryptoManager RoT(Root of Trust)的安全IP,可以在SoC中構建一個單獨的島式安全引擎。這個IP是一個單獨的RISC-V內核,專門用來進行數據加解密工作。這種保護不僅僅限於單獨密碼學的計算,也可以抵抗物理層面的攻擊,例如芯片側信道功耗分析攻擊、錯誤注入攻擊或者是剖片攻擊等。為什麼考慮使用RISC-V來構建這樣的安全IP呢?張巖先生分享到了一個在安全領域的設計原則叫作“clean sheet design”,即從一張白紙開始去做安全和構架設計。這樣從設計最初階段開始,繼承的過去的設計越少,越有可能更少地遇到原來歷史遺留的安全問題。   據蘇雷先生分享,Rambus此前曾收購了Verimatrix的安全IP團隊,再加上Rambus原有的安全團隊,現在可以實現業界非常全面的安全IP產品,並具備全球領先的安全IP研發實力,這將為客户在數據安全方面提供保駕護航。 --- 目前中國正在加緊進行5G、數據中心和人工智能等新基礎設施的建設,中國在全球高科技產業舞台上也在發揮着越來越重大的作用,這對 Rambus而言也孕育着巨大的接口IP的生意機會。蘇雷先生表示,Rambus非常看重中國的機會,將會和中國主要雲4px集運在內的更多雲服務商展開更密切的合作,同時也會和中國廣泛的OEM、ODM合作,打造整個內存產業生態系統內的一系列合作。

    時間:2020-12-21 關鍵詞: 數據 接口IP Rambus 內存

  • 英特爾正式發佈全新一代內存和存儲產品

    2020年12月16日,北京——在2020英特爾內存存儲日活動上,英特爾重磅發佈了六款全新內存和存儲產品,旨在幫助客户駕馭數字化轉型的重大機遇。 為進一步推動內存和存儲創新,英特爾宣佈推出兩款新的傲騰固態盤產品,即全球運行速度最快的數據中心固態盤英特爾®傲騰™固態盤P5800X,以及能夠為遊戲和內容創作提供高性能和主流生產力,面向客户端的英特爾®傲騰™H20混合式固態盤。通過使內存更靠近處理器,英特爾傲騰能夠滿足現代計算的需求。此外,英特爾還透露,即將面向雲和企業級用户發佈代號為“Crow Pass”的第三代英特爾®傲騰™持久內存。 英特爾數據平台事業部副總裁兼傲騰事業部總經理Alper Ilkbahar指出:“對於英特爾內存和存儲業務來説,今天是頗具里程碑意義的一天。隨着幾款全新傲騰產品的發佈,我們不僅延續創新,進一步強化了我們的內存和存儲產品組合,還將持續賦能客户更好地應對數字化轉型的複雜性。現階段,傲騰產品和技術正日益成為計算業務中的主流應用。而作為英特爾重要的組成部分,這些領先的內存和存儲產品將進一步推動包括AI、5G網絡、智能和自主邊緣計算等重點增長領域的長足發展。” 本次大會上,英特爾還宣佈推出三款採用144層存儲單元的全新NAND固態盤,包括適用於主流計算的英特爾下一代144層QLC 3D NAND固態盤——英特爾固態盤670p;全球首個推向市場的144層TLC NAND設計的英特爾固態盤D7-P5510;採用業內首個144層QLC NAND並具備更高密度、更強持久性的英特爾固態盤D5-P5316。 隨着當天傲騰技術的發佈,英特爾繼續在數據中心內存和存儲金字塔中構建融合了DRAM和NAND特性的新的層級。其中,英特爾傲騰固態盤通過高速緩存和高速存儲的性能,突破數據供應瓶頸並加速應用,提高每台服務器的性能可擴展性,並降低時延敏感型工作負載的交易成本。 英特爾傲騰持久內存是英特爾打造兼具持久性、大容量、經濟性、低延遲和近內存速度性能的內存和存儲解決方案願景的最好體現。通過傲騰持久內存,英特爾重構了內存和存儲層級,建立了以其為基礎的容量和性能都有所不同的內存和存儲層。這種方式同時使建立雙層內存架構成為可能,其中以DRAM作為性能層,持久內存作為容量層。而從存儲角度來看,傲騰持久內存可被用作基於NAND大容量存儲層之上的性能層。 同時,英特爾傲騰持久內存通過雙倍數據速率總線連接CPU,能夠以DRAM的速度直接進行加載和存儲訪問,同時它也兼具非易失性,融合了內存和存儲的最佳特性。 此外,英特爾將通過其代號為“Crow Pass”的第三代英特爾®傲騰持久內存和代號為Sapphire Rapids的英特爾®至強®可擴展處理器進一步增強和擴展其獨特的內存和存儲產品組合。 值得一提的是,當天發佈的三款全新NAND固態盤,代表着TLC和QLC作為大容量固態盤的主流技術正式邁入全新時代。其中,英特爾®3D NAND固態盤670p是用於主流計算的英特爾下一代144層(QLC)3D NAND固態盤。英特爾固態盤D7-P5510是全球首個推向市場的144層TLC NAND固態盤,而英特爾固態盤D5-P5316則是業內首個採用了144層QLC NAND的數據中心級固態盤。過去十餘年間,英特爾始終致力於推動和發展領先的內存和存儲技術。

    時間:2020-12-17 關鍵詞: 存儲 內存

  • 電腦內存有何作用?內存適用類型包含哪些?

    電腦內存有何作用?內存適用類型包含哪些?

    內存是重要器件之一,很多4px集運致力於生產高性能內存。但是,大家對電腦內存的作用真的瞭解嗎?如果你對內存作用存在疑惑,本文即可為您解惑。此外,本文還將對內存適用類型予以探討。小編相信,通過本文對內存的介紹,大家必定可以增進對內存的認識。那麼,和小編共同往下閲讀吧。 一、內存適用類型 根據內存條所應用的主機不同,內存產品也各自不同的特點。台式機內存是DIY市場內最為普遍的內存,價格也相對便宜。筆記本內存則對尺寸、穩定性、散熱性方面有一定的要求,價格要高於台式機內存。而應用於服務器的內存則對穩定性以及內存糾錯功能要求嚴格,同樣穩定性也是着重強調的。 台式機內存 筆記本內存就是應用於筆記本電腦的內存產品,筆記本內存只是使用的環境與台式機內存不同,在工作原理方面並沒有什麼區別。只是因為筆記本電腦對內存的穩定性、體積、散熱性方面的需求,筆記本內存在這幾方面要優於台式機內存,價格方面也要高於台式機內存。 筆記本內存 筆記本誕生於台式機的486年代,在那個時代的筆記本電腦,所採用的內存各不相同,各種品牌的機型使用的內存千奇百怪,甚至同一機型的不同批次也有不同的內存,規格極其複雜,有的機器甚至使用PCMICA閃存卡來做內存。進入到台式機的586時代,筆記本4px集運開始推廣72針的SO DIMM標準筆記本內存,而市場上還同時存在着多種規格的筆記本內存,諸如:72針5伏的FPM;72針5伏的EDO;72針3.3伏的FPM;72針3.3伏的EDO。此幾種類型的筆記本內存都已成為“古董”級的寶貝,早已在市場內消失了。在進入到“奔騰”時代,144針的3.3伏的EDO標準筆記本內存。在往後隨着台式機內存中SDRAM的普及,筆記本內存也出現了144針的SDRAM。現在DDR的筆記本內存也在市面中較為普遍了,而在一些輕薄筆記本內,還有些機型使用與普通機型不同的Micro DIMM接口內存。 對於多數的筆記本電腦都並沒有配備單獨的顯存,而是採用內存共享的形式,內存要同時負擔內存和顯存的存儲作用,因此內存對於筆記本電腦性能的影響很大。 服務器內存 服務器是企業信息系統的核心,因此對內存的可靠性非常敏感。服務器上運行着企業的關鍵業務,內存錯誤可能造成服務器錯誤並使數據永久丟失。因此服務器內存在可靠性方面的要求很高,所以服務器內存大多都帶有Buffer(緩存器),Register(寄存器),ECC(錯誤糾正代碼),以保證把錯誤發生可能性降到最低。服務器內存具有普通PC內存所不具備的高性能、高兼容性和高可靠性。 二、電腦內存外觀 可能大家看了以上關於內存含義的概述還是不怎麼了解內存是什麼,其實內存也是存儲器,只是內存不同於硬盤等存儲器,比一般的硬盤燈速度更快,採用的是閃存技術,不過內存上的數據在斷電後將全部清空,也就是説內存是隨機存儲,在計算機中開機狀態下內存最為CPU與外界數據交換的橋樑,所有諸如硬盤、主板上的數據均是通過內存與CPU進行數據交換的,一般來説內存越大,對數據交換越有利,因此速度也越快些。 其實我們只要知道內存就是暫時存儲程序以及數據交換的地方,不同於硬盤,當電腦關機內存斷點後,所有臨時存儲在內存的上的數據將全部清空,而保存在硬盤上的數據再次開機後還在,這主要是因為內存與硬盤採取的存儲技術不同,內存的優點是高速但數據需要一直通電才能保存,有興趣的朋友可以深入瞭解RAM與ROM數據讀取與存儲的關係。 三、電腦內存的作用 簡單的説內存在電腦中的作用相當於一座橋樑,用以負責諸如硬盤主板上的數據與處理器之間數據交換與處理器。所有電腦數據都是通過內存與處理器進行交換的,可能有的朋友會想為什麼數據不直接與處理器進行數據處理器與交換呢?其實大家只要瞭解內存就知道,內存的讀取速度與存儲速度是最快的,直接與主板上數據總線交換速度很慢,大家也可以將內存看作數據緩存區。 關於內存是什麼就為大家介紹到這裏,目前我們可以看到的內存均是2GB以上,內存已經發展到第3代也就是DDR3,預計2014年將上市第四代DDR4 內存。內存越大相應來説整機的速度就越快,但如果只是運行小程序,其實2G內存與8G內存是一樣的,所以通常內存越大越好只是相對的,如果不是電腦中運行大程序或同時開很多程序一般2GB內存足夠。 以上便是此次小編帶來的“內存”相關內容,通過本文,希望大家對內存適用類型具備一定的瞭解。如果你喜歡本文,不妨持續關注我們網站哦,小編將於後期帶來更多精彩內容。最後,十分感謝大家的閲讀,have a nice day!

    時間:2020-12-03 關鍵詞: 指數 電腦內存 內存

  • 高頻率內存有何優勢?虛擬內存又為何物?

    高頻率內存有何優勢?虛擬內存又為何物?

    我們每天都在同內存打交道,但大家對內存真的瞭解嗎?上篇文章中,我們對服務器內存以及服務器內存技術有所介紹,為增進大家對內存的認識,本文將為大家介紹高頻率內存的優勢。此外,小編還將對虛擬內存加以探討。如果你對內存及其相關知識具有興趣,不妨繼續往下閲讀哦。 一、高頻率內存優勢 由於決定內存性能的核心因素有內存容量、帶寬和頻率,而如果在同代內存,相同容量條件下,內存頻率越高,性能就越好。如果是不同代內存,比如DDR3和DDR4內存,如果是相同容量下,DDR4內存性能肯定在DDR3之上,畢竟DDR4內存頻率均在DDR3之上,加之新一代內存還在帶寬上有升級,功耗更低等。 關於內存和頻率的關係就介紹到這裏,簡單來説,頻率是決定內存性能的重要因素,不同代內存往往頻率都不同,在相同容量下,內存頻率越高,其性能往往更好。而在現實使用中,有適合不僅看理論,比如買的是DDR4 3000內存,但由於主板僅支持DDR4 2400,那麼DDR4 3000高頻內存只能識別到DDR4 2400,對於這部分用户來説,DDR4 3000由於電腦不能完全識別,顯得並不是特別合適,因此實際內存選擇時,還需要看實際需求與價格。 二、內存頻率是否越高越好 理論上來講,在同代相同容量內存中,內存頻率越高,速度就越快。也就是説,頻率是決定內存性能的一個非常重要的因素。 其實,電腦內存由第一代的DDR,發展到現在最想的DDR4,可以看到,越是最新的內存,頻率往往更高,通過內存頻率,我們有時候也基本可以判斷內存是第幾代的產品。 第一代DDR古董內存就不説了,下面主要從DDR3第二代內存説起: DDR2內存 頻率:333MHz/400MHz/667MHz/800MHz/1066MHz 工作電壓1.8V; DDR3內存 頻率:1066MHz、1333MHz、1600MHz、2133 工作電壓1.5V; DDR4內存:頻率:2133MHz、2400MHz、3000MHz、3200 工作電壓1.2V; 可以看到,越是新一代內存,頻率越高,並且工作電壓由於工藝的提升,電壓更低,功耗還更低。 三、虛擬內存 內存的一項主要任務,就是存儲進程的相關數據。我們之前已經看到過進程空間的程序段、全局數據、棧和堆,以及這些這些存儲結構在進程運行中所起到的關鍵作用。有趣的是,儘管進程和內存的關係如此緊密,但進程並不能直接訪問內存。在Linux下,進程不能直接讀寫內存中地址為0x1位置的數據。進程中能訪問的地址,只能是虛擬內存地址(virtual memory address)。操作系統會把虛擬內存地址翻譯成真實的內存地址。這種內存管理方式,稱為虛擬內存(virtual memory)。 每個進程都有自己的一套虛擬內存地址,用來給自己的進程空間編號。進程空間的數據同樣以字節為單位,依次增加。從功能上説,虛擬內存地址和物理內存地址類似,都是為數據提供位置索引。進程的虛擬內存地址相互獨立。因此,兩個進程空間可以有相同的虛擬內存地址,如0x10001000。虛擬內存地址和物理內存地址又有一定的對應關係,如圖1所示。對進程某個虛擬內存地址的操作,會被CPU翻譯成對某個具體內存地址的操作。 圖 虛擬內存地址和物理內存地址的對應 應用程序來説對物理內存地址一無所知。它只可能通過虛擬內存地址來進行數據讀寫。程序中表達的內存地址,也都是虛擬內存地址。進程對虛擬內存地址的操作,會被操作系統翻譯成對某個物理內存地址的操作。由於翻譯的過程由操作系統全權負責,所以應用程序可以在全過程中對物理內存地址一無所知。因此,C程序中表達的內存地址,都是虛擬內存地址。比如在C語言中,可以用下面指令來打印變量地址: intv = 0; printf("%p",(void*)&v); 本質上説,虛擬內存地址剝奪了應用程序自由訪問物理內存地址的權利。進程對物理內存的訪問,必須經過操作系統的審查。因此,掌握着內存對應關係的操作系統,也掌握了應用程序訪問內存的閘門。藉助虛擬內存地址,操作系統可以保障進程空間的獨立性。只要操作系統把兩個進程的進程空間對應到不同的內存區域,就讓兩個進程空間成為“老死不相往來”的兩個小王國。兩個進程就不可能相互篡改對方的數據,進程出錯的可能性就大為減少。 另一方面,有了虛擬內存地址,內存共享也變得簡單。操作系統可以把同一物理內存區域對應到多個進程空間。這樣,不需要任何的數據複製,多個進程就可以看到相同的數據。內核和共享庫的映射,就是通過這種方式進行的。每個進程空間中,最初一部分的虛擬內存地址,都對應到物理內存中預留給內核的空間。這樣,所有的進程就可以共享同一套內核數據。共享庫的情況也是類似。對於任何一個共享庫,計算機只需要往物理內存中加載一次,就可以通過操縱對應關係,來讓多個進程共同使用。IPO中的共享內存,也有賴於虛擬內存地址。 以上便是此次小編帶來的“內存”相關內容,通過本文,希望大家對高頻率內存的優勢、虛擬內存等知識具備一定的瞭解。如果你喜歡本文,不妨持續關注我們網站哦,小編將於後期帶來更多精彩內容。最後,十分感謝大家的閲讀,have a nice day!

    時間:2020-12-03 關鍵詞: 指數 虛擬內存 內存

  • 你知道服務器內存嗎??服務器內存有哪些技術?

    你知道服務器內存嗎??服務器內存有哪些技術?

    內存是電腦以及其它相關設備的重要組成,缺少內存,電腦的處理結果將無法保存。在往期文章中,小編對內存的基本知識有所介紹。為增進大家對內存的認識,本文將對服務器內存予以介紹。如果你對內存或者內存相關知識具有興趣,不妨繼續往下閲讀哦。 服務器內存也是內存(RAM),它與普通PC(個人電腦)機內存在外觀和結構上沒有什麼明顯實質性的區別,主要是在內存上引入了一些新的特有的技術,如ECC、ChipKill、熱插拔技術等,具有極高的穩定性和糾錯性能。 服務器內存主要技術: (1)ECC 在普通的內存上,常常使用一種技術,即Parity,同位檢查碼(Parity check codes)被廣泛地使用在偵錯碼(error detectioncodes)上,它們增加一個檢查位給每個資料的字元(或字節),並且能夠偵測到一個字符中所有奇(偶)同位的錯誤,但Parity有一個缺點,當計算機查到某個Byte有錯誤時,並不能確定錯誤在哪一個位,也就無法修正錯誤。基於上述情況,產生了一種新的內存糾錯技術,那就是ECC,ECC本身並不是一種內存型號,也不是一種內存專用技術,它是一種廣泛應用於各種領域的計算機指令中,是一種指令糾錯技術。ECC的英文全稱是“ Error Checking and Correcting”,對應的中文名稱就叫做“錯誤檢查和糾正”,從這個名稱我們就可以看出它的主要功能就是“發現並糾正錯誤”,它比奇偶校正技術更先進的方面主要在於它不僅能發現錯誤,而且能糾正這些錯誤,這些錯誤糾正之後計算機才能正確執行下面的任務,確保服務器的正常運行。之所以説它並不是一種內存型號,那是因為並不是一種影響內存結構和存儲速度的技術,它可以應用到不同的內存類型之中,就象前講到的“奇偶校正”內存,它也不是一種內存,最開始應用這種技術的是EDO內存,現在的SD也有應用,而ECC內存主要是從SD內存開始得到廣泛應用,而新的DDR、RDRAM也有相應的應用,目前主流的ECC內存其實是一種SD內存。 (2)Chipkill Chipkill技術是IBM公司為了解決目前服務器內存中ECC技術的不足而開發的,是一種新的ECC內存保護標準。我們知道ECC內存只能同時檢測和糾正單一比特錯誤,但如果同時檢測出兩個以上比特的數據有錯誤,則一般無能為力。目前ECC技術之所以在服務器內存中廣泛採用,一則是因為在這以前其它新的內存技術還不成熟,再則在目前的服務器中系統速度還是很高,在這種頻率上一般來説同時出現多比特錯誤的現象很少發生,正因為這樣才使得ECC技術得到了充分地認可和應用,使得ECC內存技術成為幾乎所有服務器上的內存標準。 但隨着基於Intel處理器架構的服務器的CPU性能在以幾何級的倍數提高,而硬盤驅動器的性能同期只提高了少數的倍數,因此為了獲得足夠的性能,服務器需要大量的內存來臨時保存CPU上需要讀取的數據,這樣大的數據訪問量就導致單一內存芯片上每次訪問時通常要提供4(32位)或8(64位)比特以上的數據,一次性讀取這麼多數據,出現多位數據錯誤的可能性會大大地提高,而ECC又不能糾正雙比特以上的錯誤,這樣就很可能造成全部比特數據的丟失,系統就很快崩潰了。IBM的Chipkill技術是利用內存的子結構方法來解決這一難題。內存子系統的設計原理是這樣的,單一芯片,無論數據寬度是多少,只對於一個給定的ECC識別碼,它的影響最多為一比特。舉個例子來説明的就是,如果使用4比特寬的DRAM,4比特中的每一位的奇偶性將分別組成不同的ECC識別碼,這個ECC識別碼是用單獨一個數據位來保存的,也就是説保存在不同的內存空間地址。因此,即使整個內存芯片出了故障,每個ECC識別碼也將最多出現一比特壞數據,而這種情況完全可以通過ECC邏輯修復,從而保證內存子系統的容錯性,保證了服務器在出現故障時,有強大的自我恢復能力。採用這種內存技術的內存可以同時檢查並修復4個錯誤數據位,服務器的可靠性和穩定得到了更加充分的保障。 (3)Register Register即寄存器或目錄寄存器,在內存上的作用我們可以把它理解成書的目錄,有了它,當內存接到讀寫指令時,會先檢索此目錄,然後再進行讀寫操作,這將大大提高服務器內存工作效率。帶有Register的內存一定帶Buffer(緩衝),並且目前能見到的Register內存也都具有ECC功能,其主要應用在中高端服務器及圖形工作站上,如IBM Netfinity 5000。 (4)FB-DIMM FB-DIMM(Fully Buffered-DIMM,全緩衝內存模組)是Intel在DDR2、DDR3的基礎上發展出來的一種新型內存模組與互聯架構,既可以搭配現在的DDR2內存芯片,也可以搭配未來的DDR3內存芯片。FB-DIMM可以極大地提升系統內存帶寬並且極大地增加內存最大容量。 FB-DIMM技術是Intel為了解決內存性能對系統整體性能的制約而發展出來的,在現有技術基礎上實現了跨越式的性能提升,同時成本也相對低廉。在整個計算機系統中,內存可謂是決定整機性能的關鍵因素,光有快的CPU,沒有好的內存系統與之配合,CPU性能再優秀也無從發揮。這種情況是由計算機原理所決定的,CPU在運算時所需要的數據都是從內存中獲取,如果內存系統無法及時給CPU供應數據,CPU不得不長時間處在一種等待狀態,硬件資源閒置,性能自然無從發揮。對於普通的個人電腦來説,由於是單處理器系統,目前的內存帶寬已經能滿足其性能需求;而對於多路的服務器來説,由於是多處理器系統,其對內存帶寬和內存容量是極度渴求的,傳統的內存技術已經無法滿足其需求了。這是因為目前的普通DIMM採用的是一種“短線連接”(Stub-bus)的拓撲結構,這種結構中,每個芯片與內存控制器的數據總線都有一個短小的線路相連,這樣會造成電阻抗的不繼續性,從而影響信號的穩定與完整,頻率越高或芯片數據越多,影響也就越大。雖然Rambus公司所推出的的XDR內存等新型內存技術具有極高的性能,但是卻存在着成本太高的問題,從而使其得不到普及。而FB-DIMM技術的出現就較好的解決了這個問題,既能提供更大的內存容量和較理想的內存帶寬,也能保持相對低廉的成本。FB-DIMM與XDR相比較,雖然性能不及全新架構的XDR,但成本卻比XDR要低廉得多。 與現有的普通DDR2內存相比,FB-DIMM技術具有極大的優勢:在內存頻率相同的情況下目前能提供四倍於普通內存的帶寬,並且能支持的最大內存容量也達到了普通內存的24倍,系統最大能支持192GB內存。FB-DIMM最大的特點就是採用已有的DDR2內存芯片(以後還將採用DDR3內存芯片),但它藉助內存PCB上的一個緩衝芯片AMB(Advanced Memory Buffer,高級內存緩衝)將並行數據轉換為串行數據流,並經由類似PCI Express的點對點高速串行總線將數據傳輸給處理器。 與普通的DIMM模塊技術相比,FB-DIMM與內存控制器之間的數據與命令傳輸不再是傳統設計的並行線路,而採用了類似於PCI-Express的串行接口多路並聯的設計,以串行的方式進行數據傳輸。在這種新型架構中,每個DIMM上的緩衝區是互相串聯的,之間是點對點的連接方式,數據會在經過第一個緩衝區後傳向下一個緩衝區,這樣,第一個緩衝區和內存控制器之間的連接阻抗就能始終保持穩定,從而有助於容量與頻率的提升。 服務器內存典型類型 目前服務器常用的內存有SDRAM和DDR,DDR2三種內存。 (1)SDRAM (2)DDR SDRAM (3)DDR2 SDRAM 以下是SDRAM和DDR SDRAM的對比圖表: 由於服務器內存在各種技術上相對兼容機來説要嚴格得多,它強調的不僅是內存的速度,而是它的內在糾錯技術能力和穩定性。所以在外頻上目前來説只能是緊跟兼容機或普通台式內存之後。目前台式機的外頻一般來説已到了150MHz以上的時代,但133外頻仍是主流。而服務器由於受到整個配件外頻和高穩定性的要求制約,主流外頻還是100MHz,但133MHz外頻已逐步在各檔次服務器中推行,在選購服務器時當然最好選擇133MHz外頻的了!內存、其它配件也一樣,要儘量同步進行,否則就會影響整個服務器的性能。目前主要的服務器內存品牌主要有Kingmax、kinghorse、現代、三星、kingstone、IBM、VIKING、NEC等,但主要以前面幾種在市面上較為常見,而且質量也能得到較好的保障。

    時間:2020-12-03 關鍵詞: 指數 服務器內存 內存

  • COMSOL® 全新發布5.6 版本,並推出四個新模塊

    COMSOL® 全新發布5.6 版本,並推出四個新模塊

    美國馬薩諸塞州,伯靈頓(2020 年 11 月 11 日)——業界領先的多物理場仿真、App 設計與部署的軟件解決方案提供商 COMSOL 公司發佈了全新的 COMSOL Multiphysics® 軟件 5.6 版本。新版本為多核和集羣計算提供了計算速度更快且內存需求更低的求解器、更加高效的 CAD 裝配處理功能、仿真 App 佈局模板,以及一系列包括剪裁平面、材料渲染和部分透明視圖等圖像功能。四個新模塊進一步擴展了 COMSOL Multiphysics 軟件的建模功能,用户可以更高效地處理燃料電池和電解槽、聚合物流動、控制系統和高精度流體問題。 使用“聚合物流動模塊”模擬狹縫式塗布過程。與其他流體分析類似,本案例也極大地受益於 COMSOL Multiphysics 5.6 版本的求解器性能改進。 運行速度更快、內存需求更低的求解器 在5.6 新版本中,求解器的性能得到了極大的改進,對於具有數百萬自由度的大型模型來説,性能提升的效果尤其顯著。“在 5.6 版本中,我們改進了代數多重網格和域分解求解器技術,基本上所有使用到這些求解器的模型都會受益,性能提升可高達 30%;集羣計算時,功能提升的效果更為明顯,運行時間和內存需求普遍達到 20%-50% 的改進。對於 CFD 分析,我們改進了速度-壓力耦合預條件器,並添加了全新的預條件器來解耦這些變量的更新。受益於以上這些改進,瞬態 CFD 模型的運行時間可降低近 50%。”COMSOL 開發團隊的求解器產品經理 Jacob Ystrom 評論道。在新版本中,針對一些黏彈性結構問題的分析速度提升了 10 倍之多;基於新的邊界元法算法,用户能夠處理汽車、聲吶等應用場景下更大規模的聲場分析。 採用的新邊界元算法 (BEM) 計算得到的潛艇目標強度結果。本案例計算了離潛艇 100 m 的水中,1.5 kHz 頻率的散射場聲壓級。 剪裁平面工具、幾何裝配處理功能提升和 App 佈局模板 利用剪裁平面工具,用户可以方便地選擇複雜 CAD 模型內部的邊界和域。此外,新增圖形功能還包括部分透明的視圖效果,以及利用導入圖像對結果可視化的功能。金屬等材料的渲染可以與結果的可視化混合,並具有環境反射效果,提供更真實的場景。新版本中,大型幾何裝配體的處理功能得到了改進,幾何實體的處理更加穩定,用户更容易檢測出裝配件之間的間隙和重疊。“App 開發器”中新增的 App 佈局模板可以快速而直觀地幫助用户創建佈局合理的用户界面。 COMSOL Multiphysics 5.6版本中的電機仿真案例,使用剪裁平面可以輕鬆訪問模型內部結構,為模型設定材料和載荷。 分析燃料電池與電解槽、聚合物流動、控制系統和流體屬性的新產品 新增的四個新模塊進一步擴展了 COMSOL Multiphysics 的建模功能,用户可以更加高效地模擬燃料電池和電解槽、聚合物流動、控制系統和流體混合物。 “燃料電池和電解槽模塊”為氫技術領域的工程師提供了研究電能轉換和存儲的新工具。COMSOL 公司電化學產品經理 Henrik Ekstrom 説道:“我們瞭解到氫經濟的發展潛力,以及理解和優化現有電解槽工藝的潛在需求。藉助這一新產品,我們可以為汽車、可再生能源、氫技術和電化學加工行業的用户提供最先進的建模仿真工具。”在5.6 版本中,之前的“電池與燃料電池模塊”保留原有功能,更名為“電池模塊”。當用户升級軟件到5.6版本時,原“電池與燃料電池模塊”將自動更新為“電池模塊”。 “聚合物流動模塊”可以用來模擬和優化聚合物、食品、製藥、化妝品、家居產品和精細化工行業中常常涉及到的黏彈性和非牛頓流體。除了提供先進的流變模型以外,該模塊還支持使用兩相流追蹤自由表面。 “氣液屬性模塊”用於計算氣體、液體和其混合物的屬性,為涉及到氣液混合物的聲學、流體和傳熱分析帶來更真實、準確的結果。 控制系統工程師可以使用 LiveLink™ for Simulink® 產品,在 COMSOL Multiphysics® 與 Simulink® 之間實現協同仿真。 使用“燃料電池和電解槽模塊”分析聚合物電解質膜水電解槽,圖中顯示的是氣體的體積分數。 疊片鐵芯、寄生電感、快速端口掃描和射線散射 “AC/DC 模塊”隨附的材料庫已使用 Bomatec 提供的 322 種磁性材料進行擴展,包含多種類型的永磁體(例如 NdFeB、SmCo 和 AlNiCo),材料數據中提供與電磁場和温度相關的材料屬性。新版本的“AC/DC 模塊”進一步提供了專門的工具來提取通過 L 矩陣計算的寄生電感,這對於印刷電路板設計來説至關重要;此外,5.6新版本還提供了新的非線性材料模型,用於模擬電機和變壓器中的疊片鐵芯損耗。 “RF 模塊”和“波動光學模塊”提供了一個用於端口掃描的新選項,針對全 S 參數、透射和反射係數矩陣提供更快的計算速度。對於超材料或等離子基元中的週期性結構,新版本為透射和反射波的計算和可視化提供了更便捷的極化圖工具。新版本中,“射線光學模塊”對射線追蹤的計算速度更快,還提供了專用工具,用於分析表面粗糙度引起的表面散射,以及體積域內由粒子引起的瑞利散射和米氏散射。 在毫米波 5G 頻段工作的級聯腔濾波器的熱-力耦合案例,圖中展示了部分透明的新視圖功能。 瞬態接觸、磨損和裂紋建模 新版本為“結構力學模塊”和“MEMS 模塊”的用户提供了機械接觸功能,可以用於模擬結構分析中的瞬態衝擊問題。“結構力學模塊”還為接觸分析提供了新工具,來分析涉及動態材料去除的機械磨損問題;新增的裂紋建模工具可以計算 J 積分和應力強度因子,並基於相場法模擬裂紋擴展。用户還可以在實體內部嵌入低維度單元,模擬類似於錨、鋼筋和金屬絲網的加強件。 “複合材料模塊”中用於分析多孔彈性效應的功能得到了擴展,可用於分析類似於層狀土壤、紙板、纖維增強塑料、層合板和夾層板等應用場景中的複合殼結構。 “MEMS 模塊”中,非線性多物理場材料模型中新增了鐵電彈性模型,可用於模擬壓電材料中如磁滯、極化飽和等非線性效應,此功能也可以通過將“AC/DC 模塊”與“結構力學模塊”或“聲學模塊”的耦合來實現。 高爾夫鐵桿擊打高爾夫球時的瞬態接觸仿真。 非線性聲學、機械端口和室內聲學分析 新版本中,“聲學模塊”的用户可以分析移動設備揚聲器中由熱黏性效應引起的失真問題,以及高強度超聲。針對超聲傳感和無損檢測中的超聲彈性波傳播問題,“結構力學模塊”、“聲學模塊”,以及“MEMS 模塊”中新增的機械端口工具,大大簡化了振動路徑和機械反饋分析的操作。射線聲學新增了室內聲學指標,包括混響時間、清晰度和明晰度,聲學工程師可以利用這些指標來改善房間和音樂廳的音質設計。 聲速和熱擾動的模擬結果顯示了壓力波與柵極結構相互作用而引起的渦脱落。這種類型的非線性熱黏性聲學效應在高保真移動設備揚聲器的分析中具有重要意義。 非等温多相流、淺水方程和表面熱輻射屬性 “CFD 模塊”和“傳熱模塊”新增了模擬分離型和分散型混合多相流的強大工具,用户可以輕鬆同時考慮自由表面和分散型多相流,例如,研究數百萬個衝破自由液麪的小氣泡等場景。新增的多相流非等温混合物模型接口可用於研究沸騰等相變現象。“多孔介質流模塊”和“傳熱模塊”中新增的多孔介質傳遞接口將水蒸氣的擴散和對流與液態水的對流與毛細流動相耦合,可用於處理濕度的兩相傳遞問題。“粒子追蹤模塊”新增了模擬液滴蒸發的新功能,這對於理解傳染病的傳播和一系列工業過程非常重要。 水文研究領域的用户將受益於“CFD 模塊”中新增的淺水方程模擬功能。淺水方程經常在海洋學和大氣應用中用來預測海嘯衝擊的影響、受污染、海岸侵蝕和極地冰蓋融化等。 “傳熱模塊”中“表面對錶面輻射”新增了與輻射入射方向相關的表面屬性設置,可用於更精確的模擬類似於太陽能板被動冷卻等應用中,表面對熱輻射方向敏感的問題。新的半透明表面功能可以指定外部輻射強度,可用於將玻璃表面設置為參與介質輻射區域的外部邊界,並能夠考慮表面擴散或鏡面透射後的入射強度。 腐蝕材料庫和自動反應配平 新版本中的“腐蝕模塊”新增的材料庫包括了 270 多種材料的極化曲線。“化學反應工程模塊”新增了用於計算化學計量係數的自動反應配平工具,以及三個預定義的用於幹空氣、濕空氣和水汽混合物的熱力學系統。“化學反應工程模塊”中新增的反應顆粒牀接口可通過定義催化劑顆粒內部非常小的孔隙的微觀尺度和顆粒之間較大孔隙的宏觀尺度(雙峯孔隙結構),對固定牀反應器進行多尺度建模。 兼容性 以下操作系統支持 COMSOL Multiphysics、COMSOL Server 和 COMSOL Compiler 軟件產品:Windows®、Linux® 和 macOS。Windows® 操作系統支持“App 開發器”工具。

    時間:2020-11-20 關鍵詞: COMSOL 求解器 內存

首頁  上一頁  1 2 3 4 5 6 7 8 9 10 下一頁 尾頁
發佈文章

技術子站

更多

項目外包