国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

malloc和內存池技術的區別 內存池技術性能優化方案

電子設計 ? 來源:面包板社區 ? 作者:一口Linux ? 2021-03-02 15:29 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

大家生活中肯定都有這樣的經驗,那就是大眾化的產品都比較便宜,但便宜的大眾產品就是一個詞,普通;而可以定制的產品一般都價位不凡,這種定制的產品注定不會在大眾中普及,因此定制產品就是一個詞,獨特。

有的同學可能會有疑問,你不是要聊技術嗎?怎么又說起消費了?

原來技術也有大眾貨以及定制品。

通用 VS 定制

作為程序員(C/C++)我們知道申請內存使用的是malloc,malloc其實就是一個通用的大眾貨,什么場景下都可以用,但是什么場景下都可以用就意味著什么場景下都不會有很高的性能。

malloc性能不高的原因一在于其沒有為特定場景做優化,除此之外還在于malloc看似簡單,但是其調用過程是很復雜的,一次malloc的調用過程可能需要經過操作系統的配合才能完成。 那么調用malloc時底層都發生了什么呢?簡單來說會有這樣典型的幾個步驟:

malloc開始搜索空閑內存塊,如果能找到一塊大小合適的就分配出去

如果malloc找不到一塊合適的空閑內存,那么調用brk等系統調用擴大堆區從而獲得更多的空閑內存

malloc調用brk后開始轉入內核態,此時操作系統中的虛擬內存系統開始工作,擴大進程的堆區,注意額外擴大的這一部分內存僅僅是虛擬內存,操作系統并沒有為此分配真正的物理內存

brk執行結束后返回到malloc,從內核態切換到用戶態,malloc找到一塊合適的空閑內存后返回

以上就是一次內存申請的完整過程,我們可以看到,一次內存申請過程其實是非常復雜的,關于這個問題的詳細討論你可以參考這里。 既然每次分配內存都要經過這么復雜的過程,那么如果程序大量使用malloc申請內存那么該程序注定無法獲得高性能。 幸好,除了大眾貨的malloc,我們還可以私人定制,也就是針對特定場景自己來維護內存申請和分配,這就是高性能高并發必備的內存池技術。

內存池技術有什么特殊的嗎? 有的同學可能會說,等等,那malloc和這里提到的內存池技術有什么區別呢? 第一個區別在于我們所說的malloc其實是標準庫的一部分,位于標準庫這一層;而內存池是應用程序的一部分。

其次在于定位,我們自己實現的malloc其實也是定位通用性的,通用性的內存分配器設計實現往往比較復雜,但是內存池技術就不一樣了,內存池技術專用于某個特定場景,以此優化程序性能,但內存池技術的通用性是很差的,在一種場景下有很高性能的內存池基本上沒有辦法在其它場景也能獲得高性能,甚至根本就不能用于其它場景,這就是內存池這種技術的定位。

那么內存池技術是怎樣優化性能的呢?

內存池技術原理 簡單來說,內存池技術一次性獲取到大塊內存,然后在其之上自己管理內存的申請和釋放,這樣就繞過了標準庫以及操作系統:

也就是說,通過內存池,一次內存的申請再也不用去繞一大圈了。 除此之外,我們可以根據特定的使用模式來進一步優化,比如在服務器端,每次用戶請求需要創建的對象可能就那幾種,那么這時我們就可以在自己的內存池上提前創建出這些對象,當業務邏輯需要時就從內存池中申請已經創建好的對象,使用完畢后還回內存池。 因此我們可以看到,這種為某些應用場景定制的內存池相比通用的比如malloc內存分配器會有大的優勢。 接下來我們就著手實現一個。

實現內存池的考慮 值得注意的是,內存池實際上有很多的實現方法,在這里我們還是以服務器端編程為例來說明。 假設你的服務器程序非常簡單,處理用戶請求時只使用一種對象(數據結構),那么最簡單的就是我們提前申請出一堆來,使用的時候拿出一個,使用完后還回去:

