Skip to content

Commit 7719744

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Make Atomic*FieldUpdater fields static for better performance.
Compare cl/713006636. (Also, better document the similar code in `AbstractFuture`.) Note that I also evaluated performance with `VarHandle`, and I found it no better. (Maybe we did a similar experiment with `Unsafe` way back when and came to a similar conclusion?) Note that that's all based on _JVM_ performance (and on benchmarks that are not necessarily great). It's possible that Android it worth a further look someday. But our only option there _today_ might be `Unsafe`, and new usages of `Unsafe` would be moving backward. RELNOTES=n/a PiperOrigin-RevId: 724013501
1 parent a3500eb commit 7719744

File tree

4 files changed

+92
-38
lines changed

4 files changed

+92
-38
lines changed

Diff for: android/guava/src/com/google/common/util/concurrent/AbstractFuture.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -1485,19 +1485,34 @@ boolean casValue(AbstractFuture<?> future, @Nullable Object expect, Object updat
14851485
}
14861486
}
14871487

1488-
/** Returns an {@link AtomicReferenceFieldUpdater} for {@link #waiters}. */
1488+
/**
1489+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #waiters}.
1490+
*
1491+
* <p>The creation of the updater has to happen directly inside {@link AbstractFuture}, as
1492+
* discussed in {@link #methodHandlesLookupFromWithinAbstractFuture}.
1493+
*/
14891494
private static AtomicReferenceFieldUpdater<? super AbstractFuture<?>, Waiter>
14901495
waitersUpdaterFromWithinAbstractFuture() {
14911496
return newUpdater(AbstractFuture.class, Waiter.class, "waiters");
14921497
}
14931498

1494-
/** Returns an {@link AtomicReferenceFieldUpdater} for {@link #listeners}. */
1499+
/**
1500+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #listeners}.
1501+
*
1502+
* <p>The creation of the updater has to happen directly inside {@link AbstractFuture}, as
1503+
* discussed in {@link #methodHandlesLookupFromWithinAbstractFuture}.
1504+
*/
14951505
private static AtomicReferenceFieldUpdater<? super AbstractFuture<?>, Listener>
14961506
listenersUpdaterFromWithinAbstractFuture() {
14971507
return newUpdater(AbstractFuture.class, Listener.class, "listeners");
14981508
}
14991509

