Glide vs. Picasso

Glide and Picasso are the most used image loading library in the world of android applications. Most of the android application developers have used any of these or both libraries in their career. Both libraries provide number of features, very fast and optimized. They are also well tested on many applications. On the surface, it looks like both are working on the same mechanism. But they both are very different in the way how they download images, caches images and loads them into memory. Today, we are going to look into the core differences between both the libraries and try to figure out which one is the best for application development.

We are comparing Glide v3.7.0 and Picasso v2.5.2 versions for this article. The latest available version might be different depending on when you are reading this article.

Import to the project:

Picasso and Glide, both are on jcenter. You can simply import those into your project with below dependency.

Picasso:

Glide:

support-v4 dependency is not needed for most of the projects as most of them uses support library by default.

Size and Method Count:

While comparing the sizes of the .jar file of both the libraries, Glide is almost 3.5 times larger than Picasso in size.

1rqe23b0xa6fpd6zopjx2aq

Picasso has method count of 849, while Glide has total 2678 method count. 2678 is quite a lot for 65535 methods limit of Android DEX file. You should enable ProGuard if you choose to use Glide.

1se-djihhpw8iwf4gij66aa

Syntax:

Both libraries have almost same syntax if you want to simply load the image from the URL and display them into the image view. Both support the fade animations and center crop. You can also add placeholder image to display while loading the image or while the image loading fails.

Glide:

Picasso:

One thing in which Glide dominates is, it is designed to work with Activity and Fragment’s life cycle too. You can pass the activity or fragment context with Glide.with() and it will brilliantly integrate with activity lifecycle callbacks such as onPause() or onResume().

1*Luh0ueUaCghrAywvkMxE4Q.png

Disk caching:

Both the library supports caching the image in the disk. They download the images from the URL and store those images on the disk by caching. But there are some differences how they store the images in the cache.

Picasso downloads the image and stores the full-size image (in my case the image resolution was 1160*750) in the cache and whenever we ask for the same image, it will return the full-size image and resize them to fit into the ImageView in real time.

On the other hand, Glide works differently. Glide downloads the image from the given URL, resize it to the size of the image view and stores it to the disk cache. So if you are loading the same image in two different sized image views, Glide will store two different copies of the same image in the cache with different resolutions. That will increase the disk cache size, but it has some of its own benefits. We will see that in the next section.

When I tried to adjust ImageView to the different sizes, Picasso cached only single size of the image and that is full-size. While Glide caches separate files for each size of ImageView. On down point of this approach is, although an image has already been loaded once, if you need to load the image in another size ImageView, it needs to be downloaded once again before be resized to the right resolution and then be cached.

Memory:

By default, Glide uses RGB_555 configuration while Picasso loads images in ARGB_8888 configuration to load the bitmap into memory. So for fair comparison, I made some changes in GlideModule to load images in ARGB_8888 format by creating a new class which extended from GlideModule like this:

Below is the graph of memory consumption of loading the image in Glide and Picasso:

1*-TOjFF8NJ6W7bmHZycjDtw.png

By looking into the graph, we can see that Glide is more memory efficient (about 8 MB) than Picasso (about 13 MB). This is pretty much understandable as we discussed in the earlier section, that Picasso loads the full-size image into the memory and relies on GPU to resize that image to fit into the size of the ImageView. While Glide loads an image that is already resized as per the ImageView, that requires significantly less memory than loading the full image like Picasso. This helps to prevent your app from throwing popular OutOfMemoryError.

Time taken to load the Image:

When we try to load an image from the URL, both libraries checks their local caches and if the image is not present in the cache, they will download the image from the URL.

When I tried to download images from the URL, Picasso was quite fast in loading the image from the internet than Glide. Maybe because after downloading the image, Picasso directly pushes the full-size image to the memory; while Glide resizes the image as per the dimension of the ImageView. That needs some time to resize the image. (You can reduce this time by using thumbnail() which we will discuss in later section.)

1*P7b1K_pp494aPLZ2sFI3Sw.gif

But while loading the image from the cache, Glide wins the battle. This is because of an advantage of the way Glide was designed. While the Picasso causes some delay on loading since it needs to be resized the image first in real-time before images are set to an ImageView. Even if you use .noFade()to appear it instantly.

1*0nIGJyOVgut-kCDMbu3kIg.gif

