내 프로그램 코드에는 바이트 또는 2 ~ 16 자 정도의 매우 작은 다양한 객체가 있습니다. Vector2 (2 * T), Vector3 (3 * T), Vector4 (4 * T), ColourI32 (4), LightValue16 (2), Tile (2) 등 (괄호 안의 바이트 크기)C++ Small Object Performance
예상보다 느린 기능을하는 프로파일 링 (샘플 기반)을 수행하고있었습니다.
//4 bits per channel natural light and artificial RGB
class LightValue16
{
...
explicit LightValue16(uint16_t value);
LightValue16(const LightValueF &);
LightValue16(int r, int g, int b, int natural);
int natural()const;
void natural(int v);
int artificialRed()const;
...
uint16_t data;
};
...
LightValue16 World::getLight(const Vector3I &pos)
{ ... }
이 기능은 세계의 인구 부분 위의 몇 가지 기본 값으로, 배열의 몇 가지를 통해 값을 조회하는 몇 가지 수학을한다. 내용물은 멋지게 줄 지어 있으며 해체를 보는 것은 대략 100 가지의 지시 사항으로 얻을 수있는만큼 좋은 것으로 보입니다.
mov eax, dword pyt [ebp + 8]
mov cx, word ptr[ecx + edx * 2] ; or say mov ecx, Fh
mov word ptr [eax], cx
pop ebp
ret 10h
가 64 동안 나는 거의 같은 일을 보았다 그러나 한 점은 같은 구현 된 모든 반환 사이트에 띄었다. 내 GCC 빌드를 확인하지는 않았지만 같은 일을한다.
나는 약간의 실험을했으며 uint16_t 반환 유형을 사용하여 발견했습니다. 결과적으로 World :: getLight 함수가 인라인되어 (결과적으로 동일한 코어 80 인스트럭션 또는 조건부/루프가 다른 것 같이 보이지 않게 보임) 외부 함수에 대한 총 CPU 사용량이 16.87 %에서 14.04 % 내가 할 수있는 일은 케이스베이스별로 (내가 생각하는 인라인 인스트루먼트를 시도하는 것과 함께) 그런 성능 문제를 피하기위한 실용적인 방법이 있는가? 전체 코드에서 몇 % 더 빨라질 수도 있습니까?
제가 생각할 수있는 가장 좋은 점은이 경우 (< 4 또는 아마도 8 바이트 객체)의 기본 유형을 사용하고 현재 멤버를 비 멤버 함수로 옮기는 것입니다. C에서와 같이 , 네임 스페이스 만 있으면됩니다.
이것에 대해 생각해보십시오. "t foo (float x, float y, float z)"를 통해 "t foo (const Vector3F &p)"와 같은 물건을 만드는 데 드는 비용이 종종 있습니다. 그렇다면 const &을 광범위하게 사용하는 프로그램에서 상당한 차이가 날 수 있습니까?
: 당신이 명시 적, 복사 생성자를 원하는 상태로 원하는 당신이 C++ (11)를 사용하는 경우, 당신은 또한이 아닌 사소한하지 않습니다 채무 불이행 기능로 내려 쓸 수 있습니다 , 명시된 경우의 차이점은 관련된 모든 오버 헤드와 16 비트 부호없는 int를 반환하는 개체를 반환한다는 것입니다. 이전 버전에서는 int가 아닌 전체 객체를 복사해야했기 때문에 RVO가 작동하더라도 CPU 시간을 약간 더 소비해야합니다. –
힙이 아닌 스택에 객체를 할당하면이 상황에서 성능에 영향을 줍니까? –
Timo : 전체 개체가 왜 2 바이트 이상의 메모리를 차지합니까? 컴파일러는 vtable을 거기에 넣으면 안된다고 생각합니다. –