Недавно я прочитал, как std::move
может ускорить код, просто перемещая значения вместо их копирования. Поэтому я сделал тестовую программу для сравнения скорости с использованием std::vector
.
Код:
#include <iostream>
#include <vector>
#include <stdint.h>
#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif
#undef max
// Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
// windows and linux.
uint64_t GetTimeMs64()
{
#ifdef _WIN32
// Windows
FILETIME ft;
LARGE_INTEGER li;
// Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
// to a LARGE_INTEGER structure.
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
uint64_t ret = li.QuadPart;
ret -= 116444736000000000LL; // Convert from file time to UNIX epoch time.
ret /= 10000; // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals
return ret;
#else
// Linux
struct timeval tv;
gettimeofday(&tv, NULL);
uint64 ret = tv.tv_usec;
// Convert from micro seconds (10^-6) to milliseconds (10^-3)
ret /= 1000;
// Adds the seconds (10^0) after converting them to milliseconds (10^-3)
ret += (tv.tv_sec * 1000);
return ret;
#endif
}
static std::vector<std::string> GetVec1()
{
std::vector<std::string> o(100000, "abcd");
bool tr = true;
if (tr)
return std::move(o);
return std::move(std::vector<std::string>(100000, "abcd"));
}
static std::vector<std::string> GetVec2()
{
std::vector<std::string> o(100000, "abcd");
bool tr = true;
if (tr)
return o;
return std::vector<std::string>(100000, "abcd");
}
int main()
{
uint64_t timer;
std::vector<std::string> vec;
timer = GetTimeMs64();
for (int i = 0; i < 1000; ++i)
vec = GetVec1();
std::cout << GetTimeMs64() - timer << " timer 1(std::move)" << std::endl;
timer = GetTimeMs64();
for (int i = 0; i < 1000; ++i)
vec = GetVec2();
std::cout << GetTimeMs64() - timer << " timer 2(no move)" << std::endl;
std::cin.get();
return 0;
}
Я получил следующие результаты:
Выпуск (x86) /O2. tr = true
4376 таймер 1 (std::move)
4191 таймер 2(нет хода)
Выпуск (x86) /O2. tr = false
7311 таймер 1 (std::move)
7301 таймер 2 (без движения)
Результаты между двумя таймерами очень близки и не сильно отличаются. Я уже предположил, что это связано с оптимизацией возвращаемого значения (RVO), что означает, что мои возвращаемые значения уже перемещены компилятором без моего ведома, верно?
Затем я провел новые тесты без каких-либо оптимизаций, чтобы убедиться, что я прав. Результаты:
Выпуск (x86)/Od. tr = true
40860 таймер 1 (std::move)
40863 таймер 2(нет хода)
Выпуск (x86)/Od. tr = false
83567 таймер 1 (std::move)
82075 таймер 2 (без движения)
Теперь, несмотря на то, что разница между /O2 и /Od действительно значительна, разница между отсутствием движения или std::move
(и даже между tr
и true
или false
) минимальна.
Означает ли это, что хотя оптимизация отключена, компилятору разрешено применять RVO
или std::move
не так быстро, как я думал?
std::chrono::high_resolution_clock
для ваших потребностей во времени... - person anorm   schedule 29.09.2015std::vector
, содержащий 100 000 объектовstd::string
, достаточно дорог для копирования. - person Angew is no longer proud of SO   schedule 29.09.2015