chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.97k stars 1.22k forks source link

Async write not writing fast enough.(DOUBT) #1517

Closed jaimebw closed 3 months ago

jaimebw commented 3 months ago

Hi, First of all, thansk for maintining the libray.

I have a doubt/issue regarding writing messages to an async socket. Basically, I have a queue of messages that need to be sent with a certain rate. It works fine for anything under 30Hz, but when I try to send faster, it seems that I get stuck at 64Hz, and if I put an enormous value (1100Hz), the rate augments(to around 500Hz) but still it is not the correct rate. My code is structured so my Broadcasting class takes care of the timing and the sending.

void Broadcaster::sendMessage(std::shared_ptr<BaseMessage> message, std::shared_ptr<asio::high_resolution_timer> timer)
{
            auto serializedData = message->getTCPMessage(); //std::vector<uint8_t>
        asio::async_write(*TCPsocket_, asio::buffer(*serializedData,serializedData->size()), 
            [this, self,message, timer](const asio::error_code& error, std::size_t) {
            if (!error) 
            {

                scheduleSend(message, timer);

            }
            else 
            {
                std::cerr << "Error: " << error.message() << std::endl;
            }
});
void Broadcaster::scheduleSend(std::shared_ptr<BaseMessage> message, std::shared_ptr<asio::high_resolution_timer> timer)
{
        timer->expires_after(std::chrono::milliseconds(static_cast<int>(1000.0f/message->getRefreshRate())));
        timer->async_wait([this, self,timer,message](const asio::error_code& error) {
            if (!error) {
                sendMessage(message, timer);
            }
            else {
                std::cerr << "Timer error: " << error.message() << std::endl;
            }
            });

}

void Broadcaster::start_send()
{
        for (auto& message : MessageQueue::messages) {
            auto timer = std::make_shared<asio::high_resolution_timer>(io_context_);
            scheduleSend(message, timer);
        }
}

My main application loop woud look like this. The broadcaster is construcited with the asio::context

int main(){

Broadcaster broadcaster(io_context_, host, port)
broadcaster.start_send();
ioThread_ = std::thread([this]() {
while (running) {
     io_context_.run();
    }
});
return 0;
}

I believe I'm doing something wrong thats why I am asking for some pointers.
Thank you very much Let me know if you need more information

-Jaime

liubing commented 3 months ago

If you were on Windows, you could try to call timeBeginPeriod(1) Windows API before the loop.

jaimebw commented 3 months ago

Yes! Thanks, that solves the issue. I'm on Win11.