Skip to content

Commit

Permalink
Avoid allocations in DataLoaderHelper.dispatch when there's no work
Browse files Browse the repository at this point in the history
Bail out early in DataLoaderHelper.dispatch when loaderQueue is empty to avoid
unnecessary allocations; additionally, when there is work, size the allocated
Lists precisely based on the loaderQueue size.
  • Loading branch information
kilink committed Nov 10, 2023
1 parent 5f8ec4a commit 6b20182
Showing 1 changed file with 23 additions and 7 deletions.
30 changes: 23 additions & 7 deletions src/main/java/org/dataloader/DataLoaderHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,21 @@ Object getCacheKeyWithContext(K key, Object context) {

DispatchResult<V> dispatch() {
boolean batchingEnabled = loaderOptions.batchingEnabled();
//
// we copy the pre-loaded set of futures ready for dispatch
final List<K> keys = new ArrayList<>();
final List<Object> callContexts = new ArrayList<>();
final List<CompletableFuture<V>> queuedFutures = new ArrayList<>();
final List<K> keys;
final List<Object> callContexts;
final List<CompletableFuture<V>> queuedFutures;
synchronized (dataLoader) {
int queueSize = loaderQueue.size();
if (queueSize == 0) {
lastDispatchTime.set(now());
return emptyDispatchResult();
}

// we copy the pre-loaded set of futures ready for dispatch
keys = new ArrayList<>(queueSize);
callContexts = new ArrayList<>(queueSize);
queuedFutures = new ArrayList<>(queueSize);

loaderQueue.forEach(entry -> {
keys.add(entry.getKey());
queuedFutures.add(entry.getValue());
Expand All @@ -176,8 +185,8 @@ DispatchResult<V> dispatch() {
loaderQueue.clear();
lastDispatchTime.set(now());
}
if (!batchingEnabled || keys.isEmpty()) {
return new DispatchResult<>(completedFuture(emptyList()), 0);
if (!batchingEnabled) {
return emptyDispatchResult();
}
final int totalEntriesHandled = keys.size();
//
Expand Down Expand Up @@ -524,4 +533,11 @@ private CompletableFuture<List<V>> setToValueCache(List<V> assembledValues, List
}
return CompletableFuture.completedFuture(assembledValues);
}

private static final DispatchResult<?> EMPTY_DISPATCH_RESULT = new DispatchResult<>(completedFuture(emptyList()), 0);

@SuppressWarnings("unchecked") // Casting to any type is safe since the underlying list is empty
private static <T> DispatchResult<T> emptyDispatchResult() {
return (DispatchResult<T>) EMPTY_DISPATCH_RESULT;
}
}

0 comments on commit 6b20182

Please sign in to comment.