请考虑以下代码。
DoSomething1()在连续1000次执行中比DoSomething2()更快吗? 我假设如果我在哪里调用DoSomething1()它1000次,那么它会比调用DoSomething2()1000次更快。
将所有大缓冲区设为静态是否有任何不利之处?
#define MAX_BUFFER_LENGTH 1024*5
void DoSomething1()
{
static char buf[MAX_BUFFER_LENGTH] ;
memset( buf, 0, MAX_BUFFER_LENGTH );
}
void DoSomething2()
{
char buf[MAX_BUFFER_LENGTH] ;
memset( buf, 0, MAX_BUFFER_LENGTH );
}
感谢您的时间。
答案 0 :(得分:8)
静态缓冲区的缺点:
静态缓冲区的优点:
答案 1 :(得分:6)
如果在VC ++编译器中启用了/ GS,则堆栈分配会稍微贵一些,这样可以对缓冲区溢出进行安全检查(默认情况下/ GS处于打开状态)。真的,你应该分析这两个选项,看看哪个更快。静态内存中的缓存局部性与堆栈上的缓存局部性可能会产生差异。
这是非静态版本,VC ++编译器带有/ O2。
_main PROC ; COMDAT
; Line 5
mov eax, 5124 ; 00001404H
call __chkstk
mov eax, DWORD PTR ___security_cookie
xor eax, esp
mov DWORD PTR __$ArrayPad$[esp+5124], eax
; Line 7
push 5120 ; 00001400H
lea eax, DWORD PTR _buf$[esp+5128]
push 0
push eax
call _memset
; Line 9
mov ecx, DWORD PTR __$ArrayPad$[esp+5136]
movsx eax, BYTE PTR _buf$[esp+5139]
add esp, 12 ; 0000000cH
xor ecx, esp
call @__security_check_cookie@4
add esp, 5124 ; 00001404H
ret 0
_main ENDP
_TEXT ENDS
这是静态版本
; COMDAT _main
_TEXT SEGMENT
_main PROC ; COMDAT
; Line 7
push 5120 ; 00001400H
push 0
push OFFSET ?buf@?1??main@@9@4PADA
call _memset
; Line 8
movsx eax, BYTE PTR ?buf@?1??main@@9@4PADA+3
add esp, 12 ; 0000000cH
; Line 9
ret 0
_main ENDP
_TEXT ENDS
END
答案 2 :(得分:4)
两者之间几乎没有任何速度差异。在堆栈上分配缓冲区非常快 - 所有这一切都是将堆栈指针递减一个值。但是,如果在堆栈上分配一个非常大的缓冲区,则可能会溢出堆栈并导致段错误/访问冲突。相反,如果你有很多静态缓冲区,你会大大增加程序的工作集大小,但如果你有很好的引用位置,这会有所减轻。
另一个主要区别是堆栈缓冲区是线程安全的和可重入的,而静态缓冲区既不是线程安全的也不是可重入的。
答案 3 :(得分:2)
您还可以考虑将代码放入类中。例如。
之类的东西const MAX_BUFFER_LENGTH = 1024*5;
class DoSomethingEngine {
private:
char *buffer;
public:
DoSomethingEngine() {
buffer = new buffer[MAX_BUFFER_LENGTH];
}
virtual ~DoSomethingEngine() {
free(buffer);
}
void DoItNow() {
memset(buffer, 0, MAX_BUFFER_LENGTH);
...
}
}
如果每个胎面只分配自己的发动机,这是安全的。它避免了在堆栈上分配大量内存。堆上的分配是一个很小的开销,但如果您多次重用该类的实例,则这可以忽略不计。
答案 4 :(得分:2)
我是唯一一位从事多线程软件工作的人吗?在这种情况下,静态缓冲区是绝对禁止的,除非你想要承诺锁定和解锁的许多性能。
答案 5 :(得分:0)
正如其他人所说的堆栈分配非常快,对于更复杂的对象,例如ArrayList或HashTable(现在List<>和Dictionary<,>),每次不必重新分配的加速可能更大。通用世界)每次都有运行的构造代码,如果容量设置不正确,那么每次容器达到容量时都会有不必要的重新分配,并且必须分配新内存并将内容从旧内存复制到新内存。我经常有工作List<>我允许增长到任何大小的对象,我通过调用Clear()重用它们 - 这使得分配的内存/容量保持不变。但是,如果你的胭脂调用碰巧分配了大量内存,而这种内存不经常发生或只发生一次,你应该警惕内存泄漏。