79629050

Date: 2025-05-19 15:27:29
Score: 1
Natty:
Report link

After various shielding logic tests, the problem was identified.

The 5% performance difference is mainly due to the different TieredPGO Settings.

The 50% performance loss is due to the BUG of memory leaks in Monitor.Wait(object) and Monitor.Pulse(object) of the AOT mode, Memory leaks have caused abnormal memory usage and the decline of GC performance.

To reduce the operation of new objects in performance-insensitive scenarios, I directly use the RPC request object for Monitor operations to achieve thread synchronization. However, the AOT mode will cause this object to be leaked, resulting in no memory release for all request objects until the relevant thread ends.

After I replaced Monitor with ManualResetEvent to handle the thread synchronization issue, the request object was normally reclaimed, the memory usage returned to normal, and the performance test results also returned to normal.

I guess it's because in the AOT mode, the Monitors related operations save the request object in a certain global set bound to the thread context. After Monitor.Pulse(object) wakes up the synchronous thread, this request object is not removed from this global set, resulting in a memory leak. It can only be released after the thread ends.

Reasons:
  • Long answer (-1):
  • No code block (0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Jin Xiao