2017-11-25 262 views
4

我在這件事上聽到了矛盾的意見。有些人說,訪問堆中分配的數據(即std::vector或通過malloc分配的動態數組)總是比訪問堆棧中分配的數據稍微慢一些,因爲進程必須始終通過中間指針訪問該數據,這可能位於完全不同的記憶區域;另一方面,他們維護,訪問堆棧中分配的數據不需要通過這個中間指針,這些數據可能已經被緩存了。在堆上分配的數據比在堆棧上分配的數據要慢嗎?

其他人聲稱,堆上的數據分配比堆棧上的要慢(由於malloc,mmap和類似函數的開銷),但訪問不是,除了堆棧和堆的罕見情況位於不同的物理驅動器上。

是什麼事實?

+1

沒有道理。這取決於您的整個系統 - 代碼和硬件。在[NUMA機器]上更爲複雜(https://en.wikipedia.org/wiki/Non-uniform_memory_access)。如果您確實需要知道,請分析您的應用程序並進行測試。 –

+3

錯誤,堆棧和堆都不與物理驅動器相關聯。 –

+0

當內存訪問轉到'swap'(通常在物理驅動器上)時,您的代碼不再是'快速',既不堆棧也不堆棧。 –

回答

2

事實上(至少在最現代的cpus上)是堆棧和堆執行相同的操作,因爲它們都只是RAM的一部分。所以解引用指針幾乎是一樣的。

不同之處在於堆棧是爲您的進程/線程預分配的,因此您不需要使用mallocfree系統調用即可使用它。特別是malloc是昂貴的。另一個區別是可能有一些特定的CPU指令用於使用堆棧來提高性能(例如程序集的push,pop)。然而,這些不太可能與內存訪問有關(如將內存加載到寄存器)本身。

另一個區別是,如果你用完堆棧,你的程序將會(更可能)崩潰。雖然如果你用完堆,那麼你的操作系統可能會使用交換爲你降低性能成千上萬次。

緩存未命中當然是一個因素,它會更經常發生在堆上,然後在堆棧上。但是,這只是因爲與堆棧相比堆很大。但請注意,除非您編寫的代碼非常繁重,否則緩存未命中並不重要。

現在你是對的std::vector必須解除引用附加時間。但是這裏緩慢的是解引用,而不是堆棧或堆中的指針。它們在哪裏並不重要。雙引號總是比單引號慢。

現在棧和堆也可​​能位於不同的物理設備上。而且這兩款設備的速度不同(可能會使堆速更快)。但是這又與堆棧和堆本身無關。這可能發生在內存的任何兩個部分。而且你無法對此做任何事情。甚至沒有操作系統可以(可能,也可以,我不確定)。這是主板的事情。無論如何,主板很可能會爲更快的設備降頻。

0

有人說,在堆上分配訪問數據(即標準::載體或通過分配的malloc動態數組)總是略高於訪問堆棧上分配的數據速度較慢,因爲該過程必須總是通過一箇中間指針訪問那些可能位於完全不同的記憶區域的數據;另一方面,他們維護,訪問堆棧中分配的數據不需要通過這個中間指針,這些數據可能已經被緩存了。

這是牛糞便廢物。沒有中間指針寄存器,只能訪問靜態。通過寄存器(SP)訪問堆棧數據,其中一些處理器具有補充堆棧寄存器(例如,BP,AP)。

另外,內存是內存是內存。唯一認爲使內存成爲堆棧的是它作爲堆棧被訪問。

其他聲稱數據的唯一分配在堆上比堆(因爲malloc的,MMAP和類似功能的開銷)上慢,但訪問不是

這是正確的。在堆棧上分配數據只需要一條指令。