1500-
/** Returns an {@link AtomicReferenceFieldUpdater} for {@link #value}. */
1510+
/**
1511+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #value}.
1512+
*
1513+
* <p>The creation of the updater has to happen directly inside {@link AbstractFuture}, as
1514+
* discussed in {@link #methodHandlesLookupFromWithinAbstractFuture}.
1515+
*/
15011516
private static AtomicReferenceFieldUpdater<? super AbstractFuture<?>, Object>
15021517
valueUpdaterFromWithinAbstractFuture() {
15031518
return newUpdater(AbstractFuture.class, Object.class, "value");

Diff for: android/guava/src/com/google/common/util/concurrent/AggregateFutureState.java

+28-16
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object>
5454
AtomicHelper helper;
5555
Throwable thrownReflectionFailure = null;
5656
try {
57-
helper =
58-
new SafeAtomicHelper(
59-
newUpdater(AggregateFutureState.class, Set.class, "seenExceptions"),
60-
newUpdater(AggregateFutureState.class, "remaining"));
57+
helper = new SafeAtomicHelper();
6158
} catch (Throwable reflectionFailure) { // sneaky checked exception
6259
// Some Android 5.0.x Samsung devices have bugs in JDK reflection APIs that cause
6360
// getDeclaredField to throw a NoSuchFieldException when the field is definitely there.
@@ -156,20 +153,12 @@ abstract void compareAndSetSeenExceptions(
156153
}
157154

158155
private static final class SafeAtomicHelper extends AtomicHelper {
159-
final AtomicReferenceFieldUpdater<
156+
private static final AtomicReferenceFieldUpdater<
160157
? super AggregateFutureState<?>, ? super @Nullable Set<Throwable>>
161-
seenExceptionsUpdater;
158+
seenExceptionsUpdater = seenExceptionsUpdaterFromWithinAggregateFutureState();
162159

163-
final AtomicIntegerFieldUpdater<? super AggregateFutureState<?>> remainingCountUpdater;
164-
165-
SafeAtomicHelper(
166-
AtomicReferenceFieldUpdater<
167-
? super AggregateFutureState<?>, ? super @Nullable Set<Throwable>>
168-
seenExceptionsUpdater,
169-
AtomicIntegerFieldUpdater<? super AggregateFutureState<?>> remainingCountUpdater) {
170-
this.seenExceptionsUpdater = seenExceptionsUpdater;
171-
this.remainingCountUpdater = remainingCountUpdater;
172-
}
160+
private static final AtomicIntegerFieldUpdater<? super AggregateFutureState<?>>
161+
remainingCountUpdater = remainingCountUpdaterFromWithinAggregateFutureState();
173162

174163
@Override
175164
void compareAndSetSeenExceptions(
@@ -201,4 +190,27 @@ int decrementAndGetRemainingCount(AggregateFutureState<?> state) {
201190
}
202191
}
203192
}
193+
194+
/**
195+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #seenExceptions}.
196+
*
197+
* <p>The creation of the updater has to happen directly inside {@link AggregateFutureState}, as
198+
* discussed in {@link AbstractFuture#methodHandlesLookupFromWithinAbstractFuture}.
199+
*/
200+
private static AtomicReferenceFieldUpdater<
201+
? super AggregateFutureState<?>, ? super @Nullable Set<Throwable>>
202+
seenExceptionsUpdaterFromWithinAggregateFutureState() {
203+
return newUpdater(AggregateFutureState.class, Set.class, "seenExceptions");
204+
}
205+
206+
/**
207+
* Returns an {@link AtomicIntegerFieldUpdater} for {@link #remaining}.
208+
*
209+
* <p>The creation of the updater has to happen directly inside {@link AggregateFutureState}, as
210+
* discussed in {@link AbstractFuture#methodHandlesLookupFromWithinAbstractFuture}.
211+
*/
212+
private static AtomicIntegerFieldUpdater<? super AggregateFutureState<?>>
213+
remainingCountUpdaterFromWithinAggregateFutureState() {
214+
return newUpdater(AggregateFutureState.class, "remaining");
215+
}
204216
}

Diff for: guava/src/com/google/common/util/concurrent/AbstractFuture.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -1597,19 +1597,34 @@ boolean casValue(AbstractFuture<?> future, @Nullable Object expect, Object updat
15971597
}
15981598
}
15991599

1600-
/** Returns an {@link AtomicReferenceFieldUpdater} for {@link #waiters}. */
1600+
/**
1601+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #waiters}.
1602+
*
1603+
* <p>The creation of the updater has to happen directly inside {@link AbstractFuture}, as
1604+
* discussed in {@link #methodHandlesLookupFromWithinAbstractFuture}.
1605+
*/
16011606
private static AtomicReferenceFieldUpdater<? super AbstractFuture<?>, Waiter>
16021607
waitersUpdaterFromWithinAbstractFuture() {
16031608
return newUpdater(AbstractFuture.class, Waiter.class, "waiters");
16041609
}
16051610

1606-
/** Returns an {@link AtomicReferenceFieldUpdater} for {@link #listeners}. */
1611+
/**
1612+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #listeners}.
1613+
*
1614+
* <p>The creation of the updater has to happen directly inside {@link AbstractFuture}, as
1615+
* discussed in {@link #methodHandlesLookupFromWithinAbstractFuture}.
1616+
*/
16071617
private static AtomicReferenceFieldUpdater<? super AbstractFuture<?>, Listener>
16081618
listenersUpdaterFromWithinAbstractFuture() {
16091619
return newUpdater(AbstractFuture.class, Listener.class, "listeners");
16101620
}
16111621

