go二维map_mirrorlang——从0设计二维内存寻址语言及vm(五.内存管理的思考)
目錄
鵬鵬李李:mirrorlang——從0設計二維內存尋址語言及vm 【目錄】?zhuanlan.zhihu.com由一段函數開始思考內存布局
func longestPalindrome(s string)(r string) {if(len(s)==0){return s}//第一遍,尋找對稱點,復雜度為nhistory:=make(map[int]map[int]int)for i:=0;i<len(s)-1;i++{if(s[i]==s[i+1]){if(history[i]==nil){history[i]=make(map[int]int)}history[i][i+1]=2}if(i<len(s)-2&&s[i]==s[i+2]){if(history[i]==nil){history[i]=make(map[int]int)}history[i][i+2]=3}}//第二遍,擴展對稱點,計算長度maxc:=0maxi,maxj:=0,0for i,jc:=range history{for j,c:=range jc{m:=in:=jfor m>0&&n<len(s)-1{m--n++if(s[m]==s[n]){c+=2}else {m++n--break}}delete(history[i],j)if(history[m]==nil){history[m]=make(map[int]int)}history[m][n]=cif(c>maxc){maxc=cmaxi=mmaxj=n}}}return s[maxi:maxj+1] }我這里有一個go語言函數代碼,如果我用mirrorlang來在內存中布局這些函數,會出現什么問題呢?
mirrorlang如何為這樣的局部變量分配空間?
回答:
對于數組類型,數組在內存中的排布,是x軸反向橫向擴展的,由于代碼是向下執行的,所以橫向反而空間充足;
對于struct類型,結構是縱向布局的,也就是一個struct定義的成員數量是固定不變的;
所以golang map這個結構,是個
struct hmap{ cap len p* type }當我們定義一個map的時候,實際上會調用它的constructor函數,來進行內存初始化,也就是make()方法;
這個方法,并不是編譯的時候計算的,而是運行的時候計算;對于golang,通過逃逸分析來判斷map的實際內存分配是在堆還是在棧;
我們的內存,是二維的;
同樣需要思考,這局部變量(分子)如果需要的縱向空間越來越大,該從哪給它分配內存的問題;
先總結一些我制定的的幾個內存規則:
- 函數的執行流程,是自上而下的;
- 通常,已經被call的函數體,上下邊界是不會發生變化的;
- 數組的元素增加,是自左向右排列
- struct是自上而下排列,固定成員個數
如果像map那樣的struct里又有指針,指針指向的對象的空間分配,是我們需要計算的問題;
//例如,樹這樣的結構 type Node struct {Data []NodeValue int }它是可以無限遞歸套用自己;
如果一開始就給Data分配空間,它需要的縱向高度的公式為;
height()=1+height();這是無解的;
或者不給Data分配空間,而是把Data作為一個結構體指針 *struct,而這個height(Node)=2,這樣也可以;Node的高度就是2,也就是一個int原子和一個point原子,水平長度是1;、
另一種方法是,我們把它改成
//例如,樹這樣的結構 type Node struct {Data []*NodeValue int }這樣的話,Node的高度就是2,也就是一個int原子和一個point原子數組,水平長度是len(Data);
如果是其他語言的程序員,他可能會想讓內存更緊湊,這樣可以更節省內存;
但我并不這么想,我想做一個漂亮、適合人觀察的內存布局;就像寫在作業本上寫作業一樣,你不可能把每個格子都寫滿,如果寫滿每個格子,老師會批評你是不是窮的買不起作業本。
實際上,我希望把這個分子,在內存中的布局,也繪制成一顆漂亮的樹;這個也不難,可以通過計算坐標,讓內存的布局更美麗;就像下圖;
那么,還是那個問題;如何避免這種分子生長的過程中,出現內存碰撞?
方案1:
劃分出堆內存;
提供malloc或者new函數,這些函數是標準庫提供的,可以對這類分子生長的過程進行管理,預先劃定一個矩形,如果超出矩形,則copy并重新申請一個更大的矩形,并復制過去;
我們還需要設計原子的雙向指針,來保證互相連接的原子,當一個原子的坐標改變了內存坐標,能讓連接它的原子感知到并及時修改;
我覺得這是一個可行的方案;
但缺點在于,函數體內的局部變量分子,被放置在函數體外部的堆中了;
方案2:
不劃分堆區域;
依然是函數體矩形;
只是這個函數體的矩形,height和width都可以擴大;
定義分子的那一行,會隨著分子生長,把分子下部的所有矩形向下推,從而開辟出生長空間;
被推向下的內存中的原子,依然需要雙向指針,來保證改變了位置不會指針丟失;
這樣做的好處,是不需要把整個內存空間,劃分堆棧,維持函數體的完整性和獨立性;
雖然這樣的函數體具有完整性和獨立性,但缺點也很明顯;
當函數非常多,非常大的時候;需要下推的內存,會越來越大;這個問題要解決;
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的go二维map_mirrorlang——从0设计二维内存寻址语言及vm(五.内存管理的思考)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea中刷新项目快捷键_解决 IDEA
- 下一篇: jquery生成一个li_JQuery实