怎么樣,足夠簡單吧!這樣的內存池只能分配特定對象(數據結構),當然這樣的內存池需要自己維護哪些對象是已經被分配出去的,哪些是還沒有被使用的。 但是,在這里我們可以實現一個稍微復雜一些的,那就是可以申請不同大小的內存,而且由于是服務器端編程,那么一次用戶請求過程中我們只申請內存,只有當用戶請求處理完畢后一次性釋放所有內存,從而將內存申請釋放的開銷降低到最小。 因此,你可以看到,內存池的設計都是針對特定場景的。 現在,有了初步的設計,接下來就是細節了。

數據結構 為了能夠分配大小可變的對象,顯然我們需要管理空閑內存塊,我們可以用一個鏈表把所有內存塊鏈接起來,然后使用一個指針來記錄當前空閑內存塊的位置,如圖所示:

從圖中我們可以看到,有兩個空閑內存塊,空閑內存之間使用鏈表鏈接起來,每個內存塊都是前一個的2倍,也就是說,當內存池中的空閑內存不足以分配時我們就向malloc申請內存,只不過其大小是前一個的2倍:

其次,我們有一個指針free_ptr,指向接下來的空閑內存塊起始位置,當向內存池分配內存時找到free_ptr并判斷當前內存池剩余空閑是否足夠就可以了,有就分配出去并修改free_ptr,否則向malloc再次成倍申請內存。 從這里的設計可以看出,我們的內存池其實是不會提供類似free這樣的內存釋放函數的,如果要釋放內存,那么會一次性將整個內存池釋放掉,這一點和通用的內存分配器是不一樣。 現在,我們可以分配內存了,還有一個問題是所有內存池設計不得不考慮的,那就是線程安全,這個話題你可以參考這里。

線程安全 顯然,內存池不應該局限在單線程場景,那我們的內存池要怎樣實現線程安全呢? 有的同學可能會說這還不簡單,直接給內存池一把鎖保護就可以了。

這種方法是不是可行呢?還是那句話,It depends,要看情況。 如果你的程序有大量線程申請釋放內存,那么這種方案下鎖的競爭將會非常激烈,線程這樣的場景下使用該方案不會有很好的性能。 那么還有沒有一種更好的辦法嗎?答案是肯定的。

線程局部存儲 既然多線程使用線程池存在競爭問題,那么干脆我們為每個線程維護一個內存池就好了,這樣多線程間就不存在競爭問題了。 那么我們該怎樣為每個線程維護一個內存池呢? 線程局部存儲,Thread Local Storage正是用于解決這一類問題的,什么是線程局部存儲呢? 簡單說就是,我們可以創建一個全局變量,因此所有線程都可以使用該全局變量,但與此同時,我們將該全局變量聲明為線程私有存儲,那么這時雖然所有線程依然看似使用同一個全局變量,但該全局變量在每個線程中都有自己的副本,變量指向的值是線程私有的,相互之間不會干擾。

關于線程局部存儲,可以參考這里。 假設這個全局變量是一個整數,變量名字為global_value,初始值為100,那么當線程A將global_value修改為200時,線程B看到的global_value的值依然為100,只有線程A看到的global_value為200,這就是線程局部存儲的作用。

線程局部存儲+內存池 有了線程局部存儲問題就簡單了,我們可以將內存池聲明為線程局部存儲,這樣每個線程都只會操作屬于自己的內存池,這樣就再也不會有鎖競爭問題了。

注意,雖然這里給出了線程局部存儲的設計,但并不是說加鎖的方案就比不上線程局部存儲方案,還是那句話,一切要看使用場景,如果加鎖的方案夠用,那么我們就沒有必要絞盡腦汁的去用其它方案,因為加鎖的方案更簡單,代碼也更容易維護。 還需要提醒的是,這里只是給出了內存池的一種實現方法,并不是說所有內存池都要這么設計,內存池可以簡單也可復雜,一切要看實際場景,這一點也需要注意。

