@@ -231,7 +231,9 @@ mutable struct gRPCRequest
231231 end
232232
233233 # Reduce number of available requests by one or block if its currently zero
234- acquire (grpc. sem)
234+ # Also reduces the need to allocate the curl_done_reading Event for every request
235+ # This is a 7% reduction in allocations overall
236+ curl_done_reading = max_reqs_dec (grpc)
235237
236238 easy_handle = curl_easy_init ()
237239
@@ -287,7 +289,7 @@ mutable struct gRPCRequest
287289 false ,
288290 false ,
289291 0 ,
290- Event () ,
292+ curl_done_reading ,
291293 GRPC_OK,
292294 " " ,
293295 )
@@ -324,7 +326,8 @@ mutable struct gRPCRequest
324326 curl_slist_free_all (headers)
325327 unpreserve_handle (req)
326328 # *MUST* increment the sem or we could deadlock
327- release (grpc. sem)
329+ max_reqs_inc (grpc, req)
330+
328331 throw (
329332 gRPCServiceCallException (
330333 GRPC_FAILED_PRECONDITION,
@@ -678,7 +681,7 @@ mutable struct gRPCCURL
678681 running:: Bool
679682 requests:: Vector{gRPCRequest}
680683 # Allows for controlling the maximum number of concurrent gRPC requests/streams
681- sem :: Semaphore
684+ events :: Channel{Event}
682685
683686 function gRPCCURL (max_streams = GRPC_MAX_STREAMS)
684687 grpc = new (
@@ -689,9 +692,14 @@ mutable struct gRPCCURL
689692 ReentrantLock (),
690693 true ,
691694 Vector {gRPCRequest} (),
692- Semaphore (max_streams),
695+ Channel {Event} (max_streams),
693696 )
694697
698+ # We use a channel as a Semaphore which also acts as a way to reuse Events to reduce allocations
699+ for _ = 1 : max_streams
700+ put! (grpc. events, Event ())
701+ end
702+
695703 preserve_handle (grpc)
696704
697705 grpc_multi_init (grpc)
@@ -745,9 +753,13 @@ function Base.open(grpc::gRPCCURL)
745753 grpc. watchers = Dict {curl_socket_t,CURLWatcher} ()
746754 end
747755
756+ grpc. events = Channel {Event} (grpc. events. sz_max)
757+ for _ = 1 : grpc. events. sz_max
758+ put! (grpc. events, Event ())
759+ end
760+
748761 grpc. requests = Vector {gRPCRequest} ()
749762 grpc. timer = nothing
750- grpc. sem = Semaphore (grpc. sem. sem_size)
751763
752764 grpc. running = true
753765 grpc_multi_init (grpc)
@@ -756,6 +768,13 @@ function Base.open(grpc::gRPCCURL)
756768 end
757769end
758770
771+ max_reqs_dec (grpc:: gRPCCURL ) = take! (grpc. events)
772+ function max_reqs_inc (grpc:: gRPCCURL , req:: gRPCRequest )
773+ # Reset before we recycle
774+ reset (req. curl_done_reading)
775+ put! (grpc. events, req. curl_done_reading)
776+ end
777+
759778function cleanup_request (grpc:: gRPCCURL , req:: gRPCRequest )
760779 # First remove from the multi
761780 curl_multi_remove_handle (grpc. multi, req. easy)
@@ -766,7 +785,7 @@ function cleanup_request(grpc::gRPCCURL, req::gRPCRequest)
766785 # Allow this to be GC now that there is no risk of use in C callback
767786 unpreserve_handle (req)
768787 # Increment the request semaphore to allow more requests through
769- release (grpc. sem )
788+ max_reqs_inc (grpc, req )
770789 # Unblock anything waiting on the request
771790 notify (req. ready)
772791end
0 commit comments