byteayan opened a new pull request, #3355:
URL: https://github.com/apache/hugegraph/pull/3355

   ## Purpose of the PR
   
   - close #3254
   
   Both shipped `application-pd.yml` files set `rocksdb.total_memory_size: 
32000000000`, and the `pd` profile is always included, so the 
`Runtime.maxMemory()` fallback in `AppConfig.init()` never ran. 
`RaftRocksdbOptions` splits the value into the `WriteBufferManager` cache (66%) 
and the block cache. Both are native `LRUCache`s, so neither `-Xmx` nor the 
container limit bounds them, and a separate 1 GiB raft log cache sits on top. 
In the run in the issue all three Stores were OOM-killed at a 4 GiB limit once 
each held about 1 GB of RocksDB data.
   
   Docker users had no clean way to change it. `docker-entrypoint.sh` builds 
`SPRING_APPLICATION_JSON` from five `HG_STORE_*` keys, and none of them is a 
`rocksdb.*` key. Bind-mounting a config file or passing 
`-Drocksdb.total_memory_size=<bytes>` in `JAVA_OPTS` both work, but neither is 
documented.
   
   As the issue points out, dropping the line from the yml alone would hand 
RocksDB a budget equal to the heap, which is a second heap-sized allocation on 
top of the first.
   
   ## Main Changes
   
   - New `RocksdbMemoryBudget` in `hg-store-core/.../options`. An unset, blank 
or 0 value means auto: half of (physical memory − max heap − 
`MaxDirectMemorySize` − 1.5 GiB reserve), clamped to 256 MiB to 32 GB. The 
reserve covers the raft log cache plus stacks, metaspace and other native 
memory. Physical memory comes from 
`OperatingSystemMXBean.getTotalMemorySize()`, which on JDK 17 reports the 
cgroup v1/v2 limit inside a container. Older JDK 17 updates may not see a limit 
set only on a parent cgroup; those get host memory, as before this change. An 
unset `MaxDirectMemorySize` is counted as the heap size, since that is what the 
JVM allows. If physical memory can't be read, the previous heap-size default 
applies.
     - The issue's setup (4 GiB limit, `-Xmx1g`, 
`-XX:MaxDirectMemorySize=512m`) gets 512 MiB, and an 8 GiB limit gets 2.5 GiB. 
I checked the 4 GiB case with `resolve()` inside `eclipse-temurin:17-jre-jammy` 
under a 4 GiB Docker limit: 536870912 bytes. With `-Xmx2g` and no direct-memory 
cap it lands on the 256 MiB floor. The 32 GB cap means no host gets a bigger 
budget than before.
     - A positive value is used unchanged, with one exception: values under 1 
MiB are refused. The write buffer manager gets 2/3 of the budget, so `1` would 
give a 0-byte manager, which RocksDB treats as no memtable limit at all. `4GB` 
and other non-numeric values now fail at startup with "must be a number of 
bytes", where before they failed with a bare `NumberFormatException`. Nothing 
shipped (configs, compose files, Helm, CI) sets a value under 1 MiB.
     - Startup logs the chosen value and its inputs. It warns when the 256 MiB 
floor applies (heap plus direct memory already fill the limit), when an 
explicit value is under 256 MiB, and when an explicit value exceeds the memory 
left after the heap, direct memory and the reserve. That last case is what an 
upgraded install with an old mounted `application-pd.yml` will hit.
   - `AppConfig.init()` uses it. While there I fixed the raft disruptor sizing 
for budgets under 1 GB: `log(0)` rounded to a buffer size of 0. It now gives 
32. The formula moved to `RocksdbMemoryBudget.disruptorBufferSize()` so it has 
a test. The shipped `application.yml` pins `disruptorBufferSize: 1024`, so this 
only matters when that key is absent.
   - Both `application-pd.yml` files ship `total_memory_size: 0`, which also 
removes the #3254 TODO from #3260. The test resources keep their explicit 
values.
   - `docker-entrypoint.sh` accepts `HG_STORE_ROCKSDB_TOTAL_MEMORY_SIZE`. 