其它內存池形式 到目前為止我們給出了兩種內存池的設計方法,第一種是提前創建出一堆需要的對象(數據結構),自己維護好哪些對象(數據結構)可用哪些已被分配;第二種可以申請任意大小的內存空間,使用過程中只申請不釋放,最后一次性釋放。這兩種內存池天然適用于服務器端編程。 最后我們再來介紹一種內存池實現技術,這種內存池會提前申請出一大段內存,然后將這一大段內存切分為大小相同的小內存塊:

然后我們自己來維護這些被切分出來的小內存塊哪些是空閑的哪些是已經被分配的,比如我們可以使用棧這種數據結構,最初把所有空閑內存塊地址push到棧中,分配內存是就pop出來一個,用戶使用完畢后再push回棧里。

從這里的設計我們可以看出,這種內存池有一個限制,這個限制就是說程序申請的最大內存不能超過這里內存塊的大小,否則不足以裝下用戶數據,這需要我們對程序所涉及的業務非常了解才可以。 用戶申請到內存后根據需要將其塑造成特定對象(數據結構)。 關于線程安全的問題,可以同樣采用線程局部存儲的方式來實現:

一個有趣的問題 除了線程安全,這里還有一個非常有趣的問題,那就是如果線程A申請的對象被線程B拿去釋放,我們的內存池該怎么處理呢? 這個問題之所以有趣是因為我們必須知道該內存屬于哪個線程的局部存儲,但申請的內存本身并不能告訴你這樣的信息。 有的同學可能會說這還不簡單,不就是一個指針到另一個指針的映射嗎,直接用map之類存起來就好了,但問題并沒有這么簡單,原因就在于如果我們切分的內存塊很小,那么會存在大量內存塊,這就需要存儲大量的映射關系,有沒有辦法改進呢? 改進方法是這樣的,一般來說,我們申請到的大段內存其實是會按照特定大小進行內存對齊,我們假設總是按照4K字節對齊,那么該大段內存的起始地址后12個bit(4K = 2^12)為總是0,比如地址0x9abcd000,同時我們也假設申請到的大段內存大小也是4K:

那么我們就能知道該大段內存中的各個小內存塊起始地址除了后12個bit位外都是一樣的:

這樣拿到任意一個內存的地址我們就能知道對應的大段內存的起始地址,只需要簡單的將后12個bit置為0即可,有了大段內存的起始地址剩下的就簡單了,我們可以在大段內存中的最后保存對應的線程局部存儲信息:

這樣我們對任意一個內存塊地址進行簡單的位運算就可以得到對應的線程局部存儲信息,大大減少了維護映射信息對內存的占用。

總結 內存池是高性能服務器中常見的一種優化技術,在這里我們介紹了三種實現方法,值得注意的是,內存池實現沒有統一標準,一切都要根據具體場景定制,因此我們可以看到內存池設計是有針對性的,當然其反面就是不具備通用性。

