@@ -516,6 +516,7 @@ struct WriteRequestContext {
516516struct BulkWriteRequestContext {
517517 std::vector<uv_buf_t > buffers;
518518 ServiceRegistryRef ref;
519+ std::vector<char *>* freeList = nullptr ; // if non-null, return chunks here instead of freeing
519520};
520521
521522void ws_client_write_callback (uv_write_t * h, int status)
@@ -543,11 +544,14 @@ void ws_client_bulk_write_callback(uv_write_t* h, int status)
543544 state.loopReason |= (DeviceState::WS_COMMUNICATION | DeviceState::WS_WRITING);
544545 if (status < 0 ) {
545546 LOG (error) << " uv_write error: " << uv_err_name (status);
546- free (h);
547- return ;
548547 }
549- if (context->buffers .size ()) {
550- for (auto & b : context->buffers ) {
548+ // Return chunks to the free list (capped) so flushPending can pre-seed
549+ // the backlog for the next cycle without malloc-ing.
550+ constexpr size_t kMaxFreeChunks = 4 ;
551+ for (auto & b : context->buffers ) {
552+ if (context->freeList && b.base && context->freeList ->size () < kMaxFreeChunks ) {
553+ context->freeList ->push_back (b.base );
554+ } else {
551555 free (b.base );
552556 }
553557 }
@@ -584,4 +588,18 @@ void WSDPLClient::write(std::vector<uv_buf_t>& outputs)
584588 context->buffers .size (), ws_client_bulk_write_callback);
585589}
586590
591+ void WSDPLClient::write (std::vector<uv_buf_t >& outputs, std::vector<char *>& freeList)
592+ {
593+ if (outputs.empty ()) {
594+ return ;
595+ }
596+ auto * write_req = (uv_write_t *)malloc (sizeof (uv_write_t ));
597+ auto * context = new BulkWriteRequestContext{.ref = mContext ->ref };
598+ context->buffers .swap (outputs);
599+ context->freeList = &freeList;
600+ write_req->data = context;
601+ uv_write (write_req, (uv_stream_t *)mStream , &context->buffers .at (0 ),
602+ context->buffers .size (), ws_client_bulk_write_callback);
603+ }
604+
587605} // namespace o2::framework
0 commit comments