Other features that Glide support but not Picasso:

  • Animated GIF support: Glide supports animated GIF images out of the box. Loading GIF is simple. Just use the same Glide.with(...).load(...)call and if the image you load is an animated GIF. Also, because of Glide integrates with your activity life-cycle, animated GIFs are also paused in onStop() to avoid draining the battery in the background. While as of now, Picasso does not support animated GIF images. So, if you want to display some animated GIF, then Glide is the only option here.
  • Thumbnail support: With Glide, you can load multiple images into the same view at the same time. To first load a thumbnail at 1/10th the size of your view and then load the full image on top, you can use below code:

 This will reduce the time your user has to see image loading spinners without sacrificing quality.

  • Configurations & Customization: One good thing about Glide is, it provides various conflagrations and customization options. So, you can tweak Glide library as per your requirement. You can read more about this at configuration page.

Conclusion:

Neither Glide nor Picasso is perfect. You can use any of this library based on your application requirement. If you want the smaller app and you require very fewer features in the image loading, than Picasso is best. But If you want more customization, animated GIF support, and very better memory management, you should use Glide as your image loader library.

In my opinion, Glide is the winner over here as it handles memory very well and prevents my app from OutOfMemoryError. Also, loads image much faster than Picasso. And yes, the support for animated GIFs is almost killer.

References:

Advertisements

How to decrease your Gradle build time by 65%?

Gradle is very powerful build system. It handles the very complex process of building .dx files from java source code, merging all the resources and assets into the application package (.apk) and signing the application.

But gradle isn’t perfect. It is comparatively slower than other build systems out there.


Why should you care about build time of your project?

For a long time, I was OKAY with my build timings. I thought I can live with this. I used to do other stuff like surfing the internet, making coffee and even taking my lunch while gradle builds my project.

Now, let’s say you work on the above I/O’16 application project for 6 hours a day and run gradle build to install debug apk file on your test device for almost 15 times, you will spend 35 minutes a day and almost 3 hours/week(almost 10% of total time) just sitting idle and watching gradle build running.

That’s why it is very important that you optimize your build timing. The less time you spend watching gradle build your project, the more you can be productive. After all, time is precious.

I applied some modifications in my build process to decrease the build time and here are a few tips for you that will help you to decrease your build timings.


Here for example purpose, we will use Google I/O application as the sample project. We are going to run all the benchmarks on that project. This project contains more than 28 dependencies and 41538 method references. Also, the source code of the application is openly available on GitHub.

1d3wzkk8xca6siekdwgzclq


Build without any modifications:

Let’s measure the time to build and debug app from the project with the current configuration using below command.

./gradlew android:assembleDebug --profile

— profile will tell gradle to measure the time taken to execute each task and dump that data into HTML file. You can find that report under /projectDir/build/reports/profile directory.

1*owSs_JMY2F5KkOziRaRolg.png

  • As you can see it takes 2 minutes and 43 seconds to build the debug apk from the source on my machine. Keep this figure in your mind.

These benchmark timings may vary on your machine depending on your system configuration. Here I am going to use my 13″ Macbook Pro 2016 with touch barto run all these tasks.

Now, let’s try to decrease this time.


Gradle Build Cycle:

Gradle has three distinct phases in build life cycle:

  1. InitialisationIn this stage of the build life cycle, gradle picks the project and decides what things to build.
  2. ConfigurationHere, gradle will evaluate your build.gradle script, configure all the plugins and evaluate the task graph.
  3. ExecutionIn this phase gradle actually runs all the task those were evaluated in previous phase to get the work done and build the application.

As you can see that out of all three phases, only execution phase performs all the operations. That means that first two phases are just overhead to the gradle build process. We don’t care about them. But, sadly whenever you do anything with gradle this two phases will always get executed.

So, how can we measure the time taken to execute first two phases? Luckily, gradle provides — dry-run command, that tells gradle to evaluate the project but don’t run any task. Thus execution phase won’t get executed. So, run this command in your terminal:

./gradlew android:assembleDebug --dry-run --profile

Here is the time taken by first two phase on over Google I/O project.

You can see in above statistics that gradle passed almost 7.8 seconds just to initialise and configure the project. That is completely waste of time for us.


Let’s see if we can decrease the time taken to initialise and configure the project.

Configure on demand:

Google I/O app has two components/modules:

  • Android : That contains the source code related to the andorid application and
  • Server : This contains code related to backend server.

Now, if you are building an android application, you don’t want to configure server component. Right? But previous statistic shows that gradle passed almost a second to just configure server component.

Gradle provides — configure-on-demand flag, that will tell gradle to only build the projects that it really needs to build. Let’s run this command.

./gradlew android:assembleDebug --dry-run --profile --configure-on-demand

As you can see, if we use — configure-on-demandgradle will skip configuring the server module and it will decrease the build time by almost a second. I know this is not a huge gain, but small drops can fill the whole lake!!!

Time decreased : 1 second (6% win).

How you can enable configure-on-demand in android studio?

