Rangsh commented on issue #12266:
URL: https://github.com/apache/seatunnel/issues/12266#issuecomment-5854038311

   ## Claim + revised design (storage-first)
   
   Hi @SEZ9 @DanielLeens @CryoThrust — thanks for the earlier discussion on 
this follow-up.
   
   As the issue author, I'll take this one and open a separate PR once we align 
on the approach below. I agree with @DanielLeens: this should stay in design 
until there is a **storage-level** way to verify selected keys without 
retaining the full keyspace in heap. Benchmark-only chunking / adaptive heap 
estimates / a parameterized full `loadAll` are not sufficient on the current 
file-backed path, so I am **not** pursuing those.
   
   @CryoThrust — thank you for offering to help. Your adaptive / chunked / 
parameterized directions were a useful starting point; after Daniel's 
clarification I'm steering this toward a narrow storage contract instead. 
Collaboration on review/tests for that direction is still very welcome — please 
say if you already have in-progress work on the same storage path so we don't 
duplicate.
   
   ### Why the current API blocks the acceptance criteria
   
   Today Hazelcast `IMap.loadAll(keys, …)` ends up in:
   
   - `FileMapStore.loadAll(Collection keys)` → always `mapStorage.loadAll()` → 
then filters in memory
   - `IMapStorage` exposes only whole-map `loadAll()`
   - so requesting one key or the full growth batch has the **same 
retained-heap shape**: the complete map is materialized first
   
   That matches the OOM we hit under `initialStoredJobCount=1000` in #12173, 
and why mid-trial full reload had to be abandoned there.
   
   Importantly, the file reader stack already has the selective primitive we 
need:
   
   - `WALReader.loadAllData(path, searchKeys)`
   - `LatestMutationAccumulator` drops non-matching keys before retention
   - `WALReaderAndWriterTest#shouldRetainOnlyRequestedKeysWhileScanning` 
already pins the reader behavior
   - `DefaultReader` streams record-by-record (it does not slurps the whole 
file into one giant buffer)
   
   The gap is that `IMapFileStorage` / `FileMapStore` never pass the requested 
keys into that path (`IMapFileStorage.loadAll()` currently calls 
`loadAllData(..., new HashSet<>())`, which is treated as “load everything”).
   
   ### Proposed approach
   
   #### Phase A — storage contract (required first)
   
   1. Add an additive keyed load on `IMapStorage`, with a **default** 
implementation that preserves today's behavior for unknown implementers 
(SPI-safe), e.g. `loadAll(Collection<Object> keys)` defaulting to full 
`loadAll()` + filter.
   2. Override in `IMapFileStorage` to call `WALReader.loadAllData(path, keys)` 
for a non-empty key set (true selective retention).
   3. Change `FileMapStore.loadAll(Collection keys)` to call the keyed storage 
API instead of whole-map `loadAll()`.
   4. Update `NoOpMapStorage` accordingly.
   5. Tests must prove the contract, not only the happy path:
      - many filler keys + few targets → only targets returned
      - deterministic coverage that the file implementation uses the filtered 
path (not full materialize-then-filter)
      - an explicit memory/regression guard aimed at the 
`initialStoredJobCount=1000` growth pressure shape (unit coverage + a 
Diagnostics / local `-Xmx` smoke if needed)
   
   **Precise memory claim (please hold me to this wording):**  
   Phase A does **not** claim “never touches the WAL”. The WAL is still scanned 
sequentially (time remains O(WAL)). What changes is retained heap: from O(all 
unique keys) down to O(|requested keys|). Transient per-record deserialize of 
non-matching frames can still occur; skipping value deserialize for non-matches 
can be a later optimization if still needed. I believe this is the 
“materialize” bound Daniel asked for.
   
   #### Phase B — benchmark harness (only after Phase A)
   
   Once Phase A is green:
   
   - Widen `IMapJobGrowthBenchmarkWorkload` durability sampling from one 
representative key to the **full growth batch** via `IMap.loadAll(batchKeys, 
true)` (or equivalent), asserting every batch key is durable from MapStore — 
not only resident.
   - Keep verification **outside** measured SingleShot time.
   - Preserve the existing first empty-pressure + trial tear-down sampling 
windows unless we find a safer mid-trial strategy that still respects the heap 
budget.
   
   Phase B can land in the same PR after Phase A tests, or as a tight follow-up 
PR on top of A — either is fine with me; I’d slightly prefer one PR if A’s 
tests already prove the memory bound.
   
   ### Explicit non-goals for the first PR
   
   - Benchmark-layer chunk loops over today’s `FileMapStore.loadAll`
   - Heuristic / adaptive heap estimates
   - A “full loadAll” feature flag as a substitute for the keyed contract
   - WAL indexing / random seek
   - In-process writer reopen (unrelated)
   
   ### Ask before coding
   
   Does this direction look right?
   
   In particular:
   1. OK to treat Phase A as “keyed load through existing `searchKeys` 
retention” with the precise scan-vs-retain wording above?
   2. Prefer `loadAll(Collection)` overload with SPI `default`, or a 
differently named method?
   3. OK to include Phase B in the same PR once A’s tests pass?
   
   I will **not** start coding until this design is confirmed. After agreement 
I’ll open the PR and link it here.


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