【发布时间】:2018-08-15 09:20:38
【问题描述】:
我运行了一些测试来验证我对构造函数速度的先入为主的想法,但结果与我的预期大不相同。难道我做错了什么?我错过了什么? 我正在使用没有优化的 MVS 2015(但结果始终相同并不重要)。
class Person
{ using ushort = unsigned short;
string name_;
ushort age_;
public:
explicit Person(const string &name, ushort age) //1
{ name_ = name;
age_ = age;
}
explicit Person(const string &name,ushort age) : name_{name},age_{age} //2
{
}
explicit Person(string name, ushort age) : name_{ std::move(name) }, age_{ age } //3
{
}
};
//1 - 总是比其他 ctor 快。
//2 - 比 1 稍慢(可以忽略!!)。???
//3 - 比 1 多花 50% 的时间。???
我使用小字符串(8 字节)、1K、2K 字符串大小运行测试。 我期待 //2 ctor 是最快的,没想到 //3 花了这么多时间。 最后一个问题,我在 //3 ctor 中所做的事情是否合法?
更新 这是我写的代码
class Person
{
using ushort = unsigned short;
private:
std::string name_;
ushort age_;
public:
static constexpr size_t nr_ctors = 3;
static const char * const ctor_signature[nr_ctors];
enum class CTOR_1
{ CTOR = 0
};
enum class CTOR_2
{ CTOR = 1
};
enum class CTOR_3
{ CTOR = 2
};
explicit Person(const std::string &name, ushort age,CTOR_1)
{ name_ = name;
age_ = age;
}
explicit Person(const std::string &name, ushort age, CTOR_2) : name_{name},age_{age}
{}
explicit Person(std::string name,ushort age,CTOR_3) : name_{std::move(name)},age_{age}
{}
};
const char * const Person::ctor_signature[Person::nr_ctors] = {"\nexplicit Person(const std::string &name, ushort age,CTOR_1)",
"\nexplicit Person(const std::string &name, ushort age, CTOR_2) : name_{name},age_{age}",
"\nexplicit Person(std::string name,ushort age,CTOR_3) : name_{std::move(name)},age_{age}"};
using mclock = std::chrono::high_resolution_clock;
using time_p_t = std::chrono::time_point<mclock>;
using precision_t = std::chrono::nanoseconds;
#define NR_ITERATIONS (128 * 1024)
template <typename Ty_>
precision_t time_no_heap(const std::string &name)
{
time_p_t t_0;
time_p_t t_1;
t_0 = mclock::now();
Person p = Person{name,66,Ty_::CTOR};
t_1 = mclock::now();
return t_1 - t_0;
}
template <typename Ty_>
precision_t time_with_heap(const std::string &name)
{
time_p_t t_0;
time_p_t t_1;
Person *p_person;
t_0 = mclock::now();
p_person = new Person{ name,66,Ty_::CTOR };
t_1 = mclock::now();
delete p_person;
return t_1 - t_0;
}
void print_statistics(int iterations, size_t str_size, const precision_t(&stats)[2][Person::nr_ctors])
{
std::cout << "\nTotal iterations : "
<< iterations
<< "\nString ize : "
<< str_size
<< std::endl;
for (int i = 0; i < Person::nr_ctors; ++i)
{ std::cout << Person::ctor_signature[i]
<< "\n\t Stack (ms) : "
<< std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(stats[0][i]).count()
<< "\n\t Heap (ms) : "
<< std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(stats[1][i]).count()
<< std::endl;
}
}
int main(int argc, const char *argv[])
{
int iterations;
std::string *p_name;
if (argc != 3 && argc != 1)
{ std::cout << "USAGE [<iterations>K <string size>]" << std::endl;
return -1;
}
else if (argc == 3)
{ iterations = std::atoi(argv[1]) * 1024;
p_name = new std::string(std::atoi(argv[2]), 'x');
}
else
{ iterations = NR_ITERATIONS;
p_name = new std::string{ "Benchmark" };
}
precision_t benchmark [2][Person::nr_ctors]{};
std::cout << "\nUsing string : " << *p_name << ".\nIterating : " << iterations << " times." << std::endl;
for (auto i = iterations; --i >= 0; )
{ //Stack allocation
benchmark[0][(int)Person::CTOR_1::CTOR] += time_no_heap<Person::CTOR_1>(*p_name);
benchmark[0][(int)Person::CTOR_2::CTOR] += time_no_heap<Person::CTOR_2>(*p_name);
benchmark[0][(int)Person::CTOR_3::CTOR] += time_no_heap<Person::CTOR_3>(*p_name);
//Heap allocation
benchmark[1][(int)Person::CTOR_1::CTOR] += time_with_heap<Person::CTOR_1>(*p_name);
benchmark[1][(int)Person::CTOR_2::CTOR] += time_with_heap<Person::CTOR_2>(*p_name);
benchmark[1][(int)Person::CTOR_3::CTOR] += time_with_heap<Person::CTOR_3>(*p_name);
}
print_statistics(iterations,p_name->size(),benchmark);
delete p_name;
return 0;
}
我被 MVS 的 debug 版本弄错了,它显示的结果与 release 版本完全不同,即使项目设置相同!我的错..
【问题讨论】:
-
没有优化的基准测试是没有意义的。另外,你的基准是什么样的?你以
name传递什么字符串(它是否适合SBO)? -
嗨,也许在那里运行它:quick-bench.com 你会看到程序集以了解程序实际在做什么。您也可以使用其他编译器和优化进行测试。我做了一些基本测试,我发现了结果与您的不同
标签: c++11 visual-c++ visual-studio-2015 constructor move-semantics