我正在研究一些用于测试其他可执行文件的代码。为方便起见,我将把我的代码称为测试人员,并将代码作为客户端进行测试。测试人员将产生客户端并将命令发送到客户端的stdin并从客户端的stdout接收结果。
我想先做一些性能测试,所以我写了一个非常简单的示例测试器和客户端。测试人员等待客户端向其标准输出写入“READY”,作为响应,它将“GO”发送到客户端的标准输出。然后客户端将一些字节写入stdout,通过命令行标志配置,然后写入“\ nREADY \ n”,此时测试仪将再次写入“GO”。重复10,000次,之后我计算完成测试所需的时间和“吞吐量”,10,000除以完成时间。
我运行上述测试,客户端在发送“READY”之前发送0,10,100,1000,10000和100000字节的数据。对于每个字节大小,我重复测试10次并取平均值。当我在Ubuntu VMWare实例的笔记本电脑上运行时,我的吞吐量大约为每秒100k GO / READY对。性能相当稳定,几乎不依赖于客户端发送给测试仪的二进制字节数。然后我在运行CentOS的非常快速的24核服务器上重复测试。使用0字节有效负载时,我每秒仅观察到约55k GO / READY对,并且性能随着客户端发送的字节数的增加而显着降低。当客户端在“GO”和“READY”之间发送100k字节时,吞吐量仅为每秒约6k次操作。
所以我有三个问题
一种可能的解释是我在快速服务器上重新编译了代码,它使用的是不同版本的C ++库。 VMWare计算机正在运行Ubuntu 11.10,而快速服务器正在运行CentOS 6.两者都是64位计算机。
相关测试人员代码如下:
ios_base::sync_with_stdio(false);
const int BUFFER_SIZE = 2 << 20;
char buffer[BUFFER_SIZE];
process_stdout->rdbuf()->pubsetbuf(buffer, BUFFER_SIZE);
Timer timer;
// Wait until the process is ready
string line;
line.reserve(2 << 20);
getline(*process_stdout, line);
CHECK(line == "READY");
timer.Start();
for (int i = 0; i < num_trials; ++i) {
*process_stdin << "GO\n";
process_stdin->flush();
line = "";
while (line != "READY") {
getline(*process_stdout, line);
}
}
double elapsed = timer.Elapsed();
cout << "Done. Did " << num_trials << " iterations in "
<< elapsed << " seconds. Throughput: "
<< double(num_trials) / elapsed << " per second." << endl;
我还尝试使用read()调用(来自unistd.h)到1MB缓冲区的版本,并调用memchr找到“\ n”字符并查找READY但得到相同的性能结果。
相关客户代码如下:
// Create a vector of binary data. Some portion of the data will be sent
// to stdout each time a "GO" is received before sending "READY"
vector<char> byte_source;
const int MAX_BYTES = 1 << 20;
for (int i = 0; i < MAX_BYTES; ++i) {
byte_source.push_back(i % 256);
}
cout << "READY" << endl;
while (cin.good()) {
string line;
getline(cin, line);
if (line == "GO") {
// The value of response_bytes comes from a command line flag
OutputData(response_bytes, byte_source);
cout << "READY" << endl;
}
}
// write bytes worth of data from byte_source to stdout
void OutputData(unsigned int bytes,
const vector<char>& byte_source) {
if (bytes == 0) {
return;
}
cout.write(&byte_source[0], bytes);
cout << "\n";
}
非常感谢任何帮助!
答案 0 :(得分:0)
VM中的速度与有效负载大小无关的事实表明您做错了什么。这些不是完整的程序,所以很难确定什么。使用strace查看正在发生的事情,即客户端是否确实发送了您认为的所有数据(并检查测试人员是否正在接收所有数据)。
100k READY / GO对太多了;它基本上接近每秒上下文切换次数的上限,没有做任何其他事情。