Tôi đã đọc câu hỏi What's the performance penalty of weak_ptr? nhưng các bài kiểm tra của riêng tôi cho thấy các kết quả khác nhau.Tại sao gọi qua weak_ptr quá chậm?
Tôi đang làm đại biểu với con trỏ thông minh. Mã đơn giản dưới đây cho thấy tái tạo các vấn đề hiệu suất với weak_ptr
. Ai có thể cho tôi biết tại sao?
#include <chrono>
#include <functional>
#include <iostream>
#include <memory>
#include <stdint.h>
#include <string>
#include <utility>
struct Foo
{
Foo() : counter(0) { incrStep = 1;}
void bar()
{
counter += incrStep;
}
virtual ~Foo()
{
std::cout << "End " << counter << std::endl;
}
private:
uint64_t counter;
uint64_t incrStep;
};
void pf(const std::string &md, const std::function<void()> &g)
{
const auto st = std::chrono::high_resolution_clock::now();
g();
const auto ft = std::chrono::high_resolution_clock::now();
const auto del = std::chrono::duration_cast<std::chrono::milliseconds>(ft - st);
std::cout << md << " \t: \t" << del.count() << std::endl;
}
Và kiểm tra:
int main(int , char**)
{
volatile size_t l = 1000000000ULL;
size_t maxCounter = l;
auto a = std::make_shared<Foo>();
std::weak_ptr<Foo> wp = a;
pf("call via raw ptr ", [=](){
for (size_t i = 0; i < maxCounter; ++i)
{
auto p = a.get();
if (p)
{
p->bar();
}
}
});
pf("call via shared_ptr ", [=](){
for (size_t i = 0; i < maxCounter; ++i)
{
if (a)
{
a->bar();
}
}
});
pf("call via weak_ptr ", [=](){
std::shared_ptr<Foo> p;
for (size_t i = 0; i < maxCounter; ++i)
{
p = wp.lock();
if (p)
{
p->bar();
}
}
});
pf("call via shared_ptr copy", [=](){
volatile std::shared_ptr<Foo> p1 = a;
std::shared_ptr<Foo> p;
for (size_t i = 0; i < maxCounter; ++i)
{
p = const_cast<std::shared_ptr<Foo>& >(p1);
if (p)
{
p->bar();
}
}
});
pf("call via mem_fn ", [=](){
auto fff = std::mem_fn(&Foo::bar);
for (size_t i = 0; i < maxCounter; ++i)
{
fff(a.get());
}
});
return 0;
}
Kết quả:
$ ./test
call via raw ptr : 369
call via shared_ptr : 302
call via weak_ptr : 22663
call via shared_ptr copy : 2171
call via mem_fn : 2124
End 5000000000
Như bạn thấy, weak_ptr
là chậm hơn 10 lần so với shared_ptr
với việc sao chép và std::mem_fn
và 60 lần chậm hơn so với sử dụng nguyên ptr hoặc shared_ptr.get()
Bạn đã thử nghiệm một bản dựng được tối ưu hóa chưa? – TartanLlama
Có, tôi đang sử dụng g ++ -O3 -std = C++ 11 để xây dựng thử nghiệm của mình – user2807083
Một 'weak_ptr' cần phải thực hiện chuỗi an toàn của một' shared_ptr' ràng buộc của nó là chậm. Bạn chỉ nên sử dụng 'weak_ptr' khi bạn không biết liệu đối tượng được chia sẻ có bị hủy hay không. Nếu không, hãy sử dụng * con trỏ thô *. – Galik