You can enable — configure-on-demand for every build you can add org.gradle.configureondemand=true in your gradle.properties file or in your android studio, navigate to Preferences > Build, Execution, Deployment > Compiler and check configure on demand option.

1*MBn53rnxIQdfEIWMp9JOOw.png

Enable daemon:

Gradle has a very good feature called Gradle DaemonDaemon keeps the instance of the gradle up and running in the background even after your build finishes. This will remove the time required to initialize the gradle and decrease your build timing significantly.

You won’t be able to see the time difference in your first build as gradle has to initialize and start the daemon, but build times will decrease in subsequent builds as gradle daemon is already initialised.

./gradlew android:assembleDebug --dry-run --profile --configure-on-demand --daemon

1hdjpmnafvlwiwhf4eaqj1q

In our case, the build time is decreased by about 4.5 seconds. Hurray!!!

Time decreased by : 4.5 seconds (71% win)

How you can enable daemon in android studio?

If you are using the gradle version 3.0 or above, the gradle daemon is by default enabled. But, if you are running on older versions of gradle then you can enable it for every build by adding org.gradle.daemon=true in your gradle.properties file.

Always keep your gradle up-to-date:

Gradle itself got faster with each new releases. There are many tweaks and performance improvements in the latest versions of gradle. Also, if you are running on gradle 2.4 or above, gradle will also cache build artifacts and that will improve the build time significantly.

So, always make sure that you are using the latest version of the gradle. You can go to /gradle/wrapper/gradle-wrapper.properties and upgrade gradle version by changing distributionUrl.

While writing this article, the gradle the latest gradle version is 3.3. Here is the updated gradle-wrapper.properties file for I/O application.1*77iuK0YxGUcRmcTPNHpeXg.png

./gradlew android:assembleDebug --dry-run --profile --configure-on-demand --daemon

1*s4ymdQIRaAgpZy_h6Yja8A.png

Time decreased by : 0.7 seconds (82% win 🍾)


So far we achived almost 82% gain in initialise and configuration timings. Now, let’s try to decrease the time required in execution phase.

Increase the heap size:

Since android studio 2.0, gradle uses dex in the process to decrease the build timings for the project.

“Dex in process” is a process that allows to run multiple dex processes to run within the single VM that is also shared with the gradle.

Generally, while building the applications, multiple dx processes runs on different VM instances.1*L-XJGmxyWGvmqYErQ7klZw.png

But starting from the Android Studio 2.0, all these dx processes runs in the single VM and that VM is also shared with the gradle.(You need to have build tool version 23.0.2 or above to enable dex in the process.)

1*6JRzZijRNkHPHlbyUIlaFQ.png

This decreases the build time significantly as all the dex process runs on the same VM instances. But this requires larger memory to accommodate all the dex processes and gradle. That means you need to increase the heap size required by the gradle daemon. By default, the heap size for the daemon is about 1GB. You have to increase the heap size by adding below line in your gradle.properties.

org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

The required heap size varies from machine to machine. For my machine, I found that 3GB heap size is perfect. Any more increase in the heap size doesn’t affect the build timing significantly.

Now, let’s run full clean build using the below command:

./gradlew android:assembleDebug --profile --configure-on-demand --daemon

1*2Bi_Rwf7ySeveu-Icl7nWg.png

Time decrease by : 1 min 43 sec (63% win) — From 2 min 43 sec to 1 min

Modularise and Parallelise build:

Allow gradle to build your project in parallel. If you have multiple modules in you project, then by enabling this, gradle can run build operations for independent modules parallelly. This may decrease the build time significantly for very complex and multi-module projects.

You can enable parallelism by adding org.gradle.parallel=true in your gradle.properties file.

As our project doesn’t have multiple modules, building parallel won’t make much difference.

1*YnJyE8U214HG_4aHinXn1w.png

Time decrease by : 1 min 45 sec (64.5% win)


Other small things to remember:

Avoid heavy computations, like increasing the version code from git commits count or downloading some files from url while building the project. Gradle will spend time to perform those computations or network operations and that will afftect build timings.

Don’t use dynamic dependency like,

compile 'com.android.support:appcompat-v7:23.0.+'

If you are using the dynamic dependencies, gradle will go online and check if there is any newer version for the library is available or not? (Most of the time, it is just waste of the precious build time). Instead, use the fixed dependencies and update them manually time to time.

compile 'com.android.support:appcompat-v7:23.0.2'

TL;DR:

The long story short, add below lines to your gradle.properties file and you will get almost 65% decrease in your build time.

 <gist>2fbf175066a0cadbb3af1008954ed077</gist>

1*5Fmeh0sckqPGpgBbybARHQ-2.jpeg