lizining1231 opened a new issue, #3675:
URL: https://github.com/apache/dubbo-go/issues/3675

   ### Summary
   
   In `tools/benchmark/client/engine/engine.go`, `Stop()` cancels the parent 
context **before** draining in-flight requests, causing exactly `concurrency` 
requests to be recorded as `context canceled` failures on every benchmark 
teardown. In low-QPS scenarios (1MiB payload), the failure rate reaches 0.86%, 
distorting the success-rate metric.
   
   ### Affected Locations
   
   | Package                       | Related Source                             
                                                                                
                            |
   | ----------------------------- | 
------------------------------------------------------------------------------------------------------------------------------------------------------
 |
   | tools/benchmark/client/engine | 
<https://github.com/apache/dubbo-go/blob/develop/tools/benchmark/client/engine/engine.go#L114-L121>
 |
   
   ### Reproduction
   
   ```bash
   # 1MiB payload + 10s short test to amplify the effect
   cd tools/benchmark && \
   bash scripts/run_single.sh dubbo-go 1048576 protobuf none 50 unary \
     2>&1 | tee data/logs/reproduce_1mib.log
   
   # Check the failure count
   grep -c 'lastErr=canceled: context canceled' data/logs/reproduce_1mib.log
   
   # Observe: Failure equals exactly 50 (concurrency), logs flooded with 
lastErr=canceled: context canceled
   ```
   
   ```bash
   ========================================
             Benchmark Report
   ========================================
   QPS:             116.43
   Success Rate:    99.29%
   Total Requests:  7044
   Success:         6994
   Failure:         50
   
   lizining@Y:~/projects/dubbo-go/tools/benchmark$ grep -c 'lastErr=canceled: 
context canceled' data/logs/reproduce_1mib.log
   50
   ```
   
   <br />
   
   ### Root Cause
   
   ```go
   // 
https://github.com/apache/dubbo-go/blob/develop/tools/benchmark/client/engine/engine.go#L114-L121
   func (e *Engine) Stop() {
       e.stopOnce.Do(func() {
           close(e.stopChan)  // ① prevent new requests
           e.cancel()         // ② cancel parent ctx
           e.wg.Wait()        // ③ wait for workers
       })
   }
   ```
   
   50 workers each have one in-flight request executing. Step ② cancels all 50 
child contexts, each returning `context canceled`. The worker at L108 records 
the error via `e.metricsCollector.Record(duration, err)`. With 128B (260K total 
requests), 50 failures = 0.018%; with 1MiB (5,800 total requests), 50 failures 
= 0.86%.
   
   ### Proposed Fix
   
   Swap `e.cancel()` and `e.wg.Wait()` — drain in-flight requests before 
canceling:
   
   ```go
   func (e *Engine) Stop() {
       e.stopOnce.Do(func() {
           close(e.stopChan)  // ① prevent new requests
           e.wg.Wait()        // ② wait for all in-flight requests to complete 
naturally
           e.cancel()         // ③ cleanup (no workers remaining)
           logger.Info("[INFO] Benchmark completed")
       })
   }
   ```
   
   - No deadlock risk: `benchmarkFunc(ctx)` has a `requestTimeout` safety bound 
(default 30s)
   - No race: `stopOnce.Do` guards against double execution
   - Test duration may extend by `max(in-flight request duration)` (\~1s for 
1MiB, negligible for 128B), which is correct behavior, benchmarks should 
measure full request lifecycles, not truncate the last batch
   
   ### Verification
   
   ```bash
   # Before fix: failure = 50
   bash scripts/run_single.sh dubbo-go 1048576 protobuf none 50 unary 10s
   # Expected: Failure: 50, Success Rate: ~99.27%
   
   # After fix: failure = 0
   bash scripts/run_single.sh dubbo-go 1048576 protobuf none 50 unary 10s
   # Expected: Failure: 0, Success Rate: 100.00%
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to