2022-12-25 22:25
PS: 这是大约一年之前在另一台计算机上做的一个基准测试了,
当时需要优化一个网络文件上传程序, 而那里面大量使用了vector, 而且有大量深拷贝,
因此对这部分进行了基准测试, 并针对性进行了优化.
若在你的计算机上跑出来结果不一致, 这是正常的, 但通常结论不会有偏差.
细节请看源码
关于std::vector的深拷贝基准测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <vector>
#include <cstdint>
#include <chrono>
#include <algorithm>
#include <cassert>

int main(int argc, char **argv) {
//std::vector<std::uint32_t> responseRawBytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 10Byte*10000
std::vector<std::uint32_t> responseRawBytes; // 1024Byte*10000
for (int i = 0; i < 1024; ++i) {
responseRawBytes.push_back(i % UINT8_MAX);
}

std::chrono::time_point<std::chrono::steady_clock> beginTime = std::chrono::steady_clock::now();
//for(int i = 0; i < 10000; ++i) { // 10Byte*10000
for(int i = 0; i < 10000; ++i) { // 1024Byte*10000
// 10Byte*10000 Debug : 91 92 92 92 93 ms
// 10Byte*10000 Release: 09 09 09 10 09 ms
// 1024Byte*10000 Debug: 2647 2658 2652 2646 2653 ms
// 1024Byte*10000 Release: 36 37 36 37 36 ms
//std::vector<std::int32_t> responseBytes;
//std::transform(responseRawBytes.begin(), responseRawBytes.end(), std::back_inserter(responseBytes), [](const std::uint32_t &byte) {
// return static_cast<std::int32_t>(byte);
//});
// 1024Byte*10000 Debug: 4979 4932 4936 4935 4930 ms
// 1024Byte*10000 Release: 35 32 31 31 32 ms
//std::vector<std::int32_t> responseBytes;
//for (auto iter = responseRawBytes.begin(); iter != responseRawBytes.end(); ++iter) {
// responseBytes.push_back(static_cast<std::int32_t>(*iter));
//}
// 10Byte*10000 Debug : 16 16 16 16 16 ms
// 10Byte*10000 Release: 00 00 00 01 00 ms
// 1024Byte*10000 Debug : 17 17 17 17 17 ms
// 1024Byte*10000 Release: 01 01 01 01 01 ms
//auto rawBytesPtr = reinterpret_cast<std::int32_t*>(&responseRawBytes[0]);
//std::vector<std::int32_t> responseBytes(rawBytesPtr, rawBytesPtr + responseRawBytes.size());
// 10Byte*10000 Debug : 18 17 20 18 17 ms
// 10Byte*10000 Release: 00 00 00 01 00 ms
// 1024Byte*10000 Debug : 19 19 19 19 19 ms
// 1024Byte*10000 Release: 01 01 01 01 01 ms
std::vector<std::int32_t> responseBytes(responseRawBytes.begin(), responseRawBytes.end());
// 1024Byte*10000 Debug : 22 22 22 22 23 ms
// 1024Byte*10000 Release: 01 01 01 01 01 ms
//std::vector<std::int32_t> responseBytes;
//responseBytes.assign(responseRawBytes.begin(), responseRawBytes.end());
}
std::chrono::time_point<std::chrono::steady_clock> endTime = std::chrono::steady_clock::now();
auto diffTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime);
std::cout << "Delta Time: " << diffTimeMs.count() << " ms" << std::endl;
return 0;
}

结论表明,裸指针方式效率最高,但是考虑到安全性,最后还是折衷使用构造器方式最合适,因为两者相差其实也就1到2ms.
若可以做到不拷贝的话,效率就更好看了。

效率和通用性(抽象性)大概需要一直对它们进行平衡

最终效果还是不错的。