我將一個項目從Visual C++ 6.0移植到VS 2010,發現代碼的一個關鍵部分(腳本引擎)現在運行速度比現在慢三倍左右之前。 經過一番研究,我設法提取了代碼片段,這似乎會導致放緩。我儘可能地減少了它,所以它很容易重現問題。 當分配包含另一個類(String)的複合類(Variant)和簡單類型的其他幾個字段的聯合時,會再現該問題。從VS 6.0移植到VS 2010的C++項目帶來了較慢的代碼
與示例玩,我發現更多的「魔術」: 1.如果我評論未使用的類成員之一,速度增加,並且代碼運行最後比那些VS 6.2 2.遵守更快(!)同樣是真實的,如果我刪除了「聯盟」包裝」 3.同樣是真實的事件,如果改變的申請從1到0
我不知道這到底是怎麼回事值。 我已籤所有代碼生成和優化開關,但沒有任何成功
代碼示例如下: On my In tel 2.53 GHz CPU這個測試,在VS 6.2下編譯運行1.0秒。 編譯根據VS 2010 - 40秒 編譯在VS 2010與「魔術」線評論 - 0.3秒。
問題是使用任何優化開關重現,但應該禁用「整體程序優化」(/ GL)。否則,這個太聰明的優化器會知道out test實際上什麼都不做,測試將運行0秒。
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class String
{
public:
char *ptr;
int size;
String() : ptr(NULL), size(0) {};
~String() {if (ptr != NULL) free(ptr);};
String& operator=(const String& str2);
};
String& String::operator=(const String& string2)
{
if (string2.ptr != NULL)
{
// This part is never called in our test:
ptr = (char *)realloc(ptr, string2.size + 1);
size = string2.size;
memcpy(ptr, string2.ptr, size + 1);
}
else if (ptr != NULL)
{
// This part is never called in our test:
free(ptr);
ptr = NULL;
size = 0;
}
return *this;
}
struct Date
{
unsigned short year;
unsigned char month;
unsigned char day;
unsigned char hour;
unsigned char minute;
unsigned char second;
unsigned char dayOfWeek;
};
class Variant
{
public:
int dataType;
String valStr; // If we comment this string, the speed is OK!
// if we drop the 'union' wrapper, the speed is OK!
union
{
__int64 valInteger;
// if we comment any of these fields, unused in out test, the speed is OK!
double valReal;
bool valBool;
Date valDate;
void *valObject;
};
Variant() : dataType(0) {};
};
void TestSpeed()
{
__int64 index;
Variant tempVal, tempVal2;
tempVal.dataType = 3;
tempVal.valInteger = 1; // If we comment this string, the speed is OK!
for (index = 0; index < 200000000; index++)
{
tempVal2 = tempVal;
}
}
int main(int argc, char* argv[])
{
int ticks;
char str[64];
ticks = GetTickCount();
TestSpeed();
sprintf(str, "%.*f", 1, (double)(GetTickCount() - ticks)/1000);
MessageBox(NULL, str, "", 0);
return 0;
}
蒂莫,感謝您的建議,我沒有朝這個方向搜索。 – 2012-03-03 17:00:46
現在我發現/ fp:strict選項也有幫助。 這非常奇怪,因爲我確定默認情況下通過簡單的字節分配複製了聯合。現在很明顯,情況並非總是如此。 但有一點我還不清楚:爲什麼取消「bool」和「String」成員可以解決問題?編譯器可能爲小型和大型結構生成不同的代碼? – 2012-03-03 17:15:03
@Boris L:是的,我不太瞭解編譯器的行爲,因爲它是如此的情景。直到我從聯合中刪除了'Date',並且刪除'bool'或'void *'沒有效果,我才真正解決了這個問題。 MS已確認它是一個錯誤(http://connect.microsoft。com/VisualStudio/feedback/details/238546 /錯誤代碼生成for-union-copy-assignment-in-visual-studio-2005-c-compiler)但爲什麼他們沒有修復它,因爲VC9或VC10超出了我。似乎在VC11工作。 – Timo 2012-03-04 03:09:29