简体   繁体   中英

Boost::serial_port and asio::async_write for byte[256] exceeds 200ms

I am implementing some basic communication over serial port.

According to protocol I must respond with answer within 225ms after receiving the request. Maximum package size is 256B.

So, when I receive request I create response [header, lenght, payload, crc16] (total 256 B) for that I need in average 30 - 40 ms. Then the actual problem occurs when I put that response(byte array) in asio::async_write . That function take around 240ms in average to process that byte array.

Everything works fine except when I sending maximum length packages. It takes 240ms ( asio::async_write ) + 40ms(package assembly) around 280 ~ 300 ms.

Port: 9600 baud, length 8, one stop bit

Any idea how can I speed it up?

    void Example::do_write()
{
    if (pimpl_->WriteBuffer == nullptr)
    {
        boost::lock_guard<boost::mutex> l(pimpl_->WriteQueueMutex);
        pimpl_->WriteBufferSize = pimpl_->WriteQueue.size();
        pimpl_->WriteBuffer.reset(new byte[pimpl_->WriteQueue.size()]);
        std::move(pimpl_->WriteQueue.begin(), pimpl_->WriteQueue.end(), pimpl_->WriteBuffer.get());
        pimpl_->WriteQueue.clear();

        begin = boost::chrono::steady_clock::now();
        async_write(pimpl_->Port, asio::buffer(pimpl_->WriteBuffer.get(), pimpl_->WriteBufferSize), boost::bind(&Example::write_end, this, asio::placeholders::error));
    }
}

void Example::write_end(const system::error_code& error)
{
    if (!error)
    {
        boost::lock_guard<boost::mutex> l(pimpl_->WriteQueueMutex);
        if (pimpl_->WriteQueue.empty())
        {
            pimpl_->WriteBuffer.reset();
            pimpl_->WriteBufferSize = 0;

            end = boost::chrono::steady_clock::now();
            OutputDebugString(string("\nWRITE TIME: " + to_string(boost::chrono::duration_cast<boost::chrono::milliseconds>(end - begin).count()) + "\n").c_str());

            return;
        }

        pimpl_->WriteBufferSize = pimpl_->WriteQueue.size();
        pimpl_->WriteBuffer.reset(new byte[pimpl_->WriteQueue.size()]);

        std::move(pimpl_->WriteQueue.begin(), pimpl_->WriteQueue.end(), pimpl_->WriteBuffer.get());
        pimpl_->WriteQueue.clear();

        async_write(pimpl_->Port, asio::buffer(pimpl_->WriteBuffer.get(), pimpl_->WriteBufferSize), boost::bind(&Example::write_end, this, asio::placeholders::error));
    }
    else
    {
        set_error_status(true);
        do_close();
    }
}

In my experience boost::asio itself takes fractions of microseconds. You use 40 ms to fetch the data, communication takes 220 ms (it is about minimum to send 256 bytes over 9600 baud) and somewhere you waste more 20-40 ms and sum is 280 - 300 ms.

What to do?

  1. Most profitable is likely to increase the baud rate to 115200 baud (0.85 ms/byte of 9600 baud versus 0.07 ms/byte of 115200 baud).
  2. Next idea is to profile out where those 20-40 ms go (likely something unneeded in message loop you wrote).
  3. Finally it is likely possible also to reduce those data fetching 40 ms.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM