C++ Poco库POST发送图片耗时高 求每秒60张高速传输优化方案
现有实现代码
#include <Poco/Net/HTTPClientSession.h> #include <Poco/Net/HTTPRequest.h> #include <Poco/Net/HTTPResponse.h> #include <Poco/Path.h> #include <Poco/URI.h> #include <iostream> #include <string> #include <Poco/JSON/JSON.h> #include <Poco/JSON/Parser.h> #include <Poco/Net/HTMLForm.h> #include <Windows.h> #include <vector> #include <opencv2/opencv.hpp> #include <opencv2/calib3d/calib3d.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE #include <spdlog/spdlog.h> #include <spdlog/sinks/stdout_sinks.h> #include <chrono> #include <typeinfo> #include <string> #include "base64.cpp" std::string host="127.0.0.1"; int port =2000; std::string path="/images/" Poco::Net::HTTPClientSession session(host, port); session.setKeepAlive(true); Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_POST, path); std::string m_files_path= "C:/Users/syste/OneDrive/Pictures/Screenshots/*.png"; std::vector<std::string> imageFiles; cv::glob(m_files_path, imageFiles); cv::Mat image = cv::imread(imageFiles[0]); std::vector<unsigned char> buff; cv::imencode(".png", image, buff); auto base64_png = reinterpret_cast<const unsigned char*>(buff.data()); std::string body1 = base64_encode(base64_png, buff.size()); obj.set("photo1", body1); std::stringstream ss; obj.stringify(ss); std::string body; body = ss.str(); req.setContentType("application/json"); req.setContentLength(body.length()); session.sendRequest(req)<<body;
问题描述
当前基于C++ Poco库实现的客户端向服务端发送图片功能,单张图片处理耗时达到0.45-0.55秒,耗时主要集中在cv::imencode图片编码、Base64转码、JSON序列化三个步骤,无法满足每秒至少发送60张图片的性能要求,需要确认Poco C++发起POST请求是否存在更高效的实现方式,获取可提升图片发送速度的可行方案。
优化方案
- 淘汰Base64+JSON的传输逻辑:Base64编码会额外增加33%的数据体积,同时编解码过程会占用大量CPU资源,直接使用二进制POST请求或者
multipart/form-data格式传输图片原始字节,完全省去Base64转码和JSON序列化的耗时。 - 调整图片编码策略:PNG为无损压缩格式,编码速度慢、压缩后体积大,如果业务允许轻微画质损失,将
cv::imencode的目标格式替换为JPEG,搭配cv::IMWRITE_JPEG_QUALITY参数(推荐设置为70-85区间),可将编码耗时降低70%以上,同时大幅缩小传输数据体积;如果必须使用无损压缩,可替换为编码速度更快的WEBP无损格式;针对当前服务端部署在本地127.0.0.1的场景,完全可以跳过图片编码步骤,直接传输OpenCV Mat的原始BGR数据,省掉cv::imencode的全部耗时,本地环回带宽完全可以承载60fps下的原始图像数据传输需求。 - 减少不必要的内存拷贝:现有实现存在多次冗余内存拷贝(Base64结果写入std::string、JSON序列化写入std::stringstream、再拷贝到请求body字符串),使用Poco提供的
MemoryInputStream直接对接编码后的图片缓冲区,将数据直接写入请求发送流,减少中间环节的内存复制开销。 - 复用连接与请求对象:现有代码已经开启长连接配置,注意不要在每次发送请求时重新创建
HTTPClientSession和HTTPRequest对象,复用长连接避免重复TCP握手、连接销毁的开销。 - 采用多线程流水线处理:将图片读取、图片编码、网络发送三个环节拆分为独立工作线程,通过无锁队列衔接不同环节,实现多步骤并行处理——例如编码线程处理第N张图片时,网络线程可以同时发送第N-1张已经处理完成的图片,充分利用多核CPU和网络带宽,将单步处理的耗时摊薄。
- 调整Poco发送配置:发送请求时关闭Nagle算法,在
HTTPClientSession上设置setNoDelay(true),降低小包发送的等待延迟;针对本地传输场景可以适当调大发送缓冲区大小,减少系统调用次数。
内容的提问来源于stack exchange,提问作者REDDY
相关产品推荐
相关产品推荐

