日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[译]提案:在Go语言中增加对持久化内存的支持

發布時間:2024/4/11 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [译]提案:在Go语言中增加对持久化内存的支持 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:Jerrin Shaji George、Mohit Verma、Rajesh Venkatasubramanian、Pratap Subrahmanyam Jerrin Shaji George, Mohit Verma, Rajesh Venkatasubramanian, Pratap Subrahmanyam.

最后更新。2021年1月20日

討論地點:https://golang.org/issue/43810。

摘要

持久化存儲器是一種新的存儲器技術,其有接近DRAM的訪問速度,并提供類似磁盤的持久化。Linux和Windows服務器已經支持持久內存,服務器可用的商用硬件現在也已經推出了。關于這項技術的更多細節可以在pmem.io找到。

本文檔是為 Go 增加 pmem 支持的提案文檔,具體的詳細設計可以參考我們發表的2020年USENIX ATC論文[go-pmem](https://www.usenix.org/system/files/atc20-george.pdf)。基于Go 1.15版本的上述設計的實現,可以在以下網站找到此處。

背景

持久化存儲是一種新型的隨機存取存儲器,它提供了持久化的功能。并以類似DRAM的訪問速度實現尋址。操作系統提供了將該內存映射到應用程序的虛擬地址的能力。應用程序可以像使用內存一樣使用這個mmap區域。更新到持久化內存的數據,即使是崩潰/重啟后,這些數據依然能夠被正常使用。

使用持久化內存的應用程序在很多方面都有好處。由于數據更新到持久化內存是非易失性的,應用不再需要維護 DRAM 和存儲設備之間的數據關系,不需要在DRAM和存儲設備之間調配數據。相當一部分的應用程序代碼可以直接退役了。

另一個大的優勢是顯著減少了應用程序重新啟動時的啟動時間。這是因為應用程序不再需要把持久化的數據和內存中的數據進行轉換。商業應用SAP HANA給出的報告可以看到性能有 12 倍的提升:[12x improvement](https://cloud.google.com/blog/topics/partners/available-first-on-google-cloud-intel-optane-dc-persistent-memory)。

這個proposal是要為持久化內存提供原生支持,在Go語言中,我們的設計修改了Go 1.15,引入了一個垃圾收集的持久化的方法。我們還在 Go 編譯器中引入了新語義,以支持事務性更新到持久化內存數據結構。我們把我們修改后的Go套件稱為go-pmem。使用go-pmem開發的Redis數據庫與在NVMe SSD上運行的Redis相比,吞吐量提高了5倍。

提案

我們建議在Go中增加對持久化內存編程的本地支持。這需要在Go中提供以下功能。

  • 支持持久化的內存分配

  • 對持久化內存堆對象進行垃圾收集。

  • 修改持久化內存數據結構需要保證“崩潰時的一致性”

  • 使應用程序能夠在崩潰/重新啟動后恢復。

  • 支持應用程序從持久化內存中恢復存儲的數據。

  • 為了支持這些功能,我們擴展了Go運行時,并添加了一個新的SSA pass。我們的實現在后文中闡述。

    理由

    現在已經存在一些庫,如Intel PMDK,為C和C++開發人員提供了支持持久化內存編程的開發工具。其他編程語言,如Java和Python,正在探索如何支持。

    例如:

    • Java - https://bugs.openjdk.java.net/browse/JDK-8207851

    • Python - https://pynvm.readthedocs.io/en/v0.3.1/

    但是目前還沒有哪種語言原生地對持久化內存進行支持。我們認為這是對推廣pmem技術的一種障礙。這個提案就是要讓Go成為第一個原生完全支持持久化內存的語言。

    為什么要改變語言?

    C庫暴露了一個與現有編程模型明顯不同(而且復雜)的編程模型。內存管理對于一個語言的外部庫來說其實是很困難的。漏掉一個 "free "調用就會導致內存泄漏,而在持續化內存中,如果發生泄漏就是永久性的,不會在應用重新啟動后消失。在Go這樣有運行時的語言中,使本來只給垃圾收集管理的內存讓外部庫可見還是很困難的。為了能提供事務性的語義,需要對持久化內存的寫操作進行定制和組織,這也需要對語言進行修改。經過我們的實踐,對Go的編譯器和運行時進行增量修改還是比較容易的。

    兼容性

    我們目前的修改保留了Go 1.x未來兼容性的承諾。它做到了不會破壞不使用任何持久化內存功能的程序的兼容性。

    說到這里,我們承認我們目前的設計還存在一些缺點。

  • 我們將內存分配器元數據存儲在持久化內存中。當一個程序重新啟動,我們使用這些元數據來重新創建內存的程序狀態:分配器和垃圾收集器的相關狀態也包括在其中。與任何持久化數據一樣,我們需要維護這個元數據的數據布局。任何對Go內存分配器的數據結構修改都可能會破壞我們持久化的元數據。可以通過開發一個離線工具來解決這個問題。這樣我們可以將升級時的數據格式轉換功能嵌入到go-pmem中。

  • 目前我們增加了三個新的Go關鍵字:pnew, pmake和txn。持久化內存分配API和txn用來劃分事務性的數據結構的更新。我們已經探討了一些方法來避免下文所述的語言變化。

  • a) pnew/pmake

    在未來的Go版本中,對泛型的支持可以幫助我們避免引入這些內存分配函數。它們可以是普通的Go導出函數

    func?Pnew[T?any](_?T)?*T?{ptr?:=?runtime.pnew(T)return?ptr }func?Pmake[T?any](_?T,?len,?cap?int)?[]T?{slc?:=?runtime.pmake([]T,?len,?cap)return?slc }

    "runtime.pnew "和 "runtime.pmake "將是特殊的函數,可以取一個新的函數。類型作為參數。它們的行為與new()和make() 這兩個 API非常相似。不過它們是在持久化內存堆中分配對象的。

    b) txn

    一個替代的方案是定義一個新的Go規則,確定一個事務性的代碼塊。可以用如下語法:

    //go:transactional {//?transactional?data?updates }

    還有一種方法可以是使用閉包,并借助一些運行時和編譯器的變化。例如。

    runtime.Txn()?foo()

    這比較類似于Go編譯器在編譯期間存儲mrace/msan flag的做法。在這行代碼的情況下,foo會被事務性地執行。

    playground代碼 [code](https://go2goplay.golang.org/p/WRUTZ9dr5W3),展示了一個完整的代碼示例,以及我們建議的替代方案。

    Implementation

    我們的實現是基于Go 1.15版本的Go源代碼的fork。我們的實現為Go增加了三個新的關鍵字:pnew、pmake和txn。pnew和pmake是持久化的內存分配API,而txn是用來標志持久化內存事務塊。

  • pnew -?func pnew(Type) *Type

  • 就像new一樣,pnew也會創建一個Type參數的零值對象。并返回一個指向該對象的指針。

  • pmake -?func pmake(t Type, size ...IntType) Type

  • pmakeAPI用于在持久化內存中創建slice。語義pmake和Go中的make完全一樣。目前暫時不支持在 pmem 中創建 map 和 channel。

  • txn

  • txn()?{//?transaction?data?updates }

    我們對Go的代碼修改可以分為兩部分--運行時修改和編譯器-SSA修改。

    runtime 的變化

    我們擴展了Go的運行時以支持持久化的內存分配。垃圾收集器現在可以在持久堆和易失堆中工作。mspan?數據基礎架構有一個額外的數據成員 "memtype",用于區分持久化和易失性的span。我們還擴展了各種內存分配器在mcache、mcentral和mheap中的數據結構,將持久內存和易失性內存的元數據進行了區分。垃圾回收器現在就可以理解這些不同的span類型,并正確地根據memtype來進行不同的處理了。

    持久化內存是以64MB的倍數來管理的。每個持久化內存領域在其頭部分有一些元數據,這些元數據是為了方便在應用程序崩潰或重新啟動時恢復堆。這里會存儲兩種類型的元數據:

    • GC堆類型位 - 每個對象的 GC 堆類型 bit 都會被拷貝到 metadata 段以在程序后續的執行中繼續進行使用

    • Span表 - 捕獲該arena上每個span的元數據,以使程序在下次執行時,可以根據這些元數據重建堆

    我們在運行時包中添加了以下API來管理持久化內存。

  • func PmemInit(fname string) (unsafe.Pointer, error)。

  • 用于初始化持久化內存。它采用持久化內存文件的路徑作為輸入,返回應用程序的根指針和一個錯誤值。

  • func SetRoot(addr unsafe.Pointer) (err Error)。

  • 用于設置應用程序的根指針。所有應用程序的數據在持久化內存掛起這個根指針。

  • func GetRoot() (addr unsafe.Pointer)。

  • 返回使用SetRoot()設置的根指針。

  • func InPmem(addr unsafe.Pointer) bool。

  • 返回addr是否指向持久化內存中的數據。

  • func PersistRange(addr unsafe.Pointer, len uintptr)。

  • 刷新地址范圍(addr,addr+len)內的所有緩存,以確保任何更新到這個內存范圍的數據都會被持久存儲。

    編譯器-SSA變化

  • 修改parser以識別三個新的token--pnew,pmake,和txn。

  • 我們增加一個新的SSA pass,將所有的存儲操作都寫入到持久化內存。因為持久化內存中的數據可以在崩潰后存活,所以更新持久化內存中的數據必須是事務性的。

  • 對Go AST和SSA進行了修改,現在用戶可以將通過將一個塊封裝在txn()塊中,將這段Go代碼作為事務性代碼。

    • 為了做到這一點,我們在Go中添加了一個名為txn的新關鍵字。

    • 然后,一個新的SSA pass將尋找 txn 塊中所有對持久化內存地址的store(OpStore/OpMove/OpZero)操作,并將這些操作的老數據存儲在?撤銷日志中。該操作將在進行實際的內存更新之前完成。

    go-pmem packages

    我們開發了兩個包,使go-pmem的編寫持久化存儲器的應用更容易。

  • pmem包

  • 它提供了一個簡單的Init(fname string) bool?API,應用程序可以用它來實現初始化持久化內存。函數返回結果表示是不是第一次初始化,如果是則返回 true。如果不是的話,未完成的事務都會被 revert。

    pmem包還提供了命名對象,這些名字可以和持久化內存中的對象關聯起來。用戶可以字符串名字來創建和獲取這些對象。

  • transaction包

  • 事務包提供了撤消日志記錄的實現,這些日志記錄用于支持程序的崩潰后恢復,保證崩潰時的一致性。

    Example Code

    下面是一個使用go-pmem編寫的簡單的鏈表應用程序。

    //?一個簡單的鏈接列表應用程序。在第一次調用時,它會創建一個 //?命名為?"dbRoot?"的持久化內存指針,它持有指向第一個 //?也是鏈接列表中的最后一個元素。每次運行時,一個新的節點都會被添加 //?鏈接的列表和列表的所有內容都被打印出來。package?mainimport?("github.com/vmware/go-pmem-transaction/pmem""github.com/vmware/go-pmem-transaction/transaction" )const?(//?Used?to?identify?a?successful?initialization?of?the?root?objectmagic?=?0x1B2E8BFF7BFBD154 )//?Structure?of?each?node?in?the?linked?list type?entry?struct?{id???intnext?*entry }//?The?root?object?that?stores?pointers?to?the?elements?in?the?linked?list type?root?struct?{magic?inthead??*entrytail??*entry }//?A?function?that?populates?the?contents?of?the?root?object?transactionally func?populateRoot(rptr?*root)?{txn()?{rptr.magic?=?magicrptr.head?=?nilrptr.tail?=?nil} }//?Adds?a?node?to?the?linked?list?and?updates?the?tail?(and?head?if?empty) func?addNode(rptr?*root)?{entry?:=?pnew(entry)txn()?{entry.id?=?rand.Intn(100)if?rptr.head?==?nil?{rptr.head?=?entry}?else?{rptr.tail.next?=?entry}rptr.tail?=?entry} }func?main()?{firstInit?:=?pmem.Init("database")var?rptr?*rootif?firstInit?{//?Create?a?new?named?object?called?dbRoot?and?point?it?to?rptrrptr?=?(*root)(pmem.New("dbRoot",?rptr))populateRoot(rptr)}?else?{//?Retrieve?the?named?object?dbRootrptr?=?(*root)(pmem.Get("dbRoot",?rptr))if?rptr.magic?!=?magic?{//?An?object?named?dbRoot?exists,?but?its?initialization?did?not//?complete?previously.populateRoot(rptr)}}addNode(rptr)????//?Add?a?new?node?in?the?linked?list }

    總結

    以上是生活随笔為你收集整理的[译]提案:在Go语言中增加对持久化内存的支持的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲ⅴ国产v天堂a无码二区 | 亚洲天堂av一区二区三区 | 精品黄色| 污视频网站免费看 | 97超在线| 欧美性受视频 | 小蝌蚪av | 嫩草影院在线观看视频 | 久久99亚洲精品 | 国产成人无码专区 | 国产特级淫片免费看 | 日韩videos| 欧美日韩在线视频免费观看 | 国产成人午夜精华液 | 亚洲欧美一级 | 国产毛片视频网站 | 区一区二在线观看 | 久久99久久99精品免观看粉嫩 | 91精品视频免费在线观看 | 99热超碰 | 亚洲精品视频一二三区 | 日韩高清网站 | 日韩网站视频 | 亚洲88av| 欧美视频在线观看一区 | 日本黄色视 | 日韩免费小视频 | 91精品在线视频观看 | 少妇饥渴放荡91麻豆 | 久久久久久久久久久久久久久久久 | 亚洲永久无码7777kkk | 国产伦精品一区二区三区照片 | 91精品人妻一区二区三区 | av在线播放地址 | 中文字幕亚洲乱码熟女一区二区 | 四虎国产在线观看 | 久久看片 | 亚洲第一页色 | 成人免费福利视频 | 女同在线视频 | 欧美黄色特级片 | 欧美乱日 | 欧美在线v | 草草影院国产 | 91视频看 | 最好看的2019年中文视频 | 老妇高潮潮喷到猛进猛出 | 九九操| 精品成人av一区二区三区 | 成年人免费网站在线观看 | 黄色国产在线播放 | 高清一区二区视频 | 九色.com| 欧美在线免费 | 国产精品后入内射日本在线观看 | 欧洲一区二区三区 | 午夜精品视频一区 | 97超碰碰 | 国产主播av在线 | 国产精品美女自拍视频 | 91美女视频网站 | 国产精品久久久久久久久久久久久 | 丁香六月色婷婷 | 色香蕉av| 在线免费激情视频 | 欧美日韩一区二区视频观看 | 亚洲女优在线 | 97精品视频在线 | 少妇一级淫免费放 | 女人色极品影院 | 97超碰资源总站 | 欧美偷拍少妇精品一区 | 成年男女免费视频 | 亚欧av在线 | 淫品色影院 | 五月婷视频 | 97福利社| v天堂中文在线 | aaa久久| 国产欧美一区二区三区在线看蜜臀 | 插吧插吧综合网 | 国产精品麻豆一区二区 | 中文字幕在线看高清电影 | 欧美在线影院 | 夜夜嗨av禁果av粉嫩avhd | 精品国内自产拍在线观看视频 | 男女激情大尺度做爰视频 | av男人的天堂在线观看 | 亚洲成人手机在线 | 中文字幕日韩欧美 | 一级片免费在线播放 | 屁股夹体温计调教play | 中文字幕观看 | 人妻在线一区二区三区 | 性色av蜜臀av色欲av | 亚州av网站 | 色呦呦中文字幕 | 色综合日韩 | 丰满熟女人妻一区二区三区 |