-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbenchmark.cpp
More file actions
141 lines (123 loc) · 3.47 KB
/
benchmark.cpp
File metadata and controls
141 lines (123 loc) · 3.47 KB
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <boost/asio.hpp>
#include <iostream>
#include <chrono>
#include <atomic>
#include <vector>
#include <thread>
using boost::asio::ip::tcp;
class BenchmarkClient
{
public:
BenchmarkClient(boost::asio::io_context& io,
const std::string& host,
const std::string& port,
int num_requests,
std::atomic<int>& completed,
std::atomic<int>& errors)
: socket_(io), resolver_(io), num_requests_(num_requests), completed_(completed), errors_(errors)
{
auto endpoints = resolver_.resolve(host, port);
boost::asio::async_connect(socket_,
endpoints,
[this](boost::system::error_code ec, tcp::endpoint)
{
if (!ec)
{
send_request();
}
else
{
errors_++;
}
});
}
private:
void send_request()
{
if (current_request_ >= num_requests_)
{
socket_.close();
return;
}
std::string msg = "Benchmark test message " + std::to_string(current_request_) + "\n";
boost::asio::async_write(socket_,
boost::asio::buffer(msg),
[this, msg](boost::system::error_code ec, std::size_t)
{
if (!ec)
{
receive_response(msg.length());
}
else
{
errors_++;
socket_.close();
}
});
}
void receive_response(std::size_t expected_len)
{
boost::asio::async_read(socket_,
boost::asio::buffer(buffer_, expected_len),
[this](boost::system::error_code ec, std::size_t)
{
if (!ec)
{
completed_++;
current_request_++;
send_request();
}
else
{
errors_++;
socket_.close();
}
});
}
tcp::socket socket_;
tcp::resolver resolver_;
int num_requests_;
int current_request_ = 0;
std::atomic<int>& completed_;
std::atomic<int>& errors_;
char buffer_[1024];
};
int main(int argc, char* argv[])
{
if (argc != 5)
{
std::cerr << "用法: benchmark <host> <port> <并发数> <每连接请求数>\n";
std::cerr << "示例: benchmark localhost 8888 100 1000\n";
return 1;
}
std::string host = argv[1];
std::string port = argv[2];
int num_clients = std::atoi(argv[3]);
int requests_per_client = std::atoi(argv[4]);
std::atomic<int> completed {0};
std::atomic<int> errors {0};
auto start = std::chrono::high_resolution_clock::now();
boost::asio::io_context io;
// 创建多个客户端
std::vector<std::unique_ptr<BenchmarkClient>> clients;
for (int i = 0; i < num_clients; ++i)
{
clients.push_back(std::make_unique<BenchmarkClient>(io, host, port, requests_per_client, completed, errors));
}
// 运行事件循环
io.run();
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
int total_requests = num_clients * requests_per_client;
double seconds = duration / 1000.0;
double qps = completed.load() / seconds;
std::cout << "\n========== 压力测试结果 ==========\n";
std::cout << "总请求数: " << total_requests << "\n";
std::cout << "成功请求: " << completed.load() << "\n";
std::cout << "失败请求: " << errors.load() << "\n";
std::cout << "总耗时: " << duration << " ms\n";
std::cout << "QPS: " << static_cast<int>(qps) << " req/s\n";
std::cout << "平均延迟: " << (duration * 1.0 / completed.load()) << " ms\n";
std::cout << "==================================\n";
return 0;
}