@@ -41,6 +41,7 @@ class _BatchRequest:
4141 def __init__ (self , inputs , kwargs ):
4242 self .inputs = inputs
4343 self .kwargs = kwargs
44+ self .enqueued_at = time .monotonic ()
4445 self .event = threading .Event ()
4546 self .result = None
4647 self .error = None
@@ -64,11 +65,14 @@ def __getattr__(self, name):
6465class RealtimeBatchingEngine :
6566 """Serialize the shared engine while batching compatible session requests."""
6667
67- def __init__ (self , engine , batch_wait_ms = 10.0 , max_batch_size = 16 ):
68+ def __init__ (
69+ self , engine , batch_wait_ms = 10.0 , max_batch_size = 16 , log_profile = False
70+ ):
6871 self .engine = engine
6972 self ._engine = getattr (engine , "_engine" , engine )
7073 self .batch_wait_s = max (0.0 , float (batch_wait_ms )) / 1000.0
7174 self .max_batch_size = max (1 , int (max_batch_size ))
75+ self .log_profile = bool (log_profile )
7276 self .requests = queue .Queue ()
7377 self .pending_request = None
7478 self .worker = threading .Thread (
@@ -186,6 +190,7 @@ def _run(self):
186190
187191 def _generate_group (self , requests ):
188192 inputs = [item for request in requests for item in request .inputs ]
193+ started_at = time .monotonic ()
189194 try :
190195 results = self .engine .generate (inputs , ** requests [0 ].kwargs )
191196 if len (results ) != len (inputs ):
@@ -211,6 +216,36 @@ def _generate_group(self, requests):
211216 request .event .set ()
212217 return
213218
219+ if self .log_profile :
220+ queue_waits_ms = sorted (
221+ (started_at - request .enqueued_at ) * 1000 for request in requests
222+ )
223+ midpoint = len (queue_waits_ms ) // 2
224+ if len (queue_waits_ms ) % 2 :
225+ queue_p50_ms = queue_waits_ms [midpoint ]
226+ else :
227+ queue_p50_ms = (
228+ queue_waits_ms [midpoint - 1 ] + queue_waits_ms [midpoint ]
229+ ) / 2
230+ audio_seconds = [
231+ item .shape [- 1 ] / 16000.0
232+ for item in inputs
233+ if isinstance (item , (np .ndarray , torch .Tensor )) and item .ndim > 0
234+ ]
235+ logger .info (
236+ "Realtime decode profile: requests=%d samples=%d "
237+ "audio_sec_total=%.3f audio_sec_min=%.3f audio_sec_max=%.3f "
238+ "queue_ms_p50=%.3f queue_ms_max=%.3f engine_ms=%.3f" ,
239+ len (requests ),
240+ len (inputs ),
241+ sum (audio_seconds ),
242+ min (audio_seconds , default = 0.0 ),
243+ max (audio_seconds , default = 0.0 ),
244+ queue_p50_ms ,
245+ queue_waits_ms [- 1 ],
246+ (time .monotonic () - started_at ) * 1000 ,
247+ )
248+
214249 offset = 0
215250 for request in requests :
216251 end = offset + len (request .inputs )
@@ -1158,6 +1193,7 @@ def load_models(args):
11581193 engine ,
11591194 batch_wait_ms = getattr (args , "decode_batch_wait_ms" , 10.0 ),
11601195 max_batch_size = getattr (args , "decode_max_batch_size" , 16 ),
1196+ log_profile = getattr (args , "log_decode_profile" , False ),
11611197 )
11621198
11631199 _asr_kwargs = {}
@@ -1451,6 +1487,14 @@ def build_arg_parser():
14511487 default = 16 ,
14521488 help = "Maximum number of audio segments submitted in one batched decode." ,
14531489 )
1490+ parser .add_argument (
1491+ "--log-decode-profile" ,
1492+ action = "store_true" ,
1493+ help = (
1494+ "Log per-engine-batch request counts, audio durations, queue wait, "
1495+ "and engine latency for performance investigations."
1496+ ),
1497+ )
14541498 parser .add_argument (
14551499 "--endpoint-mode" ,
14561500 choices = ["server" , "client" ],
0 commit comments