Skip to content

Commit bee6348

Browse files
sjuddglide-copybara-robot
authored andcommittedAug 13, 2019
Avoid pooling/reusing SingleRequest objects.
~90% of devices are now running on Art and won't get any benefit from this object pooling. It's very difficult to definitively determine when it's safe to recycle an object when it's used by multiple threads. The code simplification is worth the minor performance regression on dalvik devices. PiperOrigin-RevId: 263229952
1 parent 8a094e9 commit bee6348

File tree

2 files changed

+51
-135
lines changed

2 files changed

+51
-135
lines changed
 

‎library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java

+2-10
Original file line numberDiff line numberDiff line change
@@ -383,20 +383,16 @@ public StateVerifier getVerifier() {
383383
private class CallLoadFailed implements Runnable {
384384

385385
private final ResourceCallback cb;
386-
private final Object lock;
387386

388387
CallLoadFailed(ResourceCallback cb) {
389388
this.cb = cb;
390-
// The lock may be reset if the callback is removed while our Runnable is pending, so memoize
391-
// it here. We're assuming that the lock is never re-used.
392-
this.lock = Preconditions.checkNotNull(cb.getLock());
393389
}
394390

395391
@Override
396392
public void run() {
397393
// Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
398394
// (b/136032534).
399-
synchronized (lock) {
395+
synchronized (cb.getLock()) {
400396
synchronized (EngineJob.this) {
401397
if (cbs.contains(cb)) {
402398
callCallbackOnLoadFailed(cb);
@@ -411,20 +407,16 @@ public void run() {
411407
private class CallResourceReady implements Runnable {
412408

413409
private final ResourceCallback cb;
414-
private final Object lock;
415410

416411
CallResourceReady(ResourceCallback cb) {
417412
this.cb = cb;
418-
// The lock may be reset if the callback is removed while our Runnable is pending, so memoize
419-
// it here. We're assuming that the lock is never re-used.
420-
this.lock = Preconditions.checkNotNull(cb.getLock());
421413
}
422414

423415
@Override
424416
public void run() {
425417
// Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
426418
// (b/136032534).
427-
synchronized (lock) {
419+
synchronized (cb.getLock()) {
428420
synchronized (EngineJob.this) {
429421
if (cbs.contains(cb)) {
430422
// Acquire for this particular callback.

‎library/src/main/java/com/bumptech/glide/request/SingleRequest.java

+49-125
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import androidx.annotation.GuardedBy;
99
import androidx.annotation.NonNull;
1010
import androidx.annotation.Nullable;
11-
import androidx.core.util.Pools;
1211
import com.bumptech.glide.GlideContext;
1312
import com.bumptech.glide.Priority;
1413
import com.bumptech.glide.load.DataSource;
@@ -21,10 +20,7 @@
2120
import com.bumptech.glide.request.transition.Transition;
2221
import com.bumptech.glide.request.transition.TransitionFactory;
2322
import com.bumptech.glide.util.LogTime;
24-
import com.bumptech.glide.util.Preconditions;
25-
import com.bumptech.glide.util.Synthetic;
2623
import com.bumptech.glide.util.Util;
27-
import com.bumptech.glide.util.pool.FactoryPools;
2824
import com.bumptech.glide.util.pool.StateVerifier;
2925
import java.util.List;
3026
import java.util.concurrent.Executor;
@@ -35,24 +31,12 @@
3531
*
3632
* @param <R> The type of the resource that will be transcoded from the loaded resource.
3733
*/
38-
@SuppressWarnings("SynchronizeOnNonFinalField")
39-
public final class SingleRequest<R>
40-
implements Request, SizeReadyCallback, ResourceCallback, FactoryPools.Poolable {
34+
public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback {
4135
/** Tag for logging internal events, not generally suitable for public use. */
4236
private static final String TAG = "Request";
4337
/** Tag for logging externally useful events (request completion, timing etc). */
4438
private static final String GLIDE_TAG = "Glide";
4539

46-
private static final Pools.Pool<SingleRequest<?>> POOL =
47-
FactoryPools.threadSafe(
48-
150,
49-
new FactoryPools.Factory<SingleRequest<?>>() {
50-
@Override
51-
public SingleRequest<?> create() {
52-
return new SingleRequest<Object>();
53-
}
54-
});
55-
5640
private static final boolean IS_VERBOSE_LOGGABLE = Log.isLoggable(TAG, Log.VERBOSE);
5741

5842
private enum Status {
@@ -76,52 +60,35 @@ private enum Status {
7660
private final StateVerifier stateVerifier = StateVerifier.newInstance();
7761

7862
/* Variables mutated only when a request is initialized or returned to the object pool. */
79-
private volatile Object requestLock;
63+
private final Object requestLock;
8064

81-
@GuardedBy("requestLock")
82-
@Nullable
83-
private RequestListener<R> targetListener;
65+
@Nullable private final RequestListener<R> targetListener;
8466

85-
@GuardedBy("requestLock")
86-
private RequestCoordinator requestCoordinator;
67+
private final RequestCoordinator requestCoordinator;
8768

88-
@GuardedBy("requestLock")
89-
private Context context;
69+
private final Context context;
9070

91-
@GuardedBy("requestLock")
92-
private GlideContext glideContext;
71+
private final GlideContext glideContext;
9372

94-
@GuardedBy("requestLock")
95-
@Nullable
96-
private Object model;
73+
@Nullable private final Object model;
9774

98-
@GuardedBy("requestLock")
99-
private Class<R> transcodeClass;
75+
private final Class<R> transcodeClass;
10076

101-
@GuardedBy("requestLock")
102-
private BaseRequestOptions<?> requestOptions;
77+
private final BaseRequestOptions<?> requestOptions;
10378

104-
@GuardedBy("requestLock")
105-
private int overrideWidth;
79+
private final int overrideWidth;
10680

107-
@GuardedBy("requestLock")
108-
private int overrideHeight;
81+
private final int overrideHeight;
10982

110-
@GuardedBy("requestLock")
111-
private Priority priority;
83+
private final Priority priority;
11284

113-
@GuardedBy("requestLock")
114-
private Target<R> target;
85+
private final Target<R> target;
11586

116-
@GuardedBy("requestLock")
117-
@Nullable
118-
private List<RequestListener<R>> requestListeners;
87+
@Nullable private final List<RequestListener<R>> requestListeners;
11988

120-
@GuardedBy("requestLock")
121-
private TransitionFactory<? super R> animationFactory;
89+
private final TransitionFactory<? super R> animationFactory;
12290

123-
@GuardedBy("requestLock")
124-
private Executor callbackExecutor;
91+
private final Executor callbackExecutor;
12592

12693
@GuardedBy("requestLock")
12794
private Resource<R> resource;
@@ -141,12 +108,15 @@ private enum Status {
141108
private Status status;
142109

143110
@GuardedBy("requestLock")
111+
@Nullable
144112
private Drawable errorDrawable;
145113

146114
@GuardedBy("requestLock")
115+
@Nullable
147116
private Drawable placeholderDrawable;
148117

149118
@GuardedBy("requestLock")
119+
@Nullable
150120
private Drawable fallbackDrawable;
151121

152122
@GuardedBy("requestLock")
@@ -163,7 +133,7 @@ private enum Status {
163133
public static <R> SingleRequest<R> obtain(
164134
Context context,
165135
GlideContext glideContext,
166-
@Nullable Object requestLock,
136+
Object requestLock,
167137
Object model,
168138
Class<R> transcodeClass,
169139
BaseRequestOptions<?> requestOptions,
@@ -177,15 +147,7 @@ public static <R> SingleRequest<R> obtain(
177147
Engine engine,
178148
TransitionFactory<? super R> animationFactory,
179149
Executor callbackExecutor) {
180-
@SuppressWarnings("unchecked")
181-
SingleRequest<R> request = (SingleRequest<R>) POOL.acquire();
182-
if (request == null) {
183-
request = new SingleRequest<>();
184-
}
185-
if (requestLock == null) {
186-
requestLock = request;
187-
}
188-
request.init(
150+
return new SingleRequest<>(
189151
context,
190152
glideContext,
191153
requestLock,
@@ -202,93 +164,50 @@ public static <R> SingleRequest<R> obtain(
202164
engine,
203165
animationFactory,
204166
callbackExecutor);
205-
return request;
206-
}
207-
208-
@SuppressWarnings("WeakerAccess")
209-
@Synthetic
210-
SingleRequest() {
211-
// just create, instances are reused with recycle/init
212167
}
213168

214169
// We are in fact locking on the same lock that will be used for all subsequent method calls.
215170
@SuppressWarnings("GuardedBy")
216-
private void init(
171+
private SingleRequest(
217172
Context context,
218173
GlideContext glideContext,
219174
@NonNull Object requestLock,
220-
Object model,
175+
@Nullable Object model,
221176
Class<R> transcodeClass,
222177
BaseRequestOptions<?> requestOptions,
223178
int overrideWidth,
224179
int overrideHeight,
225180
Priority priority,
226181
Target<R> target,
227-
RequestListener<R> targetListener,
182+
@Nullable RequestListener<R> targetListener,
228183
@Nullable List<RequestListener<R>> requestListeners,
229184
RequestCoordinator requestCoordinator,
230185
Engine engine,
231186
TransitionFactory<? super R> animationFactory,
232187
Executor callbackExecutor) {
233-
this.requestLock = Preconditions.checkNotNull(requestLock);
234-
synchronized (this.requestLock) {
235-
this.context = context;
236-
this.glideContext = glideContext;
237-
this.model = model;
238-
this.transcodeClass = transcodeClass;
239-
this.requestOptions = requestOptions;
240-
this.overrideWidth = overrideWidth;
241-
this.overrideHeight = overrideHeight;
242-
this.priority = priority;
243-
this.target = target;
244-
this.targetListener = targetListener;
245-
this.requestListeners = requestListeners;
246-
this.requestCoordinator = requestCoordinator;
247-
this.engine = engine;
248-
this.animationFactory = animationFactory;
249-
this.callbackExecutor = callbackExecutor;
250-
status = Status.PENDING;
251-
252-
if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
253-
requestOrigin = new RuntimeException("Glide request origin trace");
254-
}
188+
this.requestLock = requestLock;
189+
this.context = context;
190+
this.glideContext = glideContext;
191+
this.model = model;
192+
this.transcodeClass = transcodeClass;
193+
this.requestOptions = requestOptions;
194+
this.overrideWidth = overrideWidth;
195+
this.overrideHeight = overrideHeight;
196+
this.priority = priority;
197+
this.target = target;
198+
this.targetListener = targetListener;
199+
this.requestListeners = requestListeners;
200+
this.requestCoordinator = requestCoordinator;
201+
this.engine = engine;
202+
this.animationFactory = animationFactory;
203+
this.callbackExecutor = callbackExecutor;
204+
status = Status.PENDING;
205+
206+
if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
207+
requestOrigin = new RuntimeException("Glide request origin trace");
255208
}
256209
}
257210

258-
@NonNull
259-
@Override
260-
public StateVerifier getVerifier() {
261-
return stateVerifier;
262-
}
263-
264-
@Override
265-
public void recycle() {
266-
synchronized (requestLock) {
267-
assertNotCallingCallbacks();
268-
context = null;
269-
glideContext = null;
270-
model = null;
271-
transcodeClass = null;
272-
requestOptions = null;
273-
overrideWidth = -1;
274-
overrideHeight = -1;
275-
target = null;
276-
requestListeners = null;
277-
targetListener = null;
278-
requestCoordinator = null;
279-
animationFactory = null;
280-
loadStatus = null;
281-
errorDrawable = null;
282-
placeholderDrawable = null;
283-
fallbackDrawable = null;
284-
width = -1;
285-
height = -1;
286-
requestOrigin = null;
287-
POOL.release(this);
288-
}
289-
requestLock = null;
290-
}
291-
292211
@Override
293212
public void begin() {
294213
synchronized (requestLock) {
@@ -438,6 +357,11 @@ public boolean isCleared() {
438357
}
439358
}
440359

360+
@Override
361+
public void recycle() {
362+
// TODO: remove this method, it's a no-op.
363+
}
364+
441365
@GuardedBy("requestLock")
442366
private Drawable getErrorDrawable() {
443367
if (errorDrawable == null) {

0 commit comments

Comments
 (0)
Please sign in to comment.