Values must be digits only; anything else exits with code 2. It is added to 
`SPRING_APPLICATION_JSON` only when set, so an unset variable leaves the config 
file or auto-sizing in charge. When set it outranks both the config file and 
`-Drocksdb.total_memory_size` (checked against Spring Boot 2.5's property 
order).
   - `helm/hugegraph/values-cluster.yaml`: the store comment said container 
limits don't configure the RocksDB budget. It now says how the budget is 
derived (2.5 GiB for that preset) and how to pin it with `store.extraEnv`.
   
   In a small container the write buffer manager now flushes memtables much 
earlier than before, which means more small L0 files and lower write throughput 
in exchange for staying inside the limit. Both caps are soft, so RocksDB can 
still go over briefly under heavy writes. I have not measured either effect. 
Setting the value explicitly restores the old behaviour.
   
   ## Verifying these changes
   
   - [x] Need tests and can be verified as follows:
       - New `RocksdbMemoryBudgetTest` (8 tests, added to `CoreSuiteTest`, 
which the `store-core-test` profile runs). It covers:
         - explicit values kept unchanged, and values under 1 MiB refused;
         - unset, blank, `0` and `00` going to auto;
         - refusal of `4GB`, `-1`, `1.5e9` and a value past `Long.MAX_VALUE`;
         - the 4 GiB and 8 GiB examples above, both clamp bounds, and the 
unknown-physical fallback;
         - the disruptor size for 512 MiB, 1 GB and 32 GB.
       - New `test-store-docker-entrypoint.sh` (9 cases), added to the store 
job in `pd-store-ci.yml`. It checks that the `rocksdb` key is absent when the 
variable is unset or empty, that bytes and `0` pass through, that 
`app.data-path` is still set, and that `4GB`, `-1`, `1.5e9`, `1 2` and `1"}` 
are refused. It clears the variable from the caller's environment first, so 
"unset" really is unset.
       - `mvn test -pl hugegraph-store/hg-store-test -P store-core-test` on JDK 
17: 113 tests, 0 failures. `helm unittest helm/hugegraph`: 294 tests pass. `mvn 
editorconfig:check` and `git diff --check` are clean.
       - Not tested: a full Store started in a memory-limited container, and 
the load from the issue.
       - CI selection gap, left as is: a PR that changes only 
`test-store-docker-entrypoint.sh` doesn't select the store job, because the 
script isn't in `CONTRACT_SUITES` in `.github/scripts/ci-policy.py`. Changing 
the entrypoint itself does select it. The PD entrypoint test has the same gap, 
so I'd rather fix both in one place.
   
   ## Does this PR potentially affect the following parts?
   
   - [ ]  Dependencies ([add/update 
license](https://hugegraph.apache.org/docs/contribution-guidelines/contribute/#321-check-licenses)
 info & 
[regenerate_known_dependencies.sh](../install-dist/scripts/dependency/regenerate_known_dependencies.sh))
   - [x]  Modify configurations
   - [ ]  The public API
   - [ ]  Other affects (typed here)
   - [ ]  Nope
   
   ## Documentation Status
   
   - [x] `Doc - TODO`: required documentation is pending; complete it before 
merging.
   - [ ] `Doc - Done`: documentation is included here or linked below.
   - [ ] `Doc - No Need`: no user-visible documentation is affected.
   
   Documentation files in this PR or paired hugegraph-doc PR:
   - `hugegraph-store/docs/deployment-guide.md`: the auto-sizing rule and its 
inputs, the 1 MiB minimum, the new env var and its precedence in the compose 
and Kubernetes examples, and the RocksDB block (`total_memory_size: 0`; the 
nonexistent `block_cache_size` key replaced with `write_buffer_ratio`).
   - `hugegraph-store/README.md`: the env var in the `docker run` section.
   - Paired apache/hugegraph-doc PR, link to follow: 
`content/{en,cn}/docs/quickstart/hugegraph/hugegraph-hstore.md` (the default, 
the auto-sizing rule and the env var) and 
`content/{en,cn}/docs/guides/hugegraph-docker-cluster.md` (the new `HG_STORE_*` 
row). The hstore page's "checked against Server master commit" note should move 
to this PR's merge commit once both land.
   


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