HIVE-29820: Refactor and improve ObjectCache in some RecordProcessors - #6709
Open
abstractdog wants to merge 1 commit into
Open
HIVE-29820: Refactor and improve ObjectCache in some RecordProcessors#6709abstractdog wants to merge 1 commit into
abstractdog wants to merge 1 commit into
Conversation
| return Utilities.getMapWork(jconf); | ||
| } | ||
| }); | ||
| MapWork mapWork = (MapWork) planCache.retrieve(MAP_PLAN_KEY, (Callable<Object>) () -> Utilities.getMapWork(jconf)); |
Contributor
There was a problem hiding this comment.
nit: Extra casting ? in other hunks, the Callable / MapWork is not present in retrieve().
MapWork mapWork = planCache.retrieve(MAP_PLAN_KEY, () -> Utilities.getMapWork(jconf));
Contributor
There was a problem hiding this comment.
I just did java level review, The LLAP is not my forte.
Contributor
Author
|
UPDATE: mass test failures prove pretty well that HIVE-14433 is still valid, we cannot cache MapWork/ReduceWork until we don't take care of separating what's specific to each instance and mutable: work objects contain the whole operator pipeline, containing paths, etc. |
abstractdog
force-pushed
the
HIVE-29820-objectcache
branch
from
August 21, 2026 10:25
28334fc to
278e596
Compare
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What changes were proposed in this pull request?
TrackedCachenested class inRecordProcessorthat pairs anObjectCachewith the list of keys retrieved through it, replacing the parallelcache + cacheKeysanddynamicValueCache + dynamicValueCacheKeysfield pattern.MapRecordProcessor,ReduceRecordProcessor, andMergeFileRecordProcessorretrieve plans through the wrapper, andreleaseCache()at close time releases every tracked key.ObjectCacheFactory.getLlapObjectCache: removes a duplicate import, and swaps the get/putIfAbsent/log dance forcomputeIfAbsentwithObjects.requireNonNull.mr.ObjectCacheon LLAP — the safe default. See the note below on why plan sharing across fragments is deferred.Why are the changes needed?
The wrapper class removes the two parallel-list bookkeeping pattern that had drifted between subclasses and made "which cache owns this key" hard to see at the call sites. It's the seam a future daemon-wide plan-sharing change would need.
Plan sharing across concurrent fragments on LLAP
An earlier iteration of this PR routed the plan cache through the daemon-wide
LlapObjectCache(ObjectCacheFactory.getCache(..., isPlanCache=true, llapCacheAlwaysEnabled=true)) so N concurrent fragments would share one deserialisedMapWork/ReduceWorkinstead of each running Kryo. Verifying againstTestMiniLlapLocalCliDriver -Dqfile=acid_globallimit.q— which failed deterministically withFileAlreadyExistsException: .../acidtest1/delta_0000001_0000001_0000/bucket_00000_0and NPEs inOperator.initialize— showed this is unsafe today: operator trees in everyRecordProcessorsubclass carry per-fragment mutable state thatinitializeOp()resets (FileSinkOperator.fsp,VectorGroupByOperator.aggregator,Operator.childOperatorsArray,VectorTopNKeyOperator's per-instance filter state, ...), and sharing the operator tree across concurrent fragments races on those fields — the HIVE-14433 class of failure.Selective sharing (Map-only, per Reduce/MergeFile's own state) also failed the same qtest 2/2 with a
VectorHashKeyWrapperBase.isNullNPE insideTopNKeyFilter.compareWithBoundary— Map-side operator trees carry per-fragment state too.Kept off until an operator-tree refactor separates the plan descriptor from per-fragment state. The trap is documented on
RecordProcessor#planCacheso it doesn't have to be rediscovered.Does this PR introduce any user-facing change?
No. Internal refactor. Runtime behaviour is unchanged from pre-refactor: each processor deserialises its own plan.
How was this patch tested?
New unit test
TestRecordProcessor:retrieveReturnsUnderlyingValue—TrackedCache.retrieveis a pure pass-through to the underlyingObjectCache.planAndDynamicValueCachesAreIndependent— releasing one wrapper never touches the other.plansAreNotSharedAcrossProcessorsOnLlap— drives the real production path withLlapProxy.setDaemon(true), constructs twoRecordProcessorinstances through the production constructor, and asserts each loads its own plan (loader fires twice, results are distinct). Guards against the plan cache being re-flipped tollapCacheAlwaysEnabled=truewithout a matching operator-tree fix.Also verified
TestMiniLlapLocalCliDriver -Dqfile=acid_globallimit.q— deterministic failure on the earlier iteration, green on this PR.