bumptech / bumptech/glide

Glide (with Cronet) using HTTP/3 takes much longer to download images than Glide using HTTP/1.1 or HTTP/2

Open
#5,210 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
35k
Forks
6.2k
Avg merge
1d 11h
Merged PRs (30d)
8

Description

**Glide Version**: 4.14.2

**Integration libraries**: play-services-cronet:18.0.1, cronet-integration:4.14.2

**Device/Android Version**: Galaxy A23/Android 13

**Issue details / Repro steps / Use case background**:
I have a use case where I need to preload ~20-30 images.

I started out by using Glide without any integrations (ie HTTP/1.1) and it was taking (on average) 7.88s to complete this operation.
Then I used Cronet and glide's cronet-integration without QUIC enabled (ie. HTTP/2) and it was taking (average) 7.95s to complete same operation.
Then I used Cronet with QUIC enabled (ie. HTTP/3) and it took (average) 15.83s to complete the operation.

This was surprising. I was expecting HTTP/3 to be slightly better or at least equal to HTTP/2 and HTTP/1.1 but almost all times I downloaded images using HTTP/3 it took double time than HTTP/2 or HTTP/1.1
(I tried this exercise 10 times for each protocol version and cleared app data in between every trial).

**Glide load line / `GlideModule` (if any) / list Adapter code (if any)**:

Below are the code snippets I used for each of the versions -

Glide code with HTTP/1.1 -

```
// app gradle

implementation 'com.github.bumptech.glide:glide:4.14.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
implementation 'jp.wasabeef:glide-transformations:4.3.0'

// code
mPreloadCounter = 0;
ConsoleLogger.d(TAG, "start fetching items");
long startTime = System.currentTimeMillis();
for (Item item : itemsMap.values()) {
Glide.with(getApplicationContext()).load(item.getURL()).listener(new RequestListener() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
mPreloadCounter++;
if (mPreloadCounter == itemsMap.size()) {
ConsoleLogger.d(TAG, "end fetching items 1 " + (float)((System.currentTimeMillis() - startTime)/1000));
}
return false;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
mPreloadCounter++;
if (mPreloadCounter == itemsMap.size()) {
ConsoleLogger.d(TAG, "end fetching items 2 " + ((float)(System.currentTimeMillis() - startTime))/1000);
}
return false;
}
}).preload();
}
```

Glide code with HTTP/2 -

```
// app gradle

implementation 'com.github.bumptech.glide:glide:4.14.2'
implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.google.android.gms:play-services-cronet:18.0.1'
implementation "com.github.bumptech.glide:cronet-integration:4.14.2"

// code
mPreloadCounter = 0;
ConsoleLogger.d(TAG, "start fetching items");
long startTime = System.currentTimeMillis();
for (Item item : itemsMap.values()) {
Glide.with(getApplicationContext()).load(item.getURL()).listener(new RequestListener() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
mPreloadCounter++;
if (mPreloadCounter == itemsMap.size()) {
ConsoleLogger.d(TAG, "end fetching items 1 " + (float)((System.currentTimeMillis() - startTime)/1000));
}
return false;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
mPreloadCounter++;
if (mPreloadCounter == itemsMap.size()) {
ConsoleLogger.d(TAG, "end fetching items 2 " + ((float)(System.currentTimeMillis() - startTime))/1000);
}
return false;
}
}).preload();
}
```

Glide code with HTTP/3 -

```
// app gradle

implementation 'com.github.bumptech.glide:glide:4.14.2'
implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.google.android.gms:play-services-cronet:18.0.1'
implementation "com.github.bumptech.glide:cronet-integration:4.14.2"

// code

CronetEngine.Builder builder = new CronetEngine.Builder(getApplicationContext());
builder.enableQuic(true);
builder.addQuicHint("cdn.domain.com", 443, 443);
CronetEngine cronetEngine = builder.build();
CronetRequestFactory factory = new CronetRequestFactoryImpl(
new Supplier() {
@Override
public CronetEngine get() {
return cronetEngine;
}
}
);
ChromiumUrlLoader.StreamFactory factory1 = new ChromiumUrlLoader.StreamFactory(factory, null);
Glide.get(getApplicationContext()).getRegistry().replace(GlideUrl.class, InputStream.class, factory1);

mPreloadCounter = 0;
ConsoleLogger.d(TAG, "start fetching items");
long startTime = System.currentTimeMillis();
for (Item item : itemsMap.values()) {
Glide.with(getApplicationContext()).load(item.getURL()).listener(new RequestListener() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
mPreloadCounter++;
if (mPreloadCounter == itemsMap.size()) {
ConsoleLogger.d(TAG, "end fetching items 1 " + (float)((System.currentTimeMillis() - startTime)/1000));
}
return false;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
mPreloadCounter++;
if (mPreloadCounter == itemsMap.size()) {
ConsoleLogger.d(TAG, "end fetching items 2 " + ((float)(System.currentTimeMillis() - startTime))/1000);
}
return false;
}
}).preload();
}
```

In each of the 30 cases, none of the requests failed.

**Layout XML**: NA (only preloading images)

**Stack trace / LogCat**: NA (only success logs with latency)

Attaching screenshot of time taken (in seconds) every time for each of the versions.

image

I have read many articles online suggesting that HTTP/3 performs better than other versions in most of the use cases but here it was horrible. This makes me think that maybe problem is in my code.

**Any suggestions how can I correctly/optimally use Glide with Cronet + QUIC?**

PS: I know downloading 20-30 images concurrently is not ideal (can be broken down into parts) but I am curious about RCA of the behaviour that I observed today. Any insights are welcome.

Thanks

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.