membphis commented on PR #14141:
URL: https://github.com/apache/apisix/pull/14141#issuecomment-6623017268
@AlinsRan, I completed an independent local before/after run against base
`6205e4a568106eea8277f61ae6ef942bbff62d97` and PR head
`1e8b72e1ae8cf63197ab45659137442925e077a8`.
### P2: the limiter-object cache regresses high-cardinality dynamic quotas
The stable-quota case improves, but cycling through 4,096 valid resolved
counts makes the new 1,024-entry limiter cache churn. Throughput fell in all
eight paired runs, by 11.3% to 22.7%.
| Scenario / metric | Before | After | Change |
| --- | ---: | ---: | ---: |
| Stable resolved count, requests/sec | 15,106 | 18,293 | +21.1% |
| 4,096 rotating counts, requests/sec | 14,902 | 11,926 | -20.0% |
| 4,096 rotating counts, worker CPU per request | 66.81 us | 83.47 us |
+24.9% |
| Stable count, Lua allocation per request | 11,698 B | 2,193 B | -81.3% |
| Rotating counts, Lua allocation per request | 11,645 B | 2,773 B | -76.2% |
The route uses local policy and one rule:
```json
{"count":"${http_count ??
1000000000}","time_window":60,"key":"${host}:${uri}","header_prefix":"one"}
```
The single wrk thread cycles the `Count` header through `1000000000 + n %
4096`. The URI and rate-limit key stay fixed, and all benchmark requests return
200. This exercises supported request-resolved quotas without exhausting the
counter.
I also ran three diagnostic pairs using a temporary copy of the PR head,
replacing only the [limiter-cache
call](https://github.com/apache/apisix/blob/1e8b72e1ae8cf63197ab45659137442925e077a8/apisix/plugins/limit-count/init.lua#L575)
with `create_limit_obj(conf, rule, name)`. Median throughput recovered from
12,059 to 17,717 requests/sec, and worker CPU fell from 82.57 to 56.18
us/request. The template, header-name and key-prefix caches remained enabled.
This is a merge blocker for workloads whose resolved quota working set
exceeds the cache capacity: the optimization adds significant CPU cost to an
existing request path. Please avoid filling/evicting this cache for low-reuse
dynamic quota values; retaining direct construction for request-derived quotas
is a simple fallback. Keep the other caches and add an above-capacity benchmark
when revising this path.
### Regression coverage
Ran all 29 relevant files: `limit-count*.t`, `graphql-limit-count*.t`,
`proxy-rewrite*.t`, and `t/core/utils.t`.
- Before: 2,263 assertions; after: 2,321 assertions.
- Both revisions passed 28/29 files. The same two existing DNS assertions in
`utils.t` (TEST 9 and TEST 11) failed on this host. All other assertions,
including the new template/cache cases, passed. No new functional failures were
found.
- Redis MONITOR confirmed unchanged command counts per limiter invocation:
fixed window 1 with a warm script / 2 with a cold script; sliding window 2 / 3
respectively. Internal Redis Lua commands were excluded from the network-call
count.
Runtime: the CI-pinned APISIX runtime 1.4.2, with the package SHA256 checked
against the repository's installer. Performance numbers are medians of eight
interleaved before/after pairs, each with a fresh gateway, one worker pinned to
a physical core, a one-second warm-up and a five-second measurement, wrk with
one thread and 100 connections, and a separate mock-upstream core. CPU comes
from the gateway worker's process counters. Lua allocation uses three
2,000-request samples with GC paused only during that measurement.
--
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]