Trong mã chương trình của tôi có nhiều đối tượng khá nhỏ khác nhau, từ một byte hoặc 2 tối đa khoảng 16. Ví dụ: Vector2 (2 * T), Vector3 (3 * T), Vector4 (4 * T), ColourI32 (4), LightValue16 (2), Ngói (2), vv (kích thước byte trong ngoặc).C++ Hiệu suất đối tượng nhỏ
Đã thực hiện một số hồ sơ (dựa trên mẫu) dẫn tôi đến một số hàm chậm hơn mong đợi, ví dụ:
//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)
{ ... }
Chức năng này thực hiện một số toán để tra cứu giá trị thông qua một vài mảng, với một số giá trị mặc định ở trên phần đông dân cư của thế giới. Các nội dung được inlined độc đáo và nhìn vào disassembly trông về tốt như nó có thể get.with khoảng 100 hướng dẫn. Tuy nhiên có một điều nổi bật, trên tất cả các trang web trở lại nó đã được thực hiện với một cái gì đó như:
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
Đối với x64 tôi thấy khá nhiều điều tương tự. Tôi đã không kiểm tra xây dựng GCC của tôi, nhưng tôi nghi ngờ nó thực hiện khá nhiều điều tương tự.
Tôi đã thử nghiệm và tìm thấy một chút bằng cách sử dụng loại trả về uint16_t. Nó thực sự dẫn đến chức năng getLight của World :: nhận được nội tuyến (trông giống như các lệnh 80 lõi tương tự hay như vậy, không có cheats với điều kiện/vòng lặp khác nhau) và tổng mức sử dụng CPU cho hàm bên ngoài mà tôi đang điều tra để đi từ 16,87 % đến 14.04% Trong khi tôi có thể làm điều đó trên cơ sở từng trường hợp (cùng với việc thử nội dung buộc nội tuyến tôi giả sử), có cách nào thực tế để tránh các vấn đề hiệu suất như vậy bắt đầu không? Có lẽ thậm chí còn nhận được một vài% nhanh hơn trên toàn bộ mã? Điều tốt nhất tôi có thể nghĩ chỉ là sử dụng các kiểu nguyên thủy trong các trường hợp như vậy (< 4 hoặc có thể là 8 byte) và di chuyển tất cả các thành phần hiện tại thành các hàm không phải thành viên, vì vậy giống như được thực hiện trong C , chỉ với các không gian tên.
Nghĩ về điều này, tôi đoán rằng đó cũng thường là một chi phí cho các công cụ như "t foo (const Vector3F & p)" trên "t foo (float x, float y, float z)"? Và nếu như vậy, trên một chương trình rộng rãi bằng cách sử dụng const &, nó có thể thêm đến một sự khác biệt đáng kể?
tốt , sự khác biệt trong trường hợp đã nêu của bạn là bạn đang trả về một đối tượng với tất cả các chi phí liên quan so với khi bạn trả về một int không dấu 16 bit. Cho rằng trước đây, bạn phải sao chép toàn bộ đối tượng hơn là chỉ int, tôi mong đợi rằng để tiêu thụ một chút thời gian CPU ngay cả khi RVO đi vào chơi. –
Có thể phân bổ đối tượng trong ngăn xếp thay vì đống, ảnh hưởng đến hiệu suất trong trường hợp này không? –
Timo: tại sao đối tượng đầy đủ sẽ mất hơn 2 byte bộ nhớ? Trình biên dịch không nên đặt một vtable trong đó, tôi sẽ nghĩ. –