- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 Boost ASIO UDP 的性能方面遇到了一些麻烦 - 或者至少 - 我认为是这样。
我整理了一个简单的客户端/服务器应用程序来说明:
(包丢失/重新发送等在示例代码中不是问题。)
当最初用 C# 编写此代码时,客户端很快达到了 NIC 的限制 - 大约 125 兆字节/秒。当使用 Boost 在 C++ 中重写相同的代码时,速度停止在 2 兆字节/秒以下。
客户端和服务器的 CPU 都是 1-2%。没有内存问题。在本地主机上同时运行服务器和客户端。运行 Windows 10、VS 2013、Boost 1.60。
我曾尝试使用 Boost 的异步发送/接收方法,但这似乎没有帮助。 How to increase throughput of Boost ASIO, UDP client application
是否存在与从同一 boost 套接字发送/接收两个线程相关的问题? C++ Socket Server - Unable to saturate CPU
PS - 我在 2 个月前开始编写 C++ - 所以这里的某处可能是一个非常愚蠢的错误..但我无法看到确切的位置。任何帮助/想法将不胜感激。
客户:
#pragma once
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/thread/v2/thread.hpp>
#include <boost/thread/detail/thread.hpp>
#include <chrono>
#include <boost/lexical_cast.hpp>
#define EXPOSE_IN_DLL __declspec(dllexport)
namespace dummy{
EXPOSE_IN_DLL class DummyClient
{
public:
// How fast the client is receiving acks - e.g. every 200 ms.
double MillisecondsPerAck = 200;
//How fast the client should be sending packages (meaning - how long it should sleep between packages)
long long MinimumOfMillisecondsToUsePerSentPackage = 200;
//How often the code should throttle (calculate new value for 'MinimumOfMillisecondsToUsePerSentPackage')
int intervalMilliseconds = 500;
//How much faster we should send than receive (how fast we should increase the speed)
const double ThrottleAgressiveness = 0.7;
//Counters
int AcksSinceLastTime = 0;
int AcksLastTime = 0;
int PackagesSent = 0;
int AcksReceived = 0;
long long BytesSentAndAcked = 0;
//Size of UDP Package to send. IP Layer (NIC) will break larger packages into smaller ones (MTU).
static const int PacketSize = 65000;
std::shared_ptr<boost::asio::io_service> io_service;
std::shared_ptr<boost::asio::ip::udp::socket> socket;
std::shared_ptr<boost::asio::ip::udp::endpoint> udpEndPoint;
EXPOSE_IN_DLL DummyClient()
{
boost::thread receiverThread(&DummyClient::SendPackages, this);
receiverThread.detach();
using namespace std::chrono;
auto started = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
while (true){
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
auto elapsedMilliseconds = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - started;
system("cls");
std::cout << " ############ UDP CLIENT ############ \n\n";
std::cout << " Packages sent: " << PackagesSent << "\n";
std::cout << " Acks received: " << AcksReceived << "\n";
std::cout << " Bytes delivered: " << BytesToSize(BytesSentAndAcked) << "\n";
std::cout << "---------------------------------------------------------------------------\n";
if (AcksReceived > 0 && PackagesSent > 0)
std::cout << " Acked percentage: " << 100.0 * AcksReceived / PackagesSent << "\n";
std::cout << "---------------------------------------------------------------------------\n";
std::cout << " Bandwidth: " << BytesToSize(1000 * BytesSentAndAcked / elapsedMilliseconds) << "/sec\n";
std::cout << "---------------------------------------------------------------------------\n";
std::cout << " MilliSecondsPerAck: " << MillisecondsPerAck << "\n";
std::cout << " ThrottleAgressiveness: " << ThrottleAgressiveness << "\n";
std::cout << " MinimumOfMillisecondsToUsePerSentPackage: " << MinimumOfMillisecondsToUsePerSentPackage << "\n";
std::cout << "---------------------------------------------------------------------------\n";
}
}
EXPOSE_IN_DLL ~DummyClient(){
};
private:
void SendPackages(){
io_service = std::make_shared<boost::asio::io_service>();
socket = std::make_shared<boost::asio::ip::udp::socket>(*io_service);
udpEndPoint = std::make_shared<boost::asio::ip::udp::endpoint>(boost::asio::ip::address_v4::from_string("127.0.0.1"), 56000);
socket->open(boost::asio::ip::udp::v4());
//Start throtteling thread
boost::thread throttleThread(&DummyClient::ThrottleThread, this);
//Start Receiver thread - that listens for ACK packages from the Dummy server
boost::thread receiverThread(&DummyClient::ReceiverThread, this);
//Start sending packages - slowly
unsigned char dummyData[PacketSize];
auto bufferToSend = boost::asio::buffer(dummyData, PacketSize);
for (int i = 0; i < 100000; i++)
{
//Send
socket->send_to(bufferToSend, *udpEndPoint, boost::asio::socket_base::message_do_not_route);
PackagesSent++;
//Check if we need to sleep a little (throtteling) before sending next package
if (MinimumOfMillisecondsToUsePerSentPackage > 0)
boost::this_thread::sleep_for(boost::chrono::milliseconds(MinimumOfMillisecondsToUsePerSentPackage));
}
}
//"Acks" are received here - we are just counting them to get the rate they're coming in at.
void ReceiverThread(){
//Need to wait until first package is sent - so that the local andpoint is bound
while (PackagesSent == 0){
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
//Set up receiving buffer
unsigned char receiveBuffer[100];
auto bufferToReceiveInto = boost::asio::buffer(receiveBuffer, 100);
boost::asio::ip::udp::endpoint senderEndPoint;
//Start Receiving!
while (true){
socket->receive_from(bufferToReceiveInto, senderEndPoint);
AcksReceived++;
BytesSentAndAcked += PacketSize;
}
}
//Counts acks per interval - and adjusts outgoing speed accordingly.
void ThrottleThread()
{
while (true)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(intervalMilliseconds));
//Find out how many packages we got since last time - and send a little bit faster than this number.
if (PackagesSent > 0)
{
AcksSinceLastTime = AcksReceived - AcksLastTime;
AcksLastTime = AcksReceived;
if (AcksSinceLastTime == 0)
{
//No new packages got acked - slow the down!
MinimumOfMillisecondsToUsePerSentPackage = 200;
continue;
}
//Increase sending speed to a little bit faster than we're receiving packages
MillisecondsPerAck = 1.0 * intervalMilliseconds / AcksSinceLastTime;
MinimumOfMillisecondsToUsePerSentPackage = MillisecondsPerAck * ThrottleAgressiveness;
}
}
}
//Util method
std::string BytesToSize(long long Bytes){
float tb = 1099511627776;
float gb = 1073741824;
float mb = 1048576;
float kb = 1024;
std::string returnSize = "";
if (Bytes >= tb){
returnSize += boost::lexical_cast<std::string>((float)Bytes / tb);
returnSize += " TB";
}
else if (Bytes >= gb && Bytes < tb)
{
returnSize += boost::lexical_cast<std::string>((float)Bytes / gb);
returnSize += " GB";
}
else if (Bytes >= mb && Bytes < gb){
returnSize += boost::lexical_cast<std::string>((float)Bytes / mb);
returnSize += " MB";
}
else if (Bytes >= kb && Bytes < mb){
returnSize += boost::lexical_cast<std::string>((float)Bytes / kb);
returnSize += " KB";
}
else{
returnSize += boost::lexical_cast<std::string>(Bytes);
returnSize += " Bytes";
}
return returnSize;
}
};
}
服务器:
#pragma once
#include <boost/asio.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/thread/v2/thread.hpp>
#include <boost/thread/detail/thread.hpp>
#define EXPOSE_IN_DLL __declspec(dllexport)
using namespace boost::asio;
namespace dummy{
class DummyServer
{
public:
std::shared_ptr<ip::udp::socket> listenSocket;
std::shared_ptr<io_service> listenIoService;
int PackagesReceived = 0;
EXPOSE_IN_DLL DummyServer()
{
boost::thread receiverThread(&DummyServer::ReceivePackages, this);
receiverThread.detach();
//Print status
while (true){
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
system("cls");
std::cout << " ############ UDP SERVER ############ \n\n";
std::cout << " Packages received: " << PackagesReceived << "\n";
}
}
EXPOSE_IN_DLL ~DummyServer(){}
void ReceivePackages(){
//Start Receiver thread
listenIoService = std::make_shared<io_service>();
listenSocket = std::make_shared<ip::udp::socket>(*listenIoService, ip::udp::endpoint(ip::udp::v4(), 56000));
//Set up receiving buffer
auto bytesReceived = 0;
unsigned char receiveBuffer[1024 * 70];
auto bufferToReceiveInto = boost::asio::buffer(receiveBuffer, 1024 * 70);
unsigned char returnBufferBuffer[10];
auto bufferToSendBackToClient = boost::asio::buffer(returnBufferBuffer, 10);
ip::udp::endpoint senderEndPoint;
//Receive packages
while (true){
listenSocket->receive_from(bufferToReceiveInto, senderEndPoint);
PackagesReceived++;
//Send an "Ack" package back to client - letting him know that a package successfully made it.
//Doesn't matter what the package contains - since client is just counting.
listenSocket->send_to(bufferToSendBackToClient, senderEndPoint);
}
}
};
最佳答案
终于找到问题了。 sleep_for 导致了低速。
这段代码
boost::this_thread::sleep_for(boost::chrono::milliseconds(20));
通常需要超过 30 毫秒 - 当其他线程正在工作时。
我想我必须使用不同的节流策略(计算飞行中的包裹等)- 或者使用高精度多媒体计时器。
关于c++ - Boost UDP 套接字的性能 - 吞吐量低?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35663032/
我正在尝试使用boost.spirit的qi库解析某些内容,而我遇到了一个问题。根据spirit docs,a >> b应该产生类型为tuple的东西。但这是boost::tuple(又名 fusio
似乎有/正在努力做到这一点,但到目前为止我看到的大多数资源要么已经过时(带有死链接),要么几乎没有信息来实际构建一个小的工作样本(例如,依赖于boost program_options 以构建可执行文
我对 Boost.Log 的状态有点困惑。这是 Boost 的官方部分,还是尚未被接受?当我用谷歌搜索时,我看到一些帖子谈论它在 2010 年是如何被接受的,等等,但是当我查看最后一个 Boost 库
Boost 提供了两种不同的实现 string_view ,这将成为 C++17 的一部分: boost::string_ref在 utility/string_ref.hpp boost::stri
最近,我被一家GIS公司雇用来重写他们的旧地理信息库。所以我目前正在寻找一个好的计算几何库。我看过CGAL,这真是了不起,但是我的老板想要免费的东西。 所以我现在正在检查Boost.Geometry。
假设我有一个无向图 G。假设我添加以下内容 add_edge(1,2,G); add_edge(1,3,G); add_edge(0,2,G); 现在我再说一遍: add_edge(0,2,G); 我
我使用 CMake 来查找 Boost。找到了 Boost,但 CMake 出错了 Imported targets not available for Boost version 请参阅下面的完整错
我是 boost::fusion 和 boost::mpl 库的新手。谁能告诉我这两个库之间的主要区别? 到目前为止,我只使用 fusion::vector 和其他一些简单的东西。现在我想使用 fus
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: What are the benefits of using Boost.Phoenix? 所以我开始阅读 boos
我正在尝试获得一个使用 Boost.Timer 的简单示例,用于一些秒表性能测量,但我不明白为什么我无法成功地将 Boost.Timer 链接到 Boost.Chrono。我使用以下简单脚本从源代码构
我有这样的东西: enum EFood{ eMeat, eFruit }; class Food{ }; class Meat: public Food{ void someM
有人可以告诉我,我如何获得boost::Variant处理无序地图? typedef boost::variant lut_value;unordered_map table; 我认为有一个用于boo
我对 Boost.Geometry 中的环和多边形感到困惑。 在文档中,没有图形显示什么是环,什么是多边形。 谁能画图解释两个概念的区别? 最佳答案 在 Boost.Geometry 中,多边形被定义
我正在使用 boost.pool,但我不知道何时使用 boost::pool<>::malloc和 boost::pool<>::ordered_malloc ? 所以, boost::pool<>:
我正在尝试通过 *boost::fast_pool_allocator* 使用 *boost::container::flat_set*。但是,我收到编译错误。非常感谢您的意见和建议。为了突出这个问题
sau_timer::sau_timer(int secs, timerparam f) : strnd(io), t(io, boost::posix_time::seconds(secs)
我无法理解此功能的文档,我已多次看到以下内容 tie (ei,ei_end) = out_edges(*(vi+a),g); **g**::out_edge_iterator ei, ei_end;
我想在 C++ 中序列化分层数据结构。我正在处理的项目使用 boost,所以我使用 boost::property_tree::ptree 作为我的数据节点结构。 我们有像 Person 这样的高级结
我需要一些帮助来解决这个异常,我正在实现一个 NPAPI 插件,以便能够使用来自浏览器扩展的本地套接字,为此我正在使用 Firebreath 框架。 对于套接字和连接,我使用带有异步调用的 Boost
我尝试将 boost::bind 与 boost::factory 结合使用但没有成功 我有这个类 Zambas 有 4 个参数(2 个字符串和 2 个整数)和 class Zambas { publ
我是一名优秀的程序员,十分优秀!