我有一个简单的程序,它首先将一些 native x86 指令写入声明的缓冲区,然后设置一个指向该缓冲区的函数指针并进行调用。但是,当该缓冲区分配在堆栈上(而不是在堆上,甚至在全局数据区域中)时,我注意到严重的性能损失。我验证了数据缓冲区中指令序列的开始位于 16 字节边界上(我假设这是 cpu 需要(或希望)它是什么)。我不知道为什么在我的过程中执行指令会有所不同,但在下面的程序中,“GOOD”在我的双核工作站上执行 4 秒,“BAD”需要 6 分钟左右.这里是否存在某种对齐/i-cache/预测问题?我对 VTune 的评估许可证刚刚结束,所以我什至无法对此进行分析:(。谢谢。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int (*funcPtrType)(int, int);
int foo(int a, int b) { return a + b; }
void main()
{
// Instructions in buf are identical to what the compiler generated for "foo".
char buf[201] = {0x55,
0x8b, 0xec,
0x8b, 0x45, 0x08,
0x03, 0x45, 0x0c,
0x5D,
0xc3
};
int i;
funcPtrType ptr;
#ifdef GOOD
char* heapBuf = (char*)malloc(200);
printf("Addr of heap buf: %x\n", &heapBuf[0]);
memcpy(heapBuf, buf, 200);
ptr = (funcPtrType)(&heapBuf[0]);
#else // BAD
printf("Addr of local buf: %x\n", &buf[0]);
ptr = (funcPtrType)(&buf[0]);
#endif
for (i=0; i < 1000000000; i++)
ptr(1,2);
}
运行结果如下:
$ cl -DGOOD ne3.cpp
Microsoft (R) 32 位 C/C++ 优化编译器版本 11.00.7022 用于 80x86
版权所有 (C) Microsoft Corp 1984-1997。版权所有。
ne3.cpp
Microsoft (R) 32 位增量链接器版本 5.10.7303
版权所有 (C) Microsoft Corp 1992-1997。版权所有。
/out:ne3.exe
ne3.obj
$时间./ne3
堆缓冲区地址:410eb0
真实0m 4.33s
用户 0m 4.31s
系统 0m 0.01s
$
$
$ cl ne3.cpp
Microsoft (R) 32 位 C/C++ 优化编译器版本 11.00.7022 用于 80x86
版权所有 (C) Microsoft Corp 1984-1997。版权所有。
ne3.cpp
Microsoft (R) 32 位增量链接器版本 5.10.7303
版权所有 (C) Microsoft Corp 1992-1997。版权所有。
/out:ne3.exe
ne3.obj
$时间./ne3
本地 buf 地址:12feb0
真正的 6m41.19s
用户 6m40.46s
系统 0m 0.03s
$
谢谢。
最佳答案
堆栈保护以确保安全?
作为一个疯狂的猜测,您可能会遇到基于 MMU 的堆栈保护方案。许多安全漏洞是基于故意的缓冲区溢出,将可执行代码注入(inject)堆栈。解决这些问题的一种方法是使用不可执行的堆栈。这将导致进入操作系统的陷阱,我认为操作系统或某些病毒软件可能会做一些事情。
负 i-cache 一致性交互?
另一种可能性是同时使用对附近地址的代码和数据访问会破坏 CPU 缓存策略。我相信 x86 实现了一个本质上自动的代码/数据一致性模型,这很可能导致任何内存写入时附近的大量缓存指令失效。您无法通过将程序更改为不使用堆栈来真正解决此问题(显然您可以移动动态代码),因为堆栈始终由机器代码编写,例如,每当推送参数或返回地址时过程调用。
这些天 CPU 相对于 DRAM 甚至外层缓存环来说真的很快,所以任何破坏内层缓存环的事情都会非常严重,而且它的实现可能涉及 CPU 实现中的某种微陷阱,其次是硬件中的“循环”使事物无效。这不是英特尔或 AMD 会担心速度的事情,因为对于大多数程序来说,它永远不会发生,而且当它发生时,它通常只会在加载程序后发生一次。
关于执行存储在数据段中的 x86 指令的性能损失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1604160/