1612-
/** Returns an {@link AtomicReferenceFieldUpdater} for {@link #value}. */
1622+
/**
1623+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #value}.
1624+
*
1625+
* <p>The creation of the updater has to happen directly inside {@link AbstractFuture}, as
1626+
* discussed in {@link #methodHandlesLookupFromWithinAbstractFuture}.
1627+
*/
16131628
private static AtomicReferenceFieldUpdater<? super AbstractFuture<?>, Object>
16141629
valueUpdaterFromWithinAbstractFuture() {
16151630
return newUpdater(AbstractFuture.class, Object.class, "value");

Diff for: guava/src/com/google/common/util/concurrent/AggregateFutureState.java

+28-16
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object>
5454
AtomicHelper helper;
5555
Throwable thrownReflectionFailure = null;
5656
try {
57-
helper =
58-
new SafeAtomicHelper(
59-
newUpdater(AggregateFutureState.class, Set.class, "seenExceptions"),
60-
newUpdater(AggregateFutureState.class, "remaining"));
57+
helper = new SafeAtomicHelper();
6158
} catch (Throwable reflectionFailure) { // sneaky checked exception
6259
// Some Android 5.0.x Samsung devices have bugs in JDK reflection APIs that cause
6360
// getDeclaredField to throw a NoSuchFieldException when the field is definitely there.
@@ -156,20 +153,12 @@ abstract void compareAndSetSeenExceptions(
156153
}
157154

158155
private static final class SafeAtomicHelper extends AtomicHelper {
159-
final AtomicReferenceFieldUpdater<
156+
private static final AtomicReferenceFieldUpdater<
160157
? super AggregateFutureState<?>, ? super @Nullable Set<Throwable>>
161-
seenExceptionsUpdater;
158+
seenExceptionsUpdater = seenExceptionsUpdaterFromWithinAggregateFutureState();
162159

163-
final AtomicIntegerFieldUpdater<? super AggregateFutureState<?>> remainingCountUpdater;
164-
165-
SafeAtomicHelper(
166-
AtomicReferenceFieldUpdater<
167-
? super AggregateFutureState<?>, ? super @Nullable Set<Throwable>>
168-
seenExceptionsUpdater,
169-
AtomicIntegerFieldUpdater<? super AggregateFutureState<?>> remainingCountUpdater) {
170-
this.seenExceptionsUpdater = seenExceptionsUpdater;
171-
this.remainingCountUpdater = remainingCountUpdater;
172-
}
160+
private static final AtomicIntegerFieldUpdater<? super AggregateFutureState<?>>
161+
remainingCountUpdater = remainingCountUpdaterFromWithinAggregateFutureState();
173162

174163
@Override
175164
void compareAndSetSeenExceptions(
@@ -201,4 +190,27 @@ int decrementAndGetRemainingCount(AggregateFutureState<?> state) {
201190
}
202191
}
203192
}
193+
194+
/**
195+
* Returns an {@link AtomicReferenceFieldUpdater} for {@link #seenExceptions}.
196+
*
197+
* <p>The creation of the updater has to happen directly inside {@link AggregateFutureState}, as
198+
* discussed in {@link AbstractFuture#methodHandlesLookupFromWithinAbstractFuture}.
199+
*/
200+
private static AtomicReferenceFieldUpdater<
201+
? super AggregateFutureState<?>, ? super @Nullable Set<Throwable>>
202+
seenExceptionsUpdaterFromWithinAggregateFutureState() {
203+
return newUpdater(AggregateFutureState.class, Set.class, "seenExceptions");
204+
}
205+
206+
/**
207+
* Returns an {@link AtomicIntegerFieldUpdater} for {@link #remaining}.
208+
*
209+
* <p>The creation of the updater has to happen directly inside {@link AggregateFutureState}, as
210+
* discussed in {@link AbstractFuture#methodHandlesLookupFromWithinAbstractFuture}.
211+
*/
212+
private static AtomicIntegerFieldUpdater<? super AggregateFutureState<?>>
213+
remainingCountUpdaterFromWithinAggregateFutureState() {
214+
return newUpdater(AggregateFutureState.class, "remaining");
215+
}
204216
}

0 commit comments

Comments
 (0)