Aias00 opened a new issue, #7828: URL: https://github.com/apache/shenyu/issues/7828
### Description The in-memory cache backend performs redundant lookups and schedules every read result on `Schedulers.boundedElastic()`, although the work is entirely local map access. This adds scheduler work to the response-cache hit path. Confirmed in the current working revision (`04f7c2e8b7d282f14510157a9ab0bfaab538ecac`, 2.7.2-SNAPSHOT) and the same implementation on upstream `master` inspected during reporting (`7cc1818ace246f60a608e44b5fe985dff46908e7`). ### Code evidence [`MemoryCache.isExist()`](https://github.com/apache/shenyu/blob/7cc1818ace246f60a608e44b5fe985dff46908e7/shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-memory/src/main/java/org/apache/shenyu/plugin/cache/memory/MemoryCache.java#L65-L72) executes `mainCache.get(key)` and `cache.asMap().containsKey(key)` eagerly on the calling thread, then wraps the already-computed boolean with: ```java Mono.fromCallable(() -> Boolean.TRUE).subscribeOn(Schedulers.boundedElastic()) ``` The miss path schedules `Boolean.FALSE` in the same way. Consequently, subscribing to the read schedules a constant result on the bounded-elastic pool even though the existence check has already completed. [`MemoryCache.getData()`](https://github.com/apache/shenyu/blob/7cc1818ace246f60a608e44b5fe985dff46908e7/shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-memory/src/main/java/org/apache/shenyu/plugin/cache/memory/MemoryCache.java#L82-L88) delegates to `isExist()` and then repeats both lookups on a hit: ```java return isExist(key).mapNotNull(exist -> { if (exist) { return this.mainCache.get(key).asMap().get(key); } return null; }); ``` A successful read therefore performs two outer-map lookups, an inner existence check, an inner value lookup, and a scheduler submission. `cacheData()` similarly schedules an already-computed `Boolean.TRUE` after performing the in-memory write eagerly. This report concerns the remaining backend overhead per read. The current response-cache handler already reads one encoded response entry; it does not separately fetch the response body and Content-Type. ### Expected behavior / suggested direction Keep pure in-memory operations on the subscribing thread without an unconditional bounded-elastic handoff. Obtain the inner cache once and retrieve its value directly, using that result to distinguish a hit from a miss. A lazy publisher such as `Mono.fromCallable(...)` without `subscribeOn(...)` can defer the actual lookup until subscription. Preserve the existing contract: missing/expired entries yield an empty `Mono`, `isExist()` yields a boolean, per-entry TTL remains effective, and cleanup must not remove a concurrently replaced entry. This optimization does not require changing the Redis backend or adding dependencies. ### Task List - [ ] Remove unnecessary bounded-elastic scheduling from pure in-memory operations. - [ ] Consolidate the read path to avoid existence-check-then-read duplicate lookups. - [ ] Verify hit, miss, expiry, replacement/concurrent access, and subscription-time behavior. - [ ] Check that subscriptions from a named caller scheduler do not introduce a bounded-elastic hop. - [ ] If reporting latency or throughput gains, measure them with a reproducible cache-hit workload. ### Validation and related work The scheduling and lookup behavior above is confirmed by source inspection. No throughput benchmark was run, and this report does not claim a measured performance gain or a high-severity correctness failure. Related: #7713 describes retention of expired per-key cache objects. That issue concerns expiry/index ownership; this task concerns scheduler overhead and redundant reads, and any implementation should account for overlapping changes to `MemoryCache`. -- 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]
