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

16 views
Skip to first unread message

Yash Chandra

unread,
Jul 10, 2023, 8:23:45 PM7/10/23
to Glide

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).

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<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> 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<Drawable> 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<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> 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<Drawable> 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<CronetEngine>() { @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<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> 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<Drawable> 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.


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

Reply all
Reply to author
Forward
0 new messages