Skip to content

Conversation

@andimarek
Copy link
Member

@andimarek andimarek commented Oct 18, 2025

This PR removes any usage of Reentrant Lock in DataLoader in favor of using a self made Linked List and updates to it via AtomicReference CAS.

CacheMap change

This is a breaking change for the future cache CacheMap.

In order to avoid any locking

 CacheMap<K, V> set(K key, CompletableFuture<V> value); 

was replaced with

 CompletableFuture<V> setIfAbsent(K key, CompletableFuture<V> value); 

which is required to be atomic (like for example offered by ConcurrendHashMap)

This requirement also means that the underlying cache implementation must support this atomic operation.

Concurrent loads without batching, but with caching

Previously it was guaranteed that for one key with caching enabled and batching disabled, the dispatching only happens once.
Now because we avoid any form on lock this is not guaranteed anymore: there could be unnecessary dispatch calls when concurrent load calls are happening.

TODO: Update tests to avoid Collections.reverse

See https://github.com/graphql-java/java-dataloader/pull/241/files#diff-e44f0238fddb1d168a414ceef18d7194686b83ecf167cb794d2d03e714494c88R259

}


@GuardedBy("lock")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should fix up the @GuardedBy("lock") everywhere - its no longer true

CompletableFuture[] queuedFuturesArray = new CompletableFuture[queueSize];
Object[] callContextsArray = new Object[queueSize];
int index = queueSize - 1;
while (loaderQueueEntryHead != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You dont have t use an array and then asList it. Create the ArrayList and the use java.util.ArrayList#set to set a specific index

The ArrayList is an array under the covers - so tis the same. Actually the performance cost is the same as what you have here but the codes simpler

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also you dont need to calculate queue size if you use ArrayList - but then again its defaults to size 10 - so maybe growing the array is more expensive over time then walking the list twice. We could keep a list size in a voilaitle int say

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to avoid any overhead that comes from arraylist.
Arraylist set throws oob exception and arraylist add with index does array copy

@andimarek andimarek merged commit 05d60ad into master Oct 23, 2025
1 check passed
@andimarek andimarek added this to the 6.0.0 milestone Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

3 participants