我写了一个小测试程序,使用boost::asio::ip::tcp::iostream
传输约 38 MiB 的数据:
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/asio.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
using namespace std;
class Message {
public:
Message() {
}
virtual ~Message() {
}
string text;
std::vector<int> bigLoad;
private:
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive &ar, const unsigned int version) {
ar &text;
ar &bigLoad;
}
};
BOOST_CLASS_EXPORT(Message)
void runClient() {
// Give server time to startup
this_thread::sleep_for(chrono::milliseconds(3000));
boost::asio::ip::tcp::iostream stream("127.0.0.1", "3000");
// const boost::asio::ip::tcp::no_delay option(true);
// stream.rdbuf()->set_option(option);
Message message;
stringstream ss;
ss << "Hello World!";
message.text = ss.str();
int items = 10000000;
int size = sizeof(int) * items;
std::cout << "Size in Byte = " << size << endl;
std::cout << "Size in KiB = " << size / 1024 << endl;
std::cout << "Size in MiB = " << size / 1024 / 1024 << endl;
for (int i = 0; i < items; i++)
message.bigLoad.push_back(i);
boost::archive::text_oarchive archive(stream);
cout << "Client start to send message" << endl;
try {
archive << message;
} catch (std::exception &ex) {
cout << ex.what() << endl;
}
cout << "Client send message" << endl;
stream.close();
cout << "Client shutdown" << endl;
}
void handleIncommingClientConnection(boost::asio::ip::tcp::acceptor &acceptor) {
boost::asio::ip::tcp::iostream stream;
// const boost::asio::ip::tcp::no_delay option(true);
// stream.rdbuf()->set_option(option);
acceptor.accept(*stream.rdbuf());
boost::archive::text_iarchive archive(stream);
while (true) {
try {
Message message;
archive >> message;
cout << message.text << endl;
} catch (std::exception &ex) {
cout << ex.what() << endl;
if (stream.eof()) {
cout << "eof" << endl;
stream.close();
cout << "Server: shutdown client handling..." << endl;
break;
} else
throw ex;
}
}
}
void runServer() {
boost::asio::io_service ios;
boost::asio::ip::tcp::endpoint endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 3000);
boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
handleIncommingClientConnection(acceptor);
}
template <typename TimeT = std::chrono::milliseconds>
struct measure {
template <typename F, typename... Args>
static typename TimeT::rep execution(F &&func, Args &&... args) {
auto start = std::chrono::steady_clock::now();
std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now() - start);
return duration.count();
}
};
void doIt() {
thread clientThread(runClient);
thread serverThread(runServer);
clientThread.join();
serverThread.join();
}
int main(int argc, char **argv) {
std::cout << measure<std::chrono::seconds>::execution(doIt) << std::endl;
return 0;
}
程序在发布模式下的输出如下所示:
Size in Byte = 40000000
Size in KiB = 39062
Size in MiB = 38
Client start to send message
Client send message
Client shutdown
Hello World!
input stream error
eof
Server: shutdown client handling...
148
传输 38 MB 需要 148 秒(超过 2 分钟)。我可以将数据复制到 U 盘并手动移交,速度比boost::asio
does.
有什么办法可以提高带宽性能吗?
您的时间可能浪费在与文本的序列化上。
对我来说,放入二进制存档确实将速度从 80Mbit/s 提高到 872MBit/s:
Client start to send message
Client send message
Client shutdown
Received: Hello World!
3
总时间(以秒为单位)减少到 3 秒,这恰好是初始睡眠:)
Proof Of Concept Live On Coliru http://coliru.stacked-crooked.com/a/137017448a238a71
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/asio.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
using namespace std;
class Message {
public:
Message() {}
virtual ~Message() {}
string text;
std::vector<int> bigLoad;
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) {
ar & text & bigLoad;
}
};
BOOST_CLASS_EXPORT(Message)
void runClient() {
// Give server time to startup
this_thread::sleep_for(chrono::seconds(1));
boost::asio::ip::tcp::iostream stream("127.0.0.1", "3000");
const boost::asio::ip::tcp::no_delay option(false);
stream.rdbuf()->set_option(option);
Message message;
stringstream ss;
ss << "Hello World!";
message.text = ss.str();
int items = 8 << 20;
for (int i = 0; i < items; i++)
message.bigLoad.push_back(i);
boost::archive::binary_oarchive archive(stream);
cout << "Client start to send message" << endl;
try {
archive << message;
} catch (std::exception &ex) {
cout << ex.what() << endl;
}
cout << "Client send message" << endl;
stream.close();
cout << "Client shutdown" << endl;
}
void handleIncommingClientConnection(boost::asio::ip::tcp::acceptor &acceptor) {
boost::asio::ip::tcp::iostream stream;
// const boost::asio::ip::tcp::no_delay option(false);
// stream.rdbuf()->set_option(option);
acceptor.accept(*stream.rdbuf());
boost::archive::binary_iarchive archive(stream);
{
try {
Message message;
archive >> message;
cout << "Received: " << message.text << endl;
} catch (std::exception &ex) {
cout << ex.what() << endl;
if (stream.eof()) {
cout << "eof" << endl;
stream.close();
cout << "Server: shutdown client handling..." << endl;
return;
} else
throw;
}
}
}
void runServer() {
using namespace boost::asio;
using ip::tcp;
io_service ios;
tcp::endpoint endpoint = tcp::endpoint(tcp::v4(), 3000);
tcp::acceptor acceptor(ios, endpoint);
handleIncommingClientConnection(acceptor);
}
template <typename TimeT = std::chrono::milliseconds> struct measure {
template <typename F, typename... Args> static typename TimeT::rep execution(F &&func, Args &&... args) {
auto start = std::chrono::steady_clock::now();
std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now() - start);
return duration.count();
}
};
void doIt() {
thread clientThread(runClient);
thread serverThread(runServer);
clientThread.join();
serverThread.join();
}
int main() { std::cout << measure<std::chrono::seconds>::execution(doIt) << std::endl; }
Caution:
这里“丢失”了一件事,旧版本的代码也没有真正支持这一点:直接接收多个档案。
您可能想要设备某种成帧协议。参见例如
- Boost 序列化二进制存档给出不正确的输出 https://stackoverflow.com/questions/26556145/boost-serialization-binary-archive-giving-incorrect-output/26568212#26568212
- 输出比多态文本档案更多的东西 https://stackoverflow.com/questions/27422557/outputting-more-things-than-a-polymorphic-text-archive/27424381#27424381
- 流不是档案(http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/ http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/)
我在这里发表了一些“Boost Serialization 的开销”帖子:
- 如何使用 boost 库对自定义库进行性能测试 https://stackoverflow.com/questions/23571355/how-to-do-performance-test-using-the-boost-library-for-a-custom-library/23572674#23572674
- Boost C++ 序列化开销 https://stackoverflow.com/questions/22459726/boost-c-serialization-overhead/22464553#22464553
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)