Tôi gặp phải hành vi không mong muốn về hiệu suất của mã sử dụng hàng đợi. Tôi nhận ra rằng hiệu suất bị suy giảm khi có nhiều phần tử hơn trong hàng đợi. Hóa ra việc sử dụng phương pháp size()
là lý do. Dưới đây là một số mã cho thấy sự cố:std :: queue <T, list<T>> :: size() chậm trong O (n)?
#include <queue>
#include <list>
#include <iostream>
#include "Stopwatch.h"
using namespace std;
struct BigStruct
{
int x[100];
};
int main()
{
CStopwatch queueTestSw;
typedef BigStruct QueueElementType;
typedef std::queue<QueueElementType, std::list<QueueElementType> > QueueType;
//typedef std::queue<QueueElementType > QueueType; //no surprise, this queue is fast and constant
QueueType m_queue;
for (int i=0;i<22000;i++)
m_queue.push(QueueElementType());
CStopwatch sw;
sw.Start();
int dummy;
while (!m_queue.empty())
{
//remove 1000 elements:
for (int i=0;i<1000;i++)
{
m_queue.pop();
}
//call size() 1000 times and see how long it takes
sw = CStopwatch();
sw.Start();
for (int i=0;i<1000;i++)
{
if (m_queue.size() == 123456)
{
dummy++;
}
}
std::cout << m_queue.size() << " items left. time: " << sw.GetElapsedTimeInSeconds() << std::endl;
}
return dummy;
}
Trường hợp CStopwatch
là một lớp sử dụng clock_gettime(CLOCK_REALTIME, ..)
. Kết quả là:
21000 items left. time: 1.08725
20000 items left. time: 0.968897
19000 items left. time: 0.818259
18000 items left. time: 0.71495
17000 items left. time: 0.583725
16000 items left. time: 0.497451
15000 items left. time: 0.422712
14000 items left. time: 0.352949
13000 items left. time: 0.30133
12000 items left. time: 0.227588
11000 items left. time: 0.178617
10000 items left. time: 0.124512
9000 items left. time: 0.0893425
8000 items left. time: 0.0639174
7000 items left. time: 0.0476441
6000 items left. time: 0.033177
5000 items left. time: 0.0276136
4000 items left. time: 0.022112
3000 items left. time: 0.0163013
2000 items left. time: 0.0101932
1000 items left. time: 0.00506138
Điều này có vẻ như mâu thuẫn với http://www.cplusplus.com/reference/stl/queue/size/:
phức tạp: Constant.
Vấn đề còn tệ hơn nếu cấu trúc lớn hơn. Tôi đang sử dụng GCC 4.3.2.
Bạn có thể giải thích điều này không? Có cách nào để giải quyết điều này bằng cách sử dụng danh sách?
(. Xin lưu ý rằng tôi cần phải sử dụng danh sách như container nằm bên dưới của hàng đợi bởi vì tôi cần liên tục phức tạp chèn thời gian)
cplusplus.com không có lỗi. –
@ BjörnPollex: cppreference cũng nói như vậy. Vấn đề là 'hàng đợi' là một lớp bộ điều hợp. –
Mặt khác, đề xuất O (1) cho phép kích thước trên bất kỳ vùng chứa nào (kể cả danh sách) có thể thu được bằng cách theo dõi kích thước trong danh sách. –