qianye1001 opened a new issue, #10400:
URL: https://github.com/apache/rocketmq/issues/10400

   ### Before Creating the Enhancement Request
   
   - [x] I have confirmed that this should be classified as an enhancement 
rather than a bug/feature.
   
   ### Summary
   
   `MQVersion.getVersionDesc(int)` and `MQVersion.value2Version(int)` call 
`Version.values()` repeatedly (6 times total, 2-3 times per method invocation) 
without caching the result. Since Java's `Enum.values()` returns a **new 
defensive copy** of the internal array on every call, and the `Version` enum 
currently contains **450+ constants**, each invocation allocates and populates 
a large array unnecessarily.
   
   ### Motivation
   
   - **Unnecessary allocation on hot paths**: These two methods are invoked 
from broker metrics reporting (`BrokerMetricsManager`), admin processors, 
client factories, proxy pipelines, namesrv request processing, and more — 
roughly **21 call sites** across the codebase (excluding tests). In 
high-throughput scenarios, the repeated array copying adds up.
   - **Well-known Java enum anti-pattern**: Calling `values()` without caching 
is a widely recognized performance pitfall in Java. Many projects (including 
the JDK itself) cache the result in a `private static final` field.
   - **Easy win**: The fix is trivial and risk-free — a one-line static field 
addition — but the impact is meaningful given the enum size and call frequency.
   
   ### Describe the Solution You'd Like
   
   Add a cached static array and rewrite the two methods to use it:
   
   ```java
   public class MQVersion {
   
       public static final int CURRENT_VERSION = Version.V5_5_0.ordinal();
   
       private static final Version[] VERSION_VALUES = Version.values();
   
       public static String getVersionDesc(int value) {
           if (value >= VERSION_VALUES.length) {
               return VERSION_VALUES[VERSION_VALUES.length - 1].name();
           }
           return VERSION_VALUES[value].name();
       }
   
       public static Version value2Version(int value) {
           if (value >= VERSION_VALUES.length) {
               return VERSION_VALUES[VERSION_VALUES.length - 1];
           }
           return VERSION_VALUES[value];
       }
   
       // ... enum Version unchanged ...
   }
   ```
   
   This eliminates all 6 `values()` calls, replacing them with a single static 
initialization.
   
   ### Describe Alternatives You've Considered
   
   1. **Cache inside each method with a local variable** — reduces allocations 
from 2-3 per call to 1 per call, but still allocates on every invocation. A 
static field is strictly better since the enum is immutable.
   2. **Use an `EnumMap` or ordinal-indexed `Map`** — over-engineered for this 
use case. Direct array indexing by ordinal is already the natural and most 
efficient approach, which is exactly what `values()` returns.
   
   ### Additional Context
   
   File: `common/src/main/java/org/apache/rocketmq/common/MQVersion.java`
   
   The same pattern (`MessageVersion.values()` without caching) also exists in 
`common/src/main/java/org/apache/rocketmq/common/message/MessageVersion.java:74`,
 though with a much smaller enum. It may be worth addressing both in the same 
PR.


-- 
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]

Reply via email to