This is a great question to refresh and revise what I have learned over the years from my ex-colleagues especially @inyaki_mwc & @jperezalv
I'll try to summarize what usual suspects I can recall in the 🧵
Usually, the answer lies in your build scans which is an amazing feature of the #Gradle build tool.
A Gradle build scan tells you how much time was spent in each of the three phases of the build lifecycle namely:
👉 Initialization
👉 Configuration
👉 Execution
Before going further let's refresh a few points
👉 Gradle supports single and multi-project builds.
👉 In Gradle tasks are the building block of your build process
👉 Tasks can depend on each other
👉 Gradle guarantees that tasks are executed in the order of their dependencies
How is the order determined? 🤔
Through a "Directed Acyclic Graph"
⚠️ An important point to keep in mind is that Gradle creates the dependency graph prior to executing any single task.
Speaking in terms of a Tree, you want to keep the height of your modules as small as possible
Suspect 1️⃣ - You have a module with a "high" level of dependencies and something changed "close" to the bottom of your tree.
⚠️ Dependency depth matters more than the number of dependencies at the same level.
💡 Keep your module dependency depth as low as possible.
Suspect 2️⃣ - Annotation Processors (AP)
Whenever looking into build problems my first question is what all annotation processors are we using?
⚠️ APs add additional tasks to your build execution phase.
Common libs that use it -
Dagger, Glide, Moshi, Room, etc.
How? 🤔
Each "task" takes an Input and spits an Output.
When Gradle can deterministically say that an Input of the task didn't change, it can skip executing the task and reuse the output from the cache.
Use ⤵️
Suspect 4️⃣ No Parallelism
Assuming most people have machines that have more than one processing core, not leveraging the ability of Gradle to execute certain tasks in parallel can also slow down your builds.
Use ⤵️
Suspect 5️⃣ Gradle Daemon Memory Starvation
Gradle builds use a JVM that requires memory and if doesn't have enough, it will have to constantly swap out items which result in cache misses, and slower builds.
Suspect 8️⃣ Running Irrelevant Tasks
A lot of times devs are running tasks with certain plugins or due to a setup that they actually don't need/care about.
🙅♂️Firebase perf plugin on debug builds
🙅♂️Modifying build params that lead to task cache invalidation
🙅♂️Png Crunching etc.
Suspect 9️⃣ Dynamic dependency resolution
Ever seen dependencies versions like `1.3+`
This allows gradle to dynamically resolve dependencies but they have side effects
👉 Gradle needs to resolve them (rather than just fetch/download them)
👉 Upstream Updates can break your app
Suspect 🔟 Bad Repository Ordering
If you use multiple repositories in your project. Gradle will look for your deps in that order. So the repository that contains high number of deps for your project should be listed first, there by saving unnecessary network requests.
That's it for today, I'll probably compile this into a blog later with more items that contribute to Gradle build times (in a way you don't want)
If you found this helpful, don't forget to RT this first tweet ⤵️
Been interviewing candidates for senior android roles for a while now, here at Tinder. Here’s are some thoughts and learnings —
Not going to be company specific 1/n 🧵
Majority of the candidates want to solve the problem right away, as soon as they see it. This is basic human nature but the people who didn’t take this approach most of the time did really well. Let’s talk about why I feel this hurts you as a candidate
Jumping on to a problem before clearly understanding it, is considered a 🚩 especially for IC3 and above candidates. This is because at these roles you are expected to start owning and delivering projects without any hand holding.