編輯:hfy

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    9

    文章

    3209

    瀏覽量

    76357
  • 局部存儲
    +關注

    關注

    0

    文章

    2

    瀏覽量

    5508
  • malloc
    +關注

    關注

    0

    文章

    53

    瀏覽量

    383
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    曙光云發布“HME內存聚變技術

    了顛覆性解決方案——正式推出“HME內存聚變引擎”(Hyper-Memory Engine),以獨家軟件技術,打破傳統云架構中算力成本與DRAM內存容量的剛性捆綁。 這一
    的頭像 發表于 02-08 16:26 ?4.4w次閱讀

    C語言內存使用

    不必使用free函數,如果內存有空,那么直接放入內存。同樣的道理,下一次程序申請空間的時候,先檢查下內存池里面有沒有合適的
    發表于 12-11 07:57

    TDK和北海道大學聯合開發模擬儲備AI芯片原型

    隨著AI時代的到來,AI所需的海量運算處理和電力消耗等成為全球性課題。“儲備計算”作為解決方案之一而備受關注。與模仿大腦的萬能“神經形態設備”不同,“儲備計算”利用自然現象模仿小腦,因此可以實現
    的頭像 發表于 11-24 11:22 ?786次閱讀
    TDK和北海道大學聯合開發模擬儲備<b class='flag-5'>池</b>AI芯片原型

    為什么單片機中很少使用malloc,而PC程序頻繁使用呢?

    系統通常避免在性能關鍵的地方使用動態內存分配。 PC:由于PC系統的內存充足,并且操作系統對內存進行高度優化,動態
    發表于 11-20 06:55

    內存與數據處理優化藝術

    事務數量,更好地利用CPU緩存。測試表明,在處理大量數據(如20MB)時,這種優化可能帶來數倍的性能提升。
    發表于 11-14 07:46

    數據全復用高性能化層設計思路分享

    大家好,本團隊此次分享的內容為可實現數據全復用高性能化層設計思路,核心部分主要由以下3個部分組成; 1.SRAM讀取模塊;——化使用的存儲為SRAM 基于SRAM讀與寫時序,約束
    發表于 10-29 07:10

    rt_malloc_align函數內存越界問題怎么解決?

    ; } 代碼如上所示。 條件:align = 4,rt_malloc申請到的內存地址為0x2000001,sizeof(void*) = 4 結果: align_ptr = 0x2000004 則
    發表于 09-22 08:30

    科普:什么AI 內存技術

    AI 內存是一種專為人工智能 (AI) 應用設計的新型內存技術。與傳統的通用內存(如 DDR5 或 LPDDR5)不同,AI 內存的核心目標
    的頭像 發表于 09-03 15:44 ?1390次閱讀

    請問如何優化OpenVINO?工具套件中的內存使用?

    運行OpenVINO?推斷時找不到優化內存使用情況的方法。
    發表于 06-25 06:56

    鴻蒙5開發寶藏案例分享---瀑布流優化實戰分享

    * imgRatio + titleHeight + padding } 避免布局抖動 : 圖片異步加載時,高度不會撐開容器 三、性能對比實測(500條數據) 優化方案 內存占用
    發表于 06-12 17:41

    鴻蒙5開發寶藏案例分享---長列表性能優化解析

    ; 嵌套層級≤8層 性能監測工具 **: ** 用DevEco Studio的****Profiler檢測TTFD/內存/丟幀率 這次分享就到這里啦~鴻蒙的優化方案真的超實用!大家在開
    發表于 06-12 17:40

    HarmonyOS優化應用內存占用問題性能優化

    ,不同系統的閾值不同)時,系統可能會認為應用存在嚴重的內存問題,并可能會強制殺死該應用進程,以保證設備系統的穩定性和性能。為了避免應用被系統殺死,開發者可以考慮以下兩點: 優化資源使用:通過合理設置圖片
    發表于 05-24 17:20

    HarmonyOS優化應用內存占用問題性能優化

    應用開發過程中注重內存管理,積極采取措施來減少內存占用,以優化應用程序的性能和用戶體驗。 HarmonyOS提供了一些內存管理的工具和接口,
    發表于 05-21 11:27

    HBM新技術,橫空出世:引領內存芯片創新的新篇章

    隨著人工智能、高性能計算(HPC)以及數據中心等領域的快速發展,對內存帶寬和容量的需求日益增長。傳統的內存技術,如DDR和GDDR,已逐漸難以滿足這些新興應用對高
    的頭像 發表于 03-22 10:14 ?4881次閱讀
    HBM新<b class='flag-5'>技術</b>,橫空出世:引領<b class='flag-5'>內存</b>芯片創新的新篇章

    Get這個秘籍,鴻蒙原生應用頁面滑動絲滑無比

    內存占用增加,影響整體體驗。為了解決這一痛點,華為提供了一種基于動態預加載的方案,通過將LazyForEach+ImageKnife和Repeat+ImageKnife兩種技術組合,精準優化
    發表于 03-06 14:41