Skip to content

Commit 416217d

Browse files
Annie LiangCopilot
andcommitted
perf: eliminate UnmodifiableList overhead and add HttpHeaders toLowerCase fast-path
Change 1: Replace vendored UnmodifiableList with Collections.unmodifiableList() - UnmodifiableList wraps via 4-level virtual dispatch chain (UnmodifiableList -> AbstractSerializableListDecorator -> AbstractListDecorator -> AbstractCollectionDecorator) - AbstractListDecorator.decorated() called on every list operation accounts for ~1.02% CPU (398 samples at 1t-c128) - Collections.unmodifiableList() returns a simple wrapper that JIT can inline efficiently Change 2: Add isAsciiLowerCase fast-path in HttpHeaders - HTTP/2 headers are already lowercase per protocol spec - Most x-ms-* custom headers are already lowercase - Skip String.toLowerCase(Locale.ROOT) when string is already all-lowercase via simple char range check - StringLatin1.toLowerCase accounts for ~1.29% CPU (500 samples) Files changed: - LocationCache.java: field types + return types + constructors - GlobalEndpointManager.java: return types - ClientRetryPolicy.java: variable type - GlobalPartitionEndpointManagerForPerPartitionCircuitBreaker.java: variable types - HttpHeaders.java: set() and getHeader() fast-path Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 86ee3c0 commit 416217d

12 files changed

Lines changed: 132 additions & 129 deletions

sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/GlobalPartitionEndpointManagerForPPAFUnitTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import com.azure.cosmos.implementation.ResourceType;
1515
import com.azure.cosmos.implementation.RxDocumentServiceRequest;
1616
import com.azure.cosmos.implementation.SerializationDiagnosticsContext;
17-
import com.azure.cosmos.implementation.apachecommons.collections.list.UnmodifiableList;
1817
import com.azure.cosmos.implementation.guava25.collect.ImmutableList;
1918
import com.azure.cosmos.implementation.perPartitionAutomaticFailover.GlobalPartitionEndpointManagerForPerPartitionAutomaticFailover;
2019
import com.azure.cosmos.implementation.perPartitionAutomaticFailover.PartitionLevelAutomaticFailoverInfo;
@@ -87,12 +86,12 @@ public void beforeClass() {
8786
.collect(Collectors.toList());
8887

8988
Mockito.when(this.singleWriteAccountGlobalEndpointManagerMock.getAvailableReadRoutingContexts()).thenReturn(availableReadRegionalRoutingContexts);
90-
Mockito.when(this.singleWriteAccountGlobalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(new UnmodifiableList<>(availableReadRegionalRoutingContexts));
89+
Mockito.when(this.singleWriteAccountGlobalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(availableReadRegionalRoutingContexts));
9190
Mockito.when(this.singleWriteAccountGlobalEndpointManagerMock.canUseMultipleWriteLocations()).thenReturn(false);
9291
Mockito.when(this.singleWriteAccountGlobalEndpointManagerMock.canUseMultipleWriteLocations(Mockito.any())).thenReturn(false);
9392

9493
Mockito.when(this.multiWriteAccountGlobalEndpointManagerMock.getAvailableReadRoutingContexts()).thenReturn(availableReadRegionalRoutingContexts);
95-
Mockito.when(this.multiWriteAccountGlobalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(new UnmodifiableList<>(availableReadRegionalRoutingContexts));
94+
Mockito.when(this.multiWriteAccountGlobalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(availableReadRegionalRoutingContexts));
9695
Mockito.when(this.multiWriteAccountGlobalEndpointManagerMock.canUseMultipleWriteLocations()).thenReturn(true);
9796
Mockito.when(this.multiWriteAccountGlobalEndpointManagerMock.canUseMultipleWriteLocations(Mockito.any())).thenReturn(true);
9897
}

sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/GlobalPartitionEndpointManagerForPPCBUnitTests.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import com.azure.cosmos.implementation.ResourceType;
1515
import com.azure.cosmos.implementation.RxDocumentServiceRequest;
1616
import com.azure.cosmos.implementation.SerializationDiagnosticsContext;
17-
import com.azure.cosmos.implementation.apachecommons.collections.list.UnmodifiableList;
1817
import com.azure.cosmos.implementation.perPartitionAutomaticFailover.PerPartitionAutomaticFailoverInfoHolder;
1918
import com.azure.cosmos.implementation.perPartitionCircuitBreaker.GlobalPartitionEndpointManagerForPerPartitionCircuitBreaker;
2019
import com.azure.cosmos.implementation.perPartitionCircuitBreaker.LocationHealthStatus;
@@ -214,8 +213,8 @@ public void recordHealthyToHealthyWithFailuresStatusTransition(String partitionL
214213
maxExclusive,
215214
LocationEastUs2EndpointToLocationPair.getKey());
216215

217-
Mockito.when(this.globalEndpointManagerMock.getReadEndpoints()).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
218-
Mockito.when(this.globalEndpointManagerMock.getWriteEndpoints()).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
216+
Mockito.when(this.globalEndpointManagerMock.getReadEndpoints()).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
217+
Mockito.when(this.globalEndpointManagerMock.getWriteEndpoints()).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
219218

220219
globalPartitionEndpointManagerForCircuitBreaker
221220
.handleLocationExceptionForPartitionKeyRange(request, new RegionalRoutingContext(LocationEastUs2EndpointToLocationPair.getKey()), false);
@@ -284,8 +283,8 @@ public void recordHealthyWithFailuresToUnavailableStatusTransition(String partit
284283
maxExclusive,
285284
LocationEastUs2EndpointToLocationPair.getKey());
286285

287-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
288-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
286+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
287+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
289288

290289
int exceptionCountToHandle
291290
= globalPartitionEndpointManagerForCircuitBreaker.getConsecutiveExceptionBasedCircuitBreaker().getAllowedExceptionCountToMaintainStatus(LocationHealthStatus.HealthyWithFailures, readOperationTrue);
@@ -361,8 +360,8 @@ public void recordUnavailableToHealthyTentativeStatusTransition(String partition
361360
maxExclusive,
362361
LocationEastUs2EndpointToLocationPair.getKey());
363362

364-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
365-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
363+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
364+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
366365

367366
int exceptionCountToHandle
368367
= globalPartitionEndpointManagerForCircuitBreaker.getConsecutiveExceptionBasedCircuitBreaker().getAllowedExceptionCountToMaintainStatus(LocationHealthStatus.HealthyWithFailures, readOperationTrue);
@@ -449,8 +448,8 @@ public void recordHealthyTentativeToHealthyStatusTransition(String partitionLeve
449448
maxExclusive,
450449
LocationEastUs2EndpointToLocationPair.getKey());
451450

452-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
453-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
451+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
452+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
454453

455454
int exceptionCountToHandle
456455
= globalPartitionEndpointManagerForCircuitBreaker.getConsecutiveExceptionBasedCircuitBreaker().getAllowedExceptionCountToMaintainStatus(LocationHealthStatus.HealthyWithFailures, readOperationTrue);
@@ -545,8 +544,8 @@ public void recordHealthyTentativeToUnavailableTransition(String partitionLevelC
545544
maxExclusive,
546545
LocationEastUs2EndpointToLocationPair.getKey());
547546

548-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
549-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
547+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
548+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
550549

551550
int exceptionCountToHandle
552551
= globalPartitionEndpointManagerForCircuitBreaker.getConsecutiveExceptionBasedCircuitBreaker().getAllowedExceptionCountToMaintainStatus(LocationHealthStatus.HealthyWithFailures, readOperationTrue);
@@ -639,8 +638,8 @@ public void allRegionsUnavailableHandling(String partitionLevelCircuitBreakerCon
639638
maxExclusive,
640639
LocationEastUs2EndpointToLocationPair.getKey());
641640

642-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
643-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
641+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
642+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
644643

645644
int exceptionCountToHandle
646645
= globalPartitionEndpointManagerForCircuitBreaker
@@ -724,8 +723,8 @@ public void multiContainerBothWithSinglePartitionHealthyToUnavailableHandling(St
724723
maxExclusive,
725724
LocationEastUs2EndpointToLocationPair.getKey());
726725

727-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
728-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
726+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
727+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
729728

730729
int exceptionCountToHandle
731730
= globalPartitionEndpointManagerForCircuitBreaker.getConsecutiveExceptionBasedCircuitBreaker().getAllowedExceptionCountToMaintainStatus(LocationHealthStatus.HealthyWithFailures, readOperationTrue);
@@ -821,8 +820,8 @@ public void allRegionsUnavailableHandlingWithMultiThreading(String partitionLeve
821820
.map(uriStringPair -> new RegionalRoutingContext(uriStringPair.getLeft()))
822821
.collect(Collectors.toList());
823822

824-
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
825-
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn((UnmodifiableList<RegionalRoutingContext>) UnmodifiableList.unmodifiableList(applicableReadWriteEndpoints));
823+
Mockito.when(this.globalEndpointManagerMock.getApplicableWriteRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
824+
Mockito.when(this.globalEndpointManagerMock.getApplicableReadRegionalRoutingContexts(Mockito.anyList())).thenReturn(Collections.unmodifiableList(applicableReadWriteEndpoints));
826825

827826
RxDocumentServiceRequest requestCentralUs = constructRxDocumentServiceRequestInstance(
828827
readOperationTrue ? OperationType.Read : OperationType.Create,

sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/ProactiveConnectionManagementTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import com.azure.cosmos.implementation.RxDocumentServiceRequest;
1616
import com.azure.cosmos.implementation.TestConfigurations;
1717
import com.azure.cosmos.implementation.Utils;
18-
import com.azure.cosmos.implementation.apachecommons.collections.list.UnmodifiableList;
1918
import com.azure.cosmos.implementation.apachecommons.lang.tuple.ImmutablePair;
2019
import com.azure.cosmos.implementation.caches.AsyncCache;
2120
import com.azure.cosmos.implementation.caches.AsyncCacheNonBlocking;
@@ -181,7 +180,7 @@ public void openConnectionsAndInitCachesWithContainer(ProactiveConnectionManagem
181180

182181
cosmosAsyncContainer.openConnectionsAndInitCaches(proactiveConnectionRegionCount).block();
183182

184-
UnmodifiableList<RegionalRoutingContext> readEndpoints =
183+
List<RegionalRoutingContext> readEndpoints =
185184
globalEndpointManager.getReadEndpoints();
186185

187186
List<URI> proactiveConnectionEndpoints = readEndpoints.subList(
@@ -345,7 +344,7 @@ public void openConnectionsAndInitCachesWithCosmosClient_And_PerContainerConnect
345344
ConcurrentHashMap<String, ?> routingMap = getRoutingMap(rxDocumentClient);
346345
ConcurrentHashMap<String, ?> collectionInfoByNameMap = getCollectionInfoByNameMap(rxDocumentClient);
347346
Set<String> endpoints = ConcurrentHashMap.newKeySet();
348-
UnmodifiableList<RegionalRoutingContext> readEndpoints = globalEndpointManager.getReadEndpoints();
347+
List<RegionalRoutingContext> readEndpoints = globalEndpointManager.getReadEndpoints();
349348

350349
List<URI> proactiveConnectionEndpoints = readEndpoints.subList(
351350
0,
@@ -495,7 +494,7 @@ public void openConnectionsAndInitCachesWithCosmosClient_And_PerContainerConnect
495494
ConcurrentHashMap<String, ?> routingMap = getRoutingMap(rxDocumentClient);
496495
ConcurrentHashMap<String, ?> collectionInfoByNameMap = getCollectionInfoByNameMap(rxDocumentClient);
497496
Set<String> endpoints = ConcurrentHashMap.newKeySet();
498-
UnmodifiableList<RegionalRoutingContext> readEndpoints = globalEndpointManager.getReadEndpoints();
497+
List<RegionalRoutingContext> readEndpoints = globalEndpointManager.getReadEndpoints();
499498
List<URI> proactiveConnectionEndpoints = readEndpoints.subList(
500499
0,
501500
Math.min(readEndpoints.size(), proactiveContainerInitConfig.getProactiveConnectionRegionsCount()))
@@ -666,7 +665,7 @@ public void openConnectionsAndInitCachesWithCosmosClient_And_PerContainerConnect
666665
ConcurrentHashMap<String, ?> routingMap = getRoutingMap(rxDocumentClient);
667666
ConcurrentHashMap<String, ?> collectionInfoByNameMap = getCollectionInfoByNameMap(rxDocumentClient);
668667
Set<String> endpoints = ConcurrentHashMap.newKeySet();
669-
UnmodifiableList<RegionalRoutingContext> readEndpoints = globalEndpointManager.getReadEndpoints();
668+
List<RegionalRoutingContext> readEndpoints = globalEndpointManager.getReadEndpoints();
670669
List<URI> proactiveConnectionEndpoints = readEndpoints.subList(
671670
0,
672671
Math.min(readEndpoints.size(), proactiveContainerInitConfig.getProactiveConnectionRegionsCount()))

sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/RegionScopedSessionContainerConcurrencyTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package com.azure.cosmos.implementation;
55

66
import com.azure.cosmos.GatewayTestUtils;
7-
import com.azure.cosmos.implementation.apachecommons.collections.list.UnmodifiableList;
87
import com.azure.cosmos.implementation.guava25.collect.ImmutableList;
98
import com.azure.cosmos.implementation.routing.RegionalRoutingContext;
109
import com.azure.cosmos.models.ModelBridgeInternal;
@@ -21,6 +20,7 @@
2120
import java.util.ArrayList;
2221
import java.util.Arrays;
2322
import java.util.HashMap;
23+
import java.util.Collections;
2424
import java.util.List;
2525
import java.util.Map;
2626
import java.util.Objects;
@@ -253,8 +253,8 @@ public void concurrentSetAndResolveTokens(String profileName,
253253
for (URI u : orderedReadEndpoints) {
254254
endpointBuilder.add(new RegionalRoutingContext(u));
255255
}
256-
UnmodifiableList<RegionalRoutingContext> endpoints =
257-
new UnmodifiableList<>(endpointBuilder.build());
256+
List<RegionalRoutingContext> endpoints =
257+
Collections.unmodifiableList(endpointBuilder.build());
258258

259259
Mockito.when(globalEndpointManagerMock.getReadEndpoints()).thenReturn(endpoints);
260260
Mockito.when(globalEndpointManagerMock.getRegionName(Mockito.eq(EAST_US), Mockito.any()))

0 commit comments

Comments
 (0)