2014-12-04 84 views
1

我剛剛經歷了一堆堆疊VS堆在這裏的線程堆棧溢出的去(和其他隨機網站通過谷歌找到),但我無法找到提供太多的答案(如果有的話)對讀/寫速度問題的深度(大多數答案和文章側重於分配速度)。堆VS堆棧關於讀取/寫入速度

如果我正在寫一個C程序(在我的例子中是一個遊戲),我將對象數據存儲在一個幾KB的緩衝區中,如果它存在差異(就訪問速度而言)if該緩衝區是分配在堆棧上還是堆上?或者,當決定硬件(即高速緩存或RAM)的存儲位置時,編譯器是否會以相同的方式處理該大小的緩衝區?

+0

訪問RAM本質上是獨立的地址,並在你的進程的虛擬地址映射到一個隨機的,不可知的物理地址呢。比內存的特定位置更重要的是內存訪問模式中的緩存行爲。 (還有一個分配本身的同步成本,但你沒有問那個問題。) – 2014-12-04 10:52:08

+0

「內存訪問模式」是指將對象數據存儲爲數組的結構而不是結構數組(XXXYYYZZZ vs XYZXYZXYZ)? (編輯:啊沒關係我是個白癡,只是看着它 - 你的意思是我的程序訪問數據的方式......對吧?) – DudeMan2000 2014-12-04 11:03:47

+0

@ DudeMan2000數組和結構數組的結構不是一回事:)但是,是的,KerrekSB意味着你擡起頭來。如果你有一個1GB的字節數組,如果你從頭到尾循環訪問整個GB,或者訪問次序是隨機的,或者你訪問的是相同KB的1000000次,那麼這很重要。 – deviantfan 2014-12-04 11:13:14

回答

4

在一個典型的現代CPU和OS,不,我不希望在平均訪問時間任何區別,高速緩存未命中,或者(更糟糕)的基礎上的緩衝區是堆或棧頁面錯誤的可能性的可能性。與其他內存使用相比,唯一重要的是訪問它的模式。但是,可能存在嵌入式或專用平臺,其中堆棧保存在與堆不同的內存中。

您忽略了第三種可能性,即非堆內存(由某些OS特定的調用分配,如mmap而不是malloc)。

最後,如果你想徹底刪除頁面錯誤的可能性,操作系統可以提供一種方式來做到這一點;例如,POSIX上的mlock

+0

您可能想要添加一些關於訪問它的不同方法,例如通過指針,使用代碼相對地址(PIC)作爲來自堆棧指針的偏移量......這些可能對寄存器有不同的影響 - 壓力和訪問開銷,他們可能會使用不同的指令(或指令序列)。 – Deduplicator 2014-12-04 11:15:43

+0

不錯,謝謝!我沒有聽說過mmap,也沒有讀過關於頁面錯誤的文章,我會更多地關注這些。 – DudeMan2000 2014-12-04 11:15:55

2

訪問速度沒有區別,畢竟它的內存相同。編譯器決不會決定緩衝區應存儲在哪裏物理上。這是硬件和操作系統業務。

+0

真的嗎?我認爲編譯器會進行優化,如果您創建了一個局部變量並且該變量在釋放之前被使用了很多,那麼編譯器會將該變量分配給一個寄存器。編譯器是否僅使用寄存器進行調用,而所有非寄存器內存被編譯器視爲「虛擬內存」,並由操作系統和硬件管理? – DudeMan2000 2014-12-04 10:59:42

+0

@ DudeMan2000是的,編譯器可以做到這一點。但問題是關於緩衝區,而不是變量。編譯器不能滿足:「嗯。這是非常重要的緩衝區讓我們把它放到處理器的二級緩存「 – Ari0nhh 2014-12-04 11:01:46

+0

@ DudeMan2000簡化:幾乎所有的東西都必須從RAM加載到寄存器,當在處理器中使用,然後改變的值(如果有的話)必須是處理器的寄存器數量有限(不是所有必需的都適合),但是在RAM和寄存器之間的加載和存儲需要時間,編譯器可以做的是保留一塊最常用的變量的代碼在一段時間內沒有加載/卸載,但是這與RAM中的位置無關 – deviantfan 2014-12-04 11:05:53

2

根本沒有。 heap ad stack是操作系統向您的應用程序提供的虛擬地址空間中的區域。它們的區別在於你的應用程序在stack中存儲的內容以及heap中的內容。所有參考類型都存儲在heap中,所有值類型都存儲在stack中。此外,存儲在stack中的事物的生命週期與應用的生命週期持續時間相同,而存儲在heap中的類型可能會被垃圾回收,並且他們正在使用的內存將被回收。