00:11
well we're excited to start our webinar
00:14
tonight thanks so much for everyone
00:15
being here so exciting for me to see
00:17
uh the numbers go up with the room uh
00:19
people filling up uh
00:20
joining the webinar it's always the
00:22
exciting part as we get this thing
00:25
uh just a quick reminder of where you
00:27
are today you're in the droid con
00:29
online webinar series this is part one
00:31
of what we're calling
00:32
our hands-on and in-depth series a lot
00:34
of practical knowledge that we wanna
00:36
get in your hands today we're really
00:39
grateful that we've been able to partner
00:40
with gradle on this presentation and
00:41
have nelson here with us
00:43
today to present to you uh before we get
00:45
to the rest of the lineup
00:47
i want to do just a couple of quick uh
00:49
housekeeping items before we turn nelson
00:53
on this uh on his presentation so as you
00:56
um we've got as if you've been with us
00:60
you know that all of these uh webinars
01:03
so for posterity so you'll be able to
01:07
tomorrow or the next day on android
01:12
and that will they will also have be
01:14
transcripted and fully searchable
01:16
uh so we're excited to make those
01:17
available to you there
01:20
uh just a quick item of business what's
01:24
if you uh have been checking out the
01:26
schedule up next we've got a grip
01:28
with sakis and martin also part two of
01:32
in-depth series so go take a look over
01:34
at online.droidcon.com
01:36
and you should be able to get a good
01:38
idea of what's coming up next but
01:39
register for that because we think this
01:42
uh event coming up for those of you who
01:46
are joining for us the first time you'll
01:48
know that we do the q a over slido
01:50
so take a take a quick run over in your
01:54
browser to slido.com
01:56
you'll be asked to put in individual
01:57
code and that's this
01:59
uh this particular code listed here uh
02:02
that will get you to to the particular
02:05
event you can also check in the chat
02:07
function um and that will in the chat
02:10
function you'll also have a link
02:12
directly gian should be sending that
02:13
over so make sure that you're checking
02:17
for uh for that particular
02:20
slider link and in fact i am just going
02:23
that code one more time yeah six two two
02:26
seven seven that's the one
02:28
so we're we're excited to have you do
02:30
that so basically go over
02:31
to slido.com if you see that somebody's
02:33
asked an important question something
02:35
that you wanted to ask
02:36
uh give it a thumbs up vote for it uh
02:39
that way the most important and most
02:41
uh questions slide to the top and that
02:44
in the limited time that we'll have to
02:46
answer to questions that nelson will
02:48
have after his presentation
02:49
will get to the most important questions
02:52
uh so you guys see that jan has sent
02:54
in the link in the code as well uh today
02:58
just so you know uh what we're doing
02:59
we've got nelson osaki here with us
03:02
doing the presentation not just another
03:05
scanning android build gradle after he's
03:08
stick with us because we've got an
03:10
awesome panel discussion
03:12
as you can see we're really happy to
03:14
welcome with us uh yvonne gavrilovich
03:16
zach swears israel camacho
03:18
john rodriguez uh it doesn't get more
03:21
experience than this in terms of lineup
03:23
talking about all things
03:24
android builds performance speed
03:28
so stack up your questions too this is a
03:30
really good opportunity for for you guys
03:33
to ask and get answers to all the
03:36
questions that you're
03:36
you've been wanting to know so we are
03:39
really excited to have them with us and
03:41
we'll be having them join the panel
03:43
uh join this just as soon uh as
03:46
soon as uh we've given nelson a bit of
03:50
uh to do his um q a so that is it for me
03:55
is now get out of the way turn the time
03:58
over to nelson here make him uh the
04:01
presenter and he'll be able to share his
04:04
uh so here we go uh nelson if you can
04:08
i'm gonna duck out on the video so it's
04:11
and uh we look forward to your
04:15
hey um thank you for the intro it seems
04:19
to enable some permissions here so i
04:22
right back in order to screen share
04:35
yeah this is this is always the very
04:37
exciting part of the webinar especially
04:39
doing something live
04:40
there's always the the little gotchas uh
04:43
uh but that's that's just part of the
04:45
fun that we all have with with doing
04:47
streaming live demos so uh hopefully
04:51
nelson will be right back
04:52
uh yeah yeah but this
04:56
yep we can hear you you should be back
04:59
hopefully seeing you in just a second
05:06
so let's uh i've made you the moderator
05:09
now you should be able to present your
05:16
okie doke um there we go well then
05:24
i just need uh my name is nelson osaki
05:28
i will be presenting about
05:32
scaling your android build with gradle
05:36
so a little bit of background about me
05:39
i've been previously an
05:40
android engineer i've worked at several
05:43
different companies
05:45
from large projects such as soundcloud
05:48
to very tiny startups i've seen all
05:50
kinds of android builds
05:52
i've seen a lot of different patterns
05:54
different styles different strategies
05:57
and i'm here to talk about some of those
06:00
and right now i'm a solutions engineer
06:02
at gradle so what that means
06:04
is i'll talk about that in a sec what
06:08
but some more background i'm also
06:10
maintaining a couple of gradle plugins
06:13
the first is called fladle and what it
06:15
lets you do is easily scale your
06:17
instrumentation tests on firebase
06:20
second is delect which allows easily
06:23
replaces dagger with dagger reflect to
06:25
improve your build speeds
06:26
and the last one is called gradle doctor
06:28
and it gives you actionable insights for
06:33
cool so yes right now i just started
06:36
working at cradle as a solutions
06:37
engineer what that means is
06:39
i help our customers improve their
06:41
android builds and get onboarded to our
06:44
enterprise product called gradle
06:46
enterprise which gives you insights into
06:49
but that's not what i'm
06:53
well it is what i'm here to talk about
06:54
but uh before we get started
06:57
i just want to clarify that gradle is a
06:59
company we build the gradle build tool
07:03
and that's an open source project um and
07:07
have a gradle enterprise product which
07:10
large projects scale up their android
07:12
their scale up their gradle builds
07:16
that's just to give a distinction
07:19
because there's a lot of different
07:21
companies we coordinate with
07:22
such as google google builds the android
07:25
gradle plugin and android studio
07:28
um and there's also jetbrains who builds
07:32
and kotlin so we all work together to
07:35
improve performance
07:37
and make your builds more reliable every
07:40
i um just uh yeah just to separate like
07:44
you know there's a lot of different
07:46
companies and it's not always so clear
07:47
what part of what product
07:49
uh goes with which thing
07:52
um so since i've been an android
07:56
i know what it's like you always have
07:58
feature development
08:00
and you have tech debt um obviously
08:04
other things too there's discussions
08:07
product research all kinds of stuff but
08:11
uh in general you can either work on
08:14
feature development or tech debt
08:16
uh and if you're i'm gonna make the
08:18
argument that if you're gonna work on
08:21
you know there's refactoring and there's
08:24
uh but i'm gonna say build speed is tech
08:28
and uh but it always pays off because
08:33
you're always going to build the build
08:35
again and if you make it faster
08:38
you're going to pay off that tech debt
08:40
that you just saved so
08:41
you make your build faster that's saving
08:46
that's making your work in the future
08:49
whereas sometimes you get caught up in
08:51
these refactoring projects
08:54
you know migrating databases it's
08:56
happened to me before you migrate a
08:59
you never use the database ever again so
09:02
did that tech that pay off well
09:04
i mean it was fun i learned something
09:07
um at the end of the day when you're
09:10
working on build speeds
09:12
you're always going to build the project
09:13
again unless your whole app gets
09:17
so just to talk a little bit
09:20
about the cost of builds this is
09:24
something that that um i stole from
09:27
another slide from another gradle
09:29
presentation by cedric
09:31
but if you have 60 seconds of waste in
09:34
and you have 50 builds per day
09:38
which is pretty typical for an android
09:42
you multiply that by 50 developers so 60
09:45
of wasted build like you know
09:47
theoretical performance improvements in
09:49
a build that exists
09:50
50 builds per day and 50 developers
09:54
that it very quickly adds up and and i
09:56
don't think it's sometimes it's hard to
09:58
realize but that's 42 hours lost
10:00
per day which if you're working a 40
10:03
40-hour week that means you're
10:04
losing one developer work week per day
10:08
so and that doesn't even include lost
10:11
um so fast builds really matter
10:14
you could hire five new people without
10:16
paying them no recruiting
10:19
you know the cost of onboarding all that
10:22
so what i'm here to argue is that build
10:27
it always pays off and it's also easy to
10:29
justify working on it because
10:32
the numbers are very clear
10:36
so now that i have you motivated to work
10:40
where to begin this is always always uh
10:43
the question right my build is slow
10:45
where what do i do what do i
10:47
what do i look at so the first thing i
10:50
say is update all the things
10:53
because we have a lot of teams here
10:56
working on a lot of things
10:58
to make your builds faster and so simply
11:01
you're going to get a lot of performance
11:02
improvements so as of this talk the
11:05
latest gradle version is 6.5
11:07
the latest android gradle plugin is 4.0
11:10
latest gradle enterprise plug-in is
11:14
latest kotlin version is 1.3.72
11:17
third-party plugins you should also
11:19
update them third-party libraries
11:21
uh but why like what what's going on
11:23
here right this isn't like
11:25
an iphone where it gets slower every
11:27
year i can say that joke because
11:29
i think you're all android developers
11:30
right but android phones get slower
11:32
every year too right so
11:34
um gradle 6.5 for example has new
11:37
performance apis that
11:39
plug-in developers can use to make the
11:42
um i'm just quickly giving like all
11:46
things have different sorts of things
11:48
they improve with every version but
11:50
the android gradle plugin 4.0 has you
11:52
know caching improvements in 4.0
11:55
also task configuration avoidance i'm
11:57
just like tossing out some
11:58
random things i'm going to go over some
11:60
other features that android gradle
12:03
to improve your build speeds later um
12:07
another really interesting one is gradle
12:09
enterprise plugin 3.3.4
12:11
it's the thing that uploads build scans
12:13
it now does background build scan upload
12:15
so if you update you won't have to wait
12:17
for the build scan to upload
12:19
before you install the app this is a
12:21
huge win for android developers
12:24
column plugin 1.3.72 has compiler
12:27
performance improvements new
12:29
flags to optimize your performance
12:33
third-party gradle plugins are also
12:35
important to update
12:37
because they use the new test
12:38
configuration avoidance api which can
12:40
improve your configuration time
12:43
it's also important to upgrade
12:44
third-party libraries a lot of times
12:46
include improvements to
12:51
incremental annotation processors
12:54
okay so you updated everything to latest
12:57
i know it's easy to say just
12:59
you know bump the version sometimes
13:00
there's incompatibility issues but
13:03
if you really want all the benefits of a
13:05
faster build you should
13:06
update everything and if you don't know
13:10
what the latest versions are because
13:12
obviously this slide is going to be out
13:14
as soon as something is updated there's
13:17
a gradle plugin for that
13:19
you apply the gradle plugin just like
13:23
you run the gradle task dependency
13:25
updates it does it all for you it tells
13:27
you what's out of date
13:28
what's not so i recommend using that
13:33
okay uh before we get started i know
13:37
one thing that i think is really
13:38
challenging for me in making this talk
13:41
is well one i can't see all your faces
13:44
uh so i don't know what the experience
13:46
level is of everybody
13:48
in the audience uh so i'm my goal in
13:51
this talk is to sort of give some some
13:54
tips that everyone can walk away with
13:57
and some ideas to improve their build
13:60
from you know people who aren't so
14:02
familiar with gradle
14:04
all the way to experts um
14:07
and so in order to do that you know
14:09
there might be some things at the
14:10
beginning of the talk
14:12
that you know might be beginner stuff
14:15
or it might be new to you so just hang
14:19
there'll be good stuff coming anyways
14:23
has a life cycle and this is really
14:25
important to know when optimizing gradle
14:27
right there's different areas you can
14:29
focus on in the gradle build
14:31
there's the initialization phase the
14:33
configuration phase
14:34
and then the execution phase so the
14:37
initialization phase is where gradle
14:39
the environment for the build and then
14:41
determines which projects will
14:43
take part in it this is this is
14:46
documented more in the documentation but
14:51
this is basically figuring out how many
14:52
projects you have in your build the
14:54
second part is configuration
14:56
all your build.gradle files are executed
14:60
in your entire project so any any piece
15:03
of code you have in your build.gradle
15:04
file this is why if you just write a
15:06
print line it will be executed in the
15:07
configuration phase of gradle
15:10
and then the last part is the execution
15:12
phase this will run
15:14
task graph that was computed in the
15:15
configuration phase
15:20
you can focus on different parts of
15:23
mostly the configuration phase and the
15:25
execution phase if you want performance
15:28
and so yeah let's let's get started
15:32
right so first let we do some things we
15:35
check for red flags
15:36
what is a red flag though right so um
15:40
first one to check is if nothing changes
15:44
in your build like if you're not
15:45
touching any source files no tasks
15:47
should execute no task
15:49
um should compile right so what you can
15:52
do is if you're on assemble debug twice
15:55
it says in this case this bill there's
15:57
58 actionable tests and 58 were up to
15:60
date so that that's normal right
16:02
but if you do something like that where
16:05
you run a symbol debug twice and then
16:08
three tests are executed then
16:10
that's a red flag right there's
16:12
something going on in your build you
16:13
didn't change the code why
16:15
why is my why are tasks running
16:19
so and yet you should do this check
16:21
regularly right because
16:23
plugins can change you can update your
16:26
any part you know when you have lots of
16:28
people working in the project things can
16:30
change and you don't know
16:31
really what's going on so it's always
16:32
good to to check regularly
16:34
to make sure you're in if you don't
16:37
change any code nothing happens
16:39
so yeah one one that is the case what
16:42
what do you do so if you run this in
16:44
android studio you get
16:45
the android studio build analyzer you
16:47
can also get a gradle build scan i'll
16:49
show you how to do that as well
16:51
the android studio build analyzer is a
16:54
in android studio 4.0 i'm not too
16:57
familiar with it because it just came
16:59
out but i'll show you some
17:01
insights you can gain from it and then
17:02
i'm more familiar with greater bull
17:05
and i'll also show you some insights you
17:06
can get gain from gradle build scans
17:09
so uh in this case what what did this
17:12
what did it rerun it was this inject
17:16
crashlytics mapping field debug task
17:23
filed is misspelled that's kind of funny
17:26
anyways so what what happened here this
17:28
task didn't declare its outputs
17:31
and therefore it's re-running now i'm
17:33
not going to get too deep into like the
17:35
intricacies of tasks and declaring its
17:37
outputs but basically it means
17:39
the task ran it did something but it
17:42
didn't tell the build
17:43
what it did so gradle has no way of
17:46
what this task is doing it doesn't know
17:48
if it should be cached or not
17:51
uh so if you want a little bit more
17:52
insights into this problem you can run
17:54
a build scan it's as easy as adding
17:58
a scan at the end of your build there's
18:01
also a link to the documentation
18:03
um and in the build scan you can go to
18:07
this is the same build i was showing
18:08
earlier where the three tasks ran
18:10
um and if you go to the yeah you go to
18:14
view on the left and you hit you filter
18:18
with success that just means any tasks
18:26
the tasks in the timeline to only show
18:27
the three tests actually executed in
18:30
and so the further down the page you see
18:33
the three tasks that executed
18:35
in this case that was the inject
18:37
crashlytics mapping field debug task
18:39
just saw and once again you see it's up
18:42
to date because there's no declared
18:46
and then there's also the two other
18:47
tasks that ran the sugar debug
18:50
file dependencies and then package debug
18:52
if if something changes
18:54
about your build usually the sugar and
18:55
packaging tasks also have to run
19:01
so what can we another insight to gain
19:06
okay this task ran but it's only five
19:08
milliseconds it's not that big of a deal
19:11
it is somewhat of a problem because it
19:14
is changing things in your build without
19:16
declaring the output so that's not good
19:17
for reproducible builds
19:19
um i don't want to dive too deep into
19:23
issue right now but another thing to
19:25
note is that it's not just
19:26
the task that was executed but also
19:29
plug-in application can
19:30
add some time to your build in this case
19:33
it's only 80 milliseconds so it's not
19:35
that big of a deal i mean of course
19:37
we're looking at milliseconds
19:39
maybe but maybe in your project like the
19:42
same plugin could have different
19:43
behaviors in different projects so it's
19:46
good to check what it's doing um
19:49
there's other you know crash crash type
19:53
plugins in this case
19:54
i just applied bug snag to the signal
19:56
android app the signal android app is an
19:59
it doesn't have bug snag but i just
20:01
applied it just to see
20:02
what would happen in this case nine
20:04
tasks run on every single build
20:07
luckily in their documentation they have
20:08
a way of disabling that
20:10
um the crestlytics enforcement does not
20:12
have a way of disabling it
20:15
and in this build you can see what what
20:18
exactly the plugin is doing in this case
20:20
it's also adding some time to the
20:22
configuration phase
20:23
of the gradle plugin and it's creating
20:28
86 in this case even after disabling it
20:32
i don't want to get into this whole perf
20:34
matters thing of like talking about
20:35
microseconds and builds
20:37
like these these plug-ins you know are
20:39
just adding milliseconds to the build
20:41
it's not that big of a deal but
20:43
sometimes you have plug-ins like the
20:45
same plug-in and a larger build will
20:47
will take up twice as much
20:48
time in this case um 100 milliseconds
20:53
and and there's more tasks in this
20:58
545 tasks still not not that big of a
21:02
um that you know there's bigger fish to
21:04
fry if you look at the configuration
21:07
um in um this build scan
21:12
sorry this is we're going back to the
21:14
build analyzer tool right
21:15
so the build analyzer tool doesn't give
21:17
too much insights into the
21:19
configuration phase of gradle which is
21:21
what we're focusing on right now
21:23
it does tell you over here that the
21:25
configuration phase was about four and a
21:28
but if you want to dive deep into that
21:30
number i recommend using build scans
21:34
um so yeah going back to red flags right
21:37
if you if you have five
21:38
projects and your configuration time is
21:41
that's kind of a red flag right if
21:43
before we're looking at microseconds
21:45
these plugins are taking microseconds
21:47
one second for a plug-in that's that's a
21:51
that is one second added to every single
21:53
build no matter what you're doing in
21:55
and then also here the bug snag plug-in
21:57
is taking a long time
21:60
i i once again i added the bug snap
22:03
you know sometimes um so in this case
22:07
it's a plug-in called witness it's part
22:09
of the signal android build this is an
22:11
open source project you can take a look
22:13
and it's adding 800 milliseconds to the
22:20
of course you can rewrite the plugin in
22:22
this case we can because we own it
22:28
so yeah what can we do about it right
22:30
when plugins take a long time and
22:32
we see this in other apps right in this
22:35
this plugin is adding 25 seconds to the
22:38
build that's that's really a long time
22:40
now that's something to fix
22:42
so what can you do with these plugins
22:43
right so one thing to test is okay let's
22:46
just comment out the plugin
22:47
sometimes you can just comment out
22:49
plugins especially for debug builds
22:51
and then rerun the the build in this
22:55
um so i disabled both bug snag and the
22:59
in the signal android app and now the
23:00
configuration time is half a second
23:03
and that's that's a lot better right
23:05
from five seconds to half a second
23:07
just by disabling two plugins and that
23:10
that affects every single build
23:12
so no matter if you're just running help
23:14
or whatnot you're gonna get time savings
23:17
um and so i guess after looking at a lot
23:21
of android builds i can say
23:23
and this is really really rough and so i
23:25
don't want to get a lot of flag but
23:27
your configuration time should be
23:29
roughly 5 seconds per 100 projects
23:32
if we're looking at android builds right
23:34
can be faster can be slower
23:36
you know you might have your application
23:38
plug-in take up one second but then all
23:39
your other modules take up 20
23:42
that's fine but you should be looking at
23:46
roughly five seconds per hundred
23:47
projects if not then
23:50
then you're um that's a red flag
23:52
something to look at
23:53
right so so one thing you can do about
23:55
it if you don't control the plugins
23:58
is you can disable plugins for local
24:00
developer builds right so we're going to
24:02
talk about a pattern i've used
24:03
builds to optimize them actually i
24:05
learned this pattern at square
24:07
it's called eng build pattern and all it
24:10
is a gradle property it's not a build
24:15
i know there are suggestions out there
24:16
to use build variants to create a
24:20
to improve for local developer builds
24:22
i'll talk about why that's not my
24:24
method later on in a couple slides
24:27
so it's just a gradle property you can
24:29
read about gradle properties
24:31
on this on this documentation
24:34
but what you can do basically is you can
24:38
gradle property and it's really
24:42
these performance improvements and your
24:44
build enabled by default
24:46
because you when a developer checks out
24:48
the build you just want them to be
24:53
this this is a gradle property you can
24:56
in your root project and then you can
24:58
use it anywhere else just like this
25:00
and then what you can do is just not
25:04
plugins right so you don't apply the
25:05
crashlytics plugin you don't apply the
25:08
and then your local developer build is
25:09
faster simple as that right
25:11
you can apply this to any plugin and
25:15
or locally when you actually want to run
25:19
um then you then you disable engine mode
25:23
engine build and that's a simple way of
25:30
another thing you can do is you can just
25:31
add engine build equals false to your
25:32
gradle properties so you can stick this
25:36
and that yeah that's a very simple way
25:37
of just disabling plugins for local
25:41
and that's the engine build pattern
25:42
that's a hammer you can use in your tool
25:45
of of improving gradle builds
25:48
i'll i'll get back to this edge build
25:52
with some more tips but just keep it in
25:55
that this is a a thing you can do
25:59
and this is really similar to how you
26:02
know the kotlin plug-in
26:03
has a bunch of compiler flags you can
26:04
enable it's the same
26:06
same thing right you just enable a
26:08
gradle property and then
26:09
your build does something different okay
26:12
so another thing to look at uh red flags
26:17
uh lots of tasks being created in this
26:19
case there's 16 000
26:21
tasks being created a simple way of
26:24
avoiding this is to use test
26:25
configuration avoidance this is a new
26:28
in the gradle the docs tell you exactly
26:31
you know what to replace um
26:34
you know the way you access tasks with
26:36
another way i won't
26:41
into that right now
26:44
but i wanted to go to my controversial
26:48
so this is this is the the api
26:52
implementation i've seen this debated
26:54
on many android teams from my experience
26:57
many teams not just android uh so which
27:01
should you use right and really
27:04
so so to understand which one you should
27:06
use you should understand what's
27:07
happening right if you have
27:08
module a module b and module c and
27:12
has a dependency on module b
27:16
and c and then module b just has a
27:20
on c you can do a little shortcut here
27:23
and you can declare that module b
27:27
has a dependency on module c using api
27:31
now what that means is that module c
27:35
is automatically added to the class path
27:39
right so um if you're doing this pattern
27:43
you must always be certain that module c
27:45
always consumed together with module b
27:49
you always always use module c
27:52
when you're consuming module b as well
27:54
it's kind of like pairing them together
27:57
so it's it's really a trade-off of
27:58
convenience versus performance that's
28:00
that's what this is um
28:04
and so how do we yeah prove that right
28:08
uh and i don't just wanna say okay
28:11
convenience versus performance i mean a
28:12
lot of times it makes sense to
28:14
use one versus the other we're all
28:16
developers we're lazy
28:18
there's shortcuts we can do uh but let's
28:20
take a look at a real world example
28:22
so this is the k9 mail app
28:26
it's an open source app it uh it's an
28:30
find the github reaper right there and
28:32
it happens to use an
28:34
api dependency on the uh
28:37
in this this one specific line i'll link
28:40
to the slides later in my talk you can
28:42
just click that line
28:48
so what can we do right so going back to
28:51
this tool of using gradle
28:53
or flags in this case we're just going
28:55
to use a gradle property
28:58
and in this case we just call it use
29:02
impul use implementation so when this
29:04
cradle property is enabled we use
29:05
implementation otherwise
29:06
we use api this this will allow us to
29:10
you know run both builds side by side
29:13
and compare the two
29:14
and we can profile it so i'm going to
29:15
give a quick intro to the gradle
29:19
um you know the documentation is right
29:23
basically you write scenarios and then
29:26
execute them to compare to build so if
29:29
if we change the if we make a change
29:32
using the api dependency
29:34
this is this is what you write in your
29:35
performance scenario file
29:37
when you're using the gradle profiler
29:40
and then this is the task we want to run
29:45
and in this case we're going to apply a
29:46
non-abi change to this one java file
29:49
that just means it doesn't affect the
29:53
of that java class it's a simple
29:55
implementation change
29:58
and then we write another scenario it's
30:01
a you know we just copy it
30:02
except in this case what we're going to
30:04
do is we're going to add that gradle
30:06
argument to use implementation
30:09
so we have two scenarios here
30:12
the only difference is the use input
30:18
and if we run the gradle profiler just
30:20
like this with the benchmark what it'll
30:22
is it'll stop the daemon it'll clean
30:24
your build it'll run six warm-up builds
30:26
and ten benchmark builds
30:28
it is important to run a lot of builds
30:29
because gradle builds aren't so
30:32
kind of you know sometimes take more
30:34
time sometimes take less time
30:36
so when you run the griddle profile then
30:40
you'll get a report just like this
30:42
it's really beautiful actually not
30:44
really but you also get a csv file so
30:46
then you can export it to your favorite
30:48
so these are all the benchmark builds
30:51
and you can see that
30:52
using api dependency in this case takes
30:54
more time than the implementation
30:57
here you also get the mean and the
30:58
median the confidence whatever
31:01
so it's about this is in milliseconds
31:02
it's about 10 seconds for the
31:03
implementation dependency
31:05
and it's about 11 seconds using
31:08
an api dependency so about one one and a
31:10
half seconds of difference
31:12
which is about a 15 improvement for for
31:15
specific scenario in the canine mail app
31:18
why is this though so you can also use
31:20
different tools to profile using gradle
31:24
not just build scans but build scans is
31:25
the one i'm most familiar with
31:28
and it'll give you a nice report like
31:29
that you can click the links
31:31
and we can do the same filter we're
31:32
doing before filter the build scans by
31:36
this is the build scan for the success
31:38
build scan for the api dependency in
31:41
uh 14 tasks were successful successfully
31:45
and in implementation dependence you see
31:47
that only seven tasks are ran
31:50
uh which tasks were and so here you can
31:54
of the api dependency if you go further
31:57
down in the timeline view on the build
31:60
and then here's the implementation
32:11
so if we want to take a deeper look at
32:14
why so many tests ran in the api
32:16
implementation we can take a specific
32:18
look at just one of them in this case
32:20
compile debug kotlin task
32:22
in this case you see it tells you why
32:25
and in this case it's because the class
32:28
changed that the reference to the
32:32
the jar where i made the change changed
32:35
so this task has to recompile because it
32:38
has a dependency on that
32:40
we want i want to know even more about
32:43
the difference there
32:44
um this is an enterprise feature alert
32:47
so this is what you can do with gradle
32:49
it has you can capture all the task
32:56
in gradle and then you can compare two
33:03
and here you see the 28 tasks with
33:06
what you find is that for that same
33:07
kotlin compiled task we were looking at
33:10
in build b it declares a dependency
33:16
the library where we made the change
33:20
build b in this case was the one that
33:21
used api so that's a little bit of
33:23
insight you can gain with
33:25
uh build scan comparisons and gradle
33:30
so and and that's just a general thing
33:32
if you add unnecessary inputs to tasks
33:35
you're going to have more things
33:36
recompile when you shouldn't so
33:39
how do we fix this whole api
33:41
implementation mess
33:42
i have api all over my code how do i
33:44
know which ones i can remove
33:46
there's a dependency analysis plugin
33:48
this is written by tony robolic
33:51
and this will help determine which
33:55
api dependencies in your build are
33:56
unnecessary you can read the docs apply
33:59
it to your project and check it out
34:02
all right so the next part
34:05
i'm actually kind of running short on
34:07
time so i'm going to i'm going to skip
34:09
through this whole part
34:10
you want to make sure your annotation
34:11
processors are incremental you can see
34:15
for room you can enable a flag and
34:19
make it incremental you have to get past
34:21
the arguments the java compiler or
34:24
um i apologize i'm going through this
34:28
um another thing to note here is you get
34:30
a remote cache miss
34:31
if you want to know more about those
34:32
there's a good blog post i wrote
34:34
so i won't go too deep into the details
34:38
one thing to note is that because you
34:39
have both a cache miss and room is not
34:41
incremental by default
34:42
although you can fix both those things
34:44
using the android cache fix plugin and
34:46
applying the compiler flag
34:48
i like to recommend moving room to its
34:51
or module and this is a pattern you can
34:55
annotation processors or plugins or
34:58
kind of slow in your build it's a place
35:00
to focus on when modularizing so move
35:03
to its own place in your build
35:09
so another this is a cool new feature in
35:10
the android real plugin 4.0 you can
35:12
disable unused features
35:14
so what are unused features right so
35:17
let's talk about the cost of generating
35:18
the build config file
35:20
uh so this is this is a build a
35:23
relatively large android build with 186
35:26
and and so there's 186 generate build
35:31
and that takes that adds about half a
35:32
second to the execution phase
35:34
of this build uh but if you look at the
35:37
avoidance savings it's saving
35:39
even more than that it's about 21
35:42
so you know if the build config weren't
35:44
up to date it would have
35:46
spent even more time
35:51
and it's also unused so progress is
35:52
going to remove it later so it also adds
35:54
time to your proguard in analyzing the
35:57
and the other thing to note is that
35:59
build config adds java sources to your
36:01
pure kotlin modules
36:02
so if you have a java and
36:06
what to note here is that there's a bit
36:08
of a performance impact to having mixed
36:10
sources within a module if you have java
36:11
sources and kotlin sources within a
36:13
module takes a little bit longer to
36:16
in order to make sure they interact
36:19
the other thing is like it's just also
36:21
not a good developer experience right
36:23
you have you know when you're typing and
36:26
you get this autocomplete and you're
36:28
how many build config files are there
36:31
um the other issue is like if if you're
36:33
trying to pick up the version code
36:35
this can also lead to bugs so if you
36:38
accidentally pick the version code from
36:40
project which is one by default in
36:43
then you're going to have a bug so i
36:47
oh there's also other features you may
36:50
may never heard of such as the aidl
36:54
which is part of the android gradle
36:56
plugin and so these features are enabled
36:58
by default because it makes development
37:00
right you can just stick an aidl file in
37:03
your build and it compiles automatically
37:05
add anything to gradle configuration
37:07
that's really great when you're just
37:09
but if you have 186 modules in your app
37:12
you want to disable these features
37:18
and it also this is the kotlin
37:23
the kotlin plug-in it also eagerly
37:26
um creates these tasks so anyways
37:29
there's a new feature in android gradle
37:30
plug-in 4.0 you can disable these
37:32
features by default
37:33
in your gradle.properties file i
37:36
recommend disabling them all
37:38
and then what you can do is just enable
37:40
them when you need them
37:41
so what you can do is to android in
37:45
any build.gradle file so for example
37:47
your app build.gradle file
37:48
you enable build config generation there
37:53
okay so this last part of this talk i'm
37:55
getting really close to the end of this
37:57
is about code multipliers right
38:00
um things in your bill that multiply the
38:03
amount of time needed
38:04
to compile the first one is jettifier
38:08
it migrates support library dependent
38:10
libraries to rely on android x packages
38:12
what that means is it runs a transform
38:14
if you have this flag in your gradle
38:15
properties you're running a transform on
38:18
every single dependency so if you you
38:19
know you see this in your build it
38:20
doesn't appear in build scans but
38:22
um if you upgrade your gradle version if
38:24
you upgrade your android gradle version
38:26
update your build source you're going to
38:28
run all these transforms again
38:30
so if you don't need it i recommend
38:33
disabling it of course but it's a little
38:34
bit trickier than that
38:35
lots of projects out there um
38:39
there's all sorts of different
38:40
constraints there's also a small bug
38:43
with dependency substitution
38:44
in android x which will be fixed in a
38:48
uh there's an issue tracking that there
38:51
i don't have time to explain all the
38:52
details of that but the issue is very
38:55
interesting if you use dependency
38:57
substitution it's a gotcha to watch out
38:60
so if you're stuck on the jet of fire
39:02
you should push the libraries you depend
39:04
on to update of course
39:05
but one thing you can do is you can use
39:08
this gradle plugin can i drop the
39:10
you run that task and it'll tell you
39:12
what dependencies in your project still
39:14
need to be judified
39:16
another thing you can do is you can
39:20
if you just have one library that isn't
39:22
gentified in your project
39:23
just run the jettifier on it and upload
39:27
and be done with it that's my
39:31
of course from a security perspective
39:34
might not be able to verify the
39:35
checksums or use dependency verification
39:38
on this just something to note
39:40
but it might be a build speed win if you
39:43
just have one dependency left or a
39:46
that need to be judified the next code
39:49
multiplier we want to talk about is
39:50
build flavors this is
39:52
i think something that comes up in every
39:55
specifically flavor explosion so what is
39:60
i i didn't know so i went to urban
40:01
dictionary flavor explosion is when you
40:04
that is not what you thought it was
40:06
causing a surprising surprise
40:08
so what is the surprising surprise in an
40:12
it's when you add a build dimension
40:14
multiplying build speed in a surprising
40:17
so what exactly is that every build type
40:20
you have for example
40:21
debug and release is multiplied by build
40:24
flavor let's say free and paid and
40:27
play store amazon store whatever and
40:31
variants and build variants are code
40:36
because every single so if if you have
40:39
most of your app in this module with all
40:41
these build variants
40:42
that means that that all that code needs
40:45
compiled that many times so if you have
40:49
that means all the code in that module
40:50
needs to run six times
40:52
six times as many tests are going to be
40:53
configured in the configuration area
40:56
all the resources you have
40:59
in that pngs whatever they're going to
41:02
the amount of cash in your project so so
41:06
what what can you do about this one
41:08
thing you can do very simply is you can
41:10
a gradle property this is you know this
41:13
pattern i talked about earlier
41:14
you can just enable only one variant for
41:17
debug builds by default so if you have a
41:21
and this happens sometimes in builds for
41:24
um you can just disable the variants you
41:27
very simply and then if you actually do
41:30
need a variant so for example on ci or
41:32
you need to check out the other variant
41:33
you can just enable a gradle property to
41:35
actually build that variant
41:37
once again it's important to
41:41
run the griddle profiler to actually see
41:43
that this makes a difference right on
41:44
some builds this might make only
41:46
10 10 millisecond difference that
41:48
because it's not worth
41:49
adding this extra hassle of disabling
41:53
but in some builds might be tons of
41:55
flavors and this might actually save a
41:57
ton of time so it's important to
41:58
you know not just take my advice run the
42:00
griddle profiler and verify it
42:04
so yeah once again there's mostly
42:05
configuration time when
42:07
but if you have flavors that you never
42:08
ever use you should definitely disable
42:14
so this next one is how to cut build
42:15
times in half it's not actually how to
42:17
cut build times in half
42:18
but it's very very similar to the
42:23
so for all your library projects right
42:26
you have the debug and the release
42:28
variant assembly bug assemble release
42:31
that means two times the code just like
42:33
i said before two times resources two
42:35
times the task two times the tests
42:37
two times the test that's also another
42:39
thing to note right
42:40
so the the question to ask here is how
42:44
in your build does the debug and the
42:45
release code differ for all your library
42:47
modules like if you have
42:49
100 modules how many of those actually
42:51
have different code in the debug
42:53
and the release variants it's usually
42:56
maybe one maybe two usually
42:59
not that many so why would you build all
43:03
for all those modules even if you're not
43:05
you know you're only using the debug
43:06
variant locally you still need to build
43:09
that adds ci build times it also gets a
43:13
little bit confusing if you run you know
43:14
if you run the normal gradle life cycle
43:16
test task runs all your tests twice
43:20
that's that's kind of a time waster and
43:22
if you run test debug that's not going
43:24
if you have java only modules it's not
43:26
going to run those tests
43:28
and then what's also really annoying is
43:30
if you if you switch you know sometimes
43:32
you do need to test the release variant
43:33
and you switch to it and you have to
43:35
recompile everything
43:37
and like i said before you see it takes
43:39
twice as long so what can we do about it
43:41
so what i was talking about earlier the
43:44
you can use the variant filter we were
43:48
talking about before if the variant is
43:50
and your library modules you ignore it
43:53
so this will never build the release
43:56
but there's actually something you can
43:58
do that's even a little bit better than
44:02
disable the debug variant always use the
44:06
and if and if you also disable the build
44:11
the debug and the release variant are
44:13
going to be exactly the same
44:15
and in that case you don't need to only
44:17
do this on edge build just do it for all
44:20
all ci builds all local builds every
44:22
single build in your project
44:23
just disable the debug variant for
44:27
and then one thing you'll have to do is
44:30
application module you can just add the
44:34
to the application module that way
44:36
you'll just pick all the release
44:37
variants of all your libraries
44:39
and just like that your build times will
44:45
and the other benefit is you know when
44:47
you do need to test the release field
44:48
you don't have to recompile everything
44:52
so i guess what the lesson here is
44:55
disable stuff right use gradle
44:56
properties find out what you can disable
44:58
there's a lot of stuff running
44:60
disable it and measure it
45:03
one thing you can do is to measure is
45:05
configuration time so
45:07
i went ahead and i did a performance
45:10
of some of the the things i talked about
45:13
um i ran a build the standard build is
45:16
at the bottom everything's enabled
45:18
the one at the top i disabled the debug
45:20
variant of all the library modules
45:23
the one in the middle i disabled the
45:24
debug variant and the android gradle
45:27
features that weren't needed and this is
45:31
canine mail app and uh what you can see
45:35
is this is just the configuration time
45:37
so it's not compile time nothing like
45:40
unfortunately it's a really long time to
45:41
run profiling for all these builds
45:48
yeah you can see that this is about 13
45:52
30 configuration time improvement and
45:54
this scales to all your builds so if you
45:56
a way way longer build i just got word
45:58
that i need to wrap up so i'm gonna i'm
46:00
gonna run through these slides so
46:02
yeah you can see this is the regular
46:03
build 500 task configured
46:07
and then uh when your debug mode there's
46:09
this is the android gradle
46:11
um yeah you can see a lot less tasks are
46:15
more things you can disable there's a
46:16
new apis in the nd gradle plug-in here's
46:19
some other ideas you can do in edge
46:21
build is have a higher min sdk
46:23
this disables multi-dexing it disables
46:25
core library sugaring
46:27
other things you can do is strip out
46:29
other languages strip out large images
46:32
strip out native libraries so you don't
46:34
have to compile those try new versions
46:35
of agp these are just
46:37
ideas you can add to your own edge build
46:39
to make your build faster
46:41
the other thing is always measure so i
46:43
just want to give a sneak peek of
46:45
upcoming performance enhancements before
46:47
let you all go first one is file system
46:49
watching this is an upcoming
46:51
experimental feature andrew and gradle
46:55
what this does is if you have a build
46:57
with long snapchatting in
46:58
task and puts time such as this build
47:00
where it's six minutes
47:02
that'll drastically reduce that time by
47:04
watching the file system
47:05
you can enable it with this flag there's
47:07
a blog post about it that talks more
47:10
now the next one is configuration
47:12
caching so if you have a build with the
47:13
long configuration time
47:18
your build has executed all the tasks
47:19
for all the project
47:22
so what you can do is well upcoming and
47:25
we're working on a feature to cache the
47:28
configuration so this will mean you
47:30
don't have to do configuration time
47:32
uh i'm gonna skip this part of the bill
47:34
this is talking about how configuration
47:36
okay some other talks some other
47:38
resources if you're interested
47:40
is this talk by cedric shampo this is
47:43
about two years ago but
47:44
um android builds the same basic
47:47
principles of improving android builds
47:49
haven't changed much actually stole some
47:51
slides from this talk
47:53
there's also a really good talk by
47:56
google i o 2019 on scaling
47:59
on different features and gradle
48:00
features you can use in scaling your
48:02
build for large projects i've also got
48:04
to plug my own talk this talks about
48:07
certain uh build performance
48:10
improvements that you'll get by like
48:11
sharing the gradle daemon or
48:13
talking about garbage collection time
48:17
you can also measure the remote build
48:19
cache performance i have a blog post
48:21
there these are just some resources blah
48:24
i gotta wrap it up i think i'm way over
48:25
time i really apologize for that
48:28
um so now i'm going to get started on
48:33
um and then also right down there
48:35
there's a speaker deck link to
48:37
this talk so just type that in your
48:40
uh and then you can get yeah all the
48:44
i apologize for taking so much time no
48:46
no it was great we want to encourage
48:48
everyone to just stick around really
48:49
quick because we've got a great panel
48:51
discussion coming up
48:53
uh this is definitely something that
48:54
you're going to stick around for uh
48:56
talking with a lot of very very
48:57
knowledgeable and experienced android
48:59
experts with scaling up android builds
49:01
asking them all the questions you wanted
49:03
to know about build performance static
49:06
prioritizing performance versus features
49:08
and more so there's a lot of cool things
49:10
i do want to give nelson just a couple
49:13
to ask some questions to answer some
49:15
questions we did have a number of
49:16
questions coming up
49:17
so i'm going to ask john to to make sure
49:19
that he's presenting
49:20
uh all the the questions that we've had
49:24
and as soon as we get through a couple
49:25
of those we're going to um
49:28
introduce our panel so definitely stick
49:30
around for a little bit
49:31
and get your questions uh juiced up here
49:36
so nelson take it away we're gonna give
49:38
you a couple minutes on this all right
49:43
all right you should be able to see the
49:44
questions you want to read that first
49:45
question on the top there
49:46
and go oh wait am i
49:50
anything on my screen nope we just
49:53
yeah we just had it up uh
49:57
and yeah there we go can you see those
50:00
yes okay is there any information
50:04
about how much capped plug-in slows down
50:05
builds and how to improve
50:07
on these build times like dagger and
50:09
dagger hilt so this is a really good
50:11
question that comes up a lot build scans
50:13
how much time is spent with normal and
50:16
java annotation processors but they
50:18
don't challenge time
50:18
spent with cat however there is a flag
50:22
in the capped extension i think it's
50:25
show annotation processor times or
50:27
something like that
50:29
and using that then you can see how much
50:31
time is spent with these
50:32
annotation processors i also talked
50:35
in the talk i linked about the internals
50:40
and the gradle doctor plugin that i
50:42
built actually measures all the time
50:43
that capped is spent
50:45
with dagger as an annotation processor
50:49
so i recommend checking out my talk if
50:51
you want to know more about that
50:54
okay um what about release build with
50:57
pro guard and all appeasing
50:58
it consumes more time than debug build
51:03
um so yeah you're you're still gonna
51:05
have the release build it's still gonna
51:07
take a lot of time with all the
51:09
but you won't have to recompile all the
51:11
dependent libraries
51:12
um also with proguard the
51:16
improvements to d8 and r8
51:20
will um you know make
51:23
the the prograd time a lot faster
51:27
um there's also things like the number
51:29
of rounds that pro guard and d8 and r8
51:31
and whatnot are making on your build
51:34
tweak to improve that time
51:43
what is a lower bound to expect from
51:45
gradle builds when their actual code
51:46
change is made what is
51:47
fast that that's a hard
51:51
that's a hard question answer um it
51:53
really depends on the size of your
51:55
project how many lines of code are in
51:57
how many developers are working on the
51:59
project well actually that one doesn't
52:00
but just the the lines of code um
52:05
so i can't really give you a good answer
52:09
um actually one i can give you is when i
52:12
was working at soundcloud
52:14
our average build time on local
52:17
was uh 50 seconds on average
52:21
so that's i know that's a fairly large
52:23
app and that's that was the average
52:26
um does api versus implementation really
52:29
matters when using kotlin as far as i
52:31
know collin doesn't support compound
52:33
that is true kotlin does not support
52:34
compile avoidance um the k n mail app
52:37
does use a mix of kotlin and java
52:40
and so that but the tasks that were
52:43
and not rerun and avoided in the sample
52:47
those were kotlin tasks so it does it
52:49
does help with kotlin
52:59
yeah what's another i think i
53:08
oh does the five seconds for 100
53:10
projects apply when using build source
53:12
notice my configuration times are seven
53:14
seconds total it so it starts using five
53:18
yeah i would say it probably still
53:20
applies if your configuration time
53:22
when using build source is long um
53:26
that might indicate something else with
53:28
something being rerun
53:30
uh so there might be something to
53:31
investigate as well run a build scan
53:33
check it out see what's
53:35
taking a long time yeah like
53:42
i was going to say i think these are
53:43
actually a lot of good questions and in
53:45
fact we've got some on here
53:46
that i think would be great uh to get
53:48
the panel on as well
53:49
so why don't we why don't we get the
53:51
panel in here too so what i'd like to do
53:53
is invite all of our
53:56
panelists here to to enable their
53:58
webcams they should be able to come on
53:59
enable your microphones
54:01
and let's get the panel going because i
54:02
think there's some of these questions
54:04
uh that our panelists have a lot of
54:06
experience on too there's some of these
54:07
questions i think that are very specific
54:09
to your presentation but i think we also
54:13
have a couple of good
54:14
uh questions here so before we before we
54:17
dive into the questions you can see
54:19
everybody we've got a fantastic
54:20
uh panel line up here today before we
54:23
get started i wanted to just let
54:25
everybody take just a minute to
54:26
introduce themselves
54:28
where they're working what they're
54:29
working on and to get an idea
54:32
because again this thing is all about
54:33
build speeds about performance
54:36
the scalability obviously you know that
54:39
you know israel and yvonne john uh you
54:41
know zach they're not
54:42
uh we're not talking about people just
54:44
working on uh backyard
54:46
garage projects we're talking about
54:47
people with a lot of experience working
54:49
uh some major projects so i think
54:51
they've got some good perspective here
54:54
okay let's start with um zach really i'm
54:56
just gonna go from left to right on my
54:57
screen zach if you want to start the
54:59
john israel and yvonne
55:00
talk a little bit about um what you do
55:03
how many repos you're working in
55:05
and and also the fun debate that always
55:06
pops up we can talk about later too a
55:09
sort of the monorepo versus multi repo
55:12
um there's a couple other questions i'd
55:14
you all but let's get let's get started
55:16
with that so zach why don't we
55:18
why don't we get you going oh uh
55:21
can everyone hear me okay look at me yep
55:25
um hi i'm zach spears i work at slack
55:28
in our new york office um prior to slack
55:32
uber and flipboard so you're going to
55:36
from there some bit about
55:40
our setup we have really just one
55:44
repo that one repo and only one app
55:47
that we maintain so it's a it's a sort
55:51
setup we have about 30
55:55
android developers working in it um
55:59
give or take so yeah
56:02
great john far away
56:12
ah john you're muted
56:19
okay john we should be able to hear you
56:21
now trying that again
56:23
um hello everyone my name is john
56:25
rodriguez and i work at swear on the
56:27
cash out product previously on the point
56:31
um but doing android things
56:34
and i'm contributing and a few of the
56:37
square open source repos as well
56:39
um a quick search and terminal tells me
56:42
that cash app has 261 gradle modules and
56:46
uh considerably trying to modulate
56:49
um point of sale um i believe has
56:53
in the thousands of modules if not the
56:56
um when i left it was around like 400
56:59
um that gives you kind of um a scope of
57:02
like the size of projects that i've
57:05
um i've uh played around with like
57:08
gradle plugins as well and i've given a
57:09
couple of talks on the android gradle
57:11
plugin so lots of good questions coming
57:14
you know you we as people try to
57:16
increase their speeds
57:24
prior to me and myself hey hello
57:25
everyone my name is uh israel ferry
57:28
and i'm i work at dropbox in the mobile
57:32
uh doing android mostly uh in the new
57:36
and we have a monorepo for all the
57:41
and we have over 300 modules there for
57:44
android um but the ios
57:47
application is there too
57:50
and yeah we are using gradle for android
57:57
great even hi everyone um my name is
58:01
ivankovilovich and i'm
58:03
an engineer on the android cradle plugin
58:08
our setup is i think when i checked
58:11
projects that we have that are related
58:13
to the android gradle plugin
58:15
and some other libraries that are used
58:16
by the android studio
58:18
um part of the build is in gradle and
58:21
part of the build is actually in bazel
58:23
because of the some internal
58:25
requirements requirements that we had
58:27
when it comes to building the actual ide
58:30
yeah that's about it okay
58:33
good i there were some one of the
58:35
reasons i want to get the panel involved
58:37
some of the questions coming in i
58:39
thought were really applicable to the
58:41
um if you know what we're going to click
58:44
through some of these are there anything
58:45
that you guys are seeing on here that
58:47
you'd like to address
58:49
quickly before we uh get into some other
58:51
questions i'm happy to kind of
58:53
cherry-pick some of these questions here
58:55
anything that you see on on here that uh
58:58
that you guys want to answer
59:00
can i put yvonne on the spot for that
59:02
original capped question bit just since
59:05
worked on it quite a bit
59:08
yeah i think that one was was
59:10
interesting so it was i think the first
59:12
that showed up on slido uh the question
59:15
was what is the impact of kapt
59:17
on on build speed so when you're using
59:21
um that's a good question and
59:24
before that i think i need to explain
59:26
just a tiny bit how kpt works
59:28
so whenever you're running kpt
59:31
basically there are two tasks that that
59:34
matter in your build
59:35
the first one is the one that generates
59:38
java stubs from the content sources and
59:42
actually runs annotation processing so
59:46
is basically a lightweight coupling
59:49
so the the compiler front 10 runs it
59:51
resolves all the types
59:53
and then it just generates the the the
59:56
java stuff so you can think of it like
59:58
in terms of the duration it is it's like
01:00:01
comparable to actual coughing
01:00:03
compilation the one that's actually
01:00:04
generating the full class files
01:00:06
um after that the kpt
01:00:09
task is essentially just a wrapper
01:00:14
java annotation processing apis kpt
01:00:18
is literally just invoking jdk compiler
01:00:21
and just passing all the processors and
01:00:23
all the setup that you may have put in
01:00:26
and just invoking annotation uh
01:00:28
processing there
01:00:29
now um when it comes to the build speed
01:00:31
and the impact so
01:00:32
copying the compilation supports
01:00:34
incremental processing so
01:00:36
you know when your team and you have a
01:00:38
change in the project the stop
01:00:39
generation is pretty much
01:00:40
it should be able to run incrementally
01:00:42
so so from that point of view it
01:00:45
shouldn't be too long
01:00:46
now the one of the issues was that uh
01:00:49
before kpt was supporting incremental
01:00:51
notation processing
01:00:53
you would essentially rerun all of the
01:00:54
annotation um processors you and you
01:00:57
need to reprocess all of the sources
01:00:59
which in apps that had you know that
01:01:01
have lots of sources
01:01:02
it is actually quite costly however like
01:01:04
if you're using annotation
01:01:06
processors that do support incremental
01:01:08
annotation processing
01:01:09
i think you should uh you should not see
01:01:11
a big impact there and dagger does
01:01:13
support it i think from
01:01:15
2.18 if i remember correctly i think
01:01:17
it's been enabled by default
01:01:19
um so yeah give it a go i'd say
01:01:21
definitely try it out and see what is
01:01:28
i had a couple i saw a couple of
01:01:30
questions that i wanted to give just
01:01:31
small uh addendum to to nelson's great
01:01:35
one was on obfuscation and r8 um
01:01:39
we run that only on our ci builds um
01:01:42
it's important to run them um
01:01:43
um and sometimes it has shown um
01:01:48
some inadvertent runtime crashes like
01:01:51
for uh using json parsers like json or
01:01:54
moshi maybe we've
01:01:56
misconfigured something um
01:01:59
and also during espresso tests because
01:02:03
currently the test apk what's what's
01:02:07
bundled into the test apk is unable to
01:02:09
necessarily do the the tree walk of
01:02:11
references that would otherwise be
01:02:13
comprised in your main apk and there
01:02:15
are ways to go around that i believe
01:02:16
zach wrote a plugin that helps there and
01:02:18
there's some other
01:02:20
ways to go about that but it's really
01:02:21
helpful to run the obfuscation however
01:02:24
to the point behind the question is it
01:02:26
probably doesn't have to be in your
01:02:28
local developer build because that's
01:02:31
it's kind of an 80 20 thing so if you
01:02:33
can run that nci and maybe have a couple
01:02:34
of tests that cover the cases
01:02:36
like launching the app and making sure
01:02:38
all the the app initialization doesn't
01:02:41
r8 might have been a little too
01:02:42
aggressive and you may need to tweak
01:02:45
it might be a nice healthy strategy to
01:02:47
getting your build times to an
01:02:48
acceptable fast level while still not
01:02:50
compromising your
01:02:51
production app integrity um a second
01:02:55
uh someone asked how what's fast and um
01:02:58
the answer given there made a lot of
01:02:60
sense of like well it depends on your
01:03:03
um one one i guess general solution that
01:03:06
helps a lot is we strive to make in our
01:03:08
multi-module project
01:03:10
as many and we're all we're talking from
01:03:12
this perspective of android developers
01:03:14
as many modules don't that don't need
01:03:17
parcelable activity intent if you can
01:03:21
away to like your top most
01:03:25
nodes in your gradle graph and like when
01:03:27
you're compiling the activity you don't
01:03:29
necessarily have to
01:03:31
have intent leaking in all those modules
01:03:34
and a tent is essentially
01:03:36
a specialized map and so if you can pass
01:03:39
around a map of data and eventually
01:03:41
bundle that later on in the build
01:03:43
in the module that has to speak to
01:03:46
you get a lot of benefits from that
01:03:48
first of all you could eliminate
01:03:50
roboelectric from a lot of your tests
01:03:52
a big source of like test run slowness
01:03:56
you can remove just a lot of things from
01:03:58
the class path because you don't need
01:04:01
you you just reap a lot of benefits at
01:04:04
exponential scale
01:04:05
and so like i think from a first pass if
01:04:09
we've noticed um increasing or
01:04:12
decreasing build times
01:04:13
when we achieve by essentially we graph
01:04:18
and using colors what are our android
01:04:20
and pure jvm modules
01:04:22
and basically look to advance the front
01:04:26
pushing android android further to the
01:04:27
top and as we do so we do see notable
01:04:30
impact on build times
01:04:33
let's actually john that's a good segue
01:04:35
because you know you're talking about
01:04:36
build times i'd kind of like to see
01:04:38
what the panel's thoughts are on some of
01:04:41
surprising build performance
01:04:43
improvements that you guys have made
01:04:45
in your apps what what have been some of
01:04:47
the things that you've done
01:04:48
to increase build times what's what's
01:04:52
what's worked i have a recent one um
01:04:55
but first of all i will say if you don't
01:04:56
measure you know that it's happening and
01:04:59
we were aggressively improving the
01:05:01
execution time of the bill
01:05:02
and we were ignoring the configuration
01:05:04
time and then when we were checking
01:05:06
configuration time we realized that that
01:05:08
more than what we were saving on
01:05:10
execution i was like okay we should
01:05:12
start mentioning configuration and
01:05:14
execution and taking care of both
01:05:17
um and and pretty much any plugin that
01:05:21
to your bill it's a hassle right
01:05:24
and then and we need to be really
01:05:28
and be measuring those every single day
01:05:32
you know ideally that that's an
01:05:37
job in the ci and then we have some
01:05:39
alerts and those alerts will let us know
01:05:41
if there is any regulation in the speed
01:05:43
and when you do that when you have that
01:05:46
it's way easier to decrease the build
01:05:51
and uh stop impacting the team really
01:05:54
so we had this uh one plugin i won't
01:05:58
but we had this one plugin that was
01:06:01
adding a listener
01:06:03
to each configuration of each module
01:06:06
and that means the execution time and
01:06:10
and listeners per m configurations
01:06:14
in each module and that adds like
01:06:17
30 seconds to our configuration just
01:06:19
that one plug-in
01:06:24
just a headset be careful having
01:06:26
plug-ins and make sure that you
01:06:29
do perform and before and after
01:06:31
measurement to see how that impacts your
01:06:34
yeah i wholeheartedly agree with that i
01:06:38
we have the sql delight and wire plug-in
01:06:41
that we're using internally in our app
01:06:43
and we're constantly mindful of how it
01:06:45
changes may inadvertently affect build
01:06:48
so measuring that either if you're using
01:06:50
the gradle build scan functionality or
01:06:52
you know profiling the file and just
01:06:54
cutting it out to standard out and
01:06:56
diffing it across
01:06:57
builds like you can at least come up
01:06:59
with some rudimentary heuristic
01:07:02
um to show like hey i added this plugin
01:07:05
because you want to add plugins right
01:07:07
reuse open source code that you don't
01:07:09
have to otherwise write yourself
01:07:11
but to israel's point measure measure
01:07:13
measure so that you can um
01:07:15
catch these things as early as possible
01:07:20
i can tell an interesting story that we
01:07:23
or rather we kind of still run into
01:07:26
it's a bit of a whack-a-mole game where
01:07:29
it's easy for an annotation processor to
01:07:31
accidentally become not incremental
01:07:34
if it so even if it declares itself as
01:07:37
incremental if it doesn't
01:07:39
adhere to certain requirements for
01:07:41
incremental processing
01:07:42
like attaching a source element for
01:07:46
file that it generates then it will run
01:07:49
non-incrementally and a common case that
01:07:52
we run into this with is with dagger
01:07:54
where dagger is sort of maybe a little
01:07:57
too helpful in the sense that if you
01:07:59
like annotate your class your
01:08:00
constructor with
01:08:01
inject but then don't remember to add
01:08:03
the dagger compiler
01:08:05
to your actual annotation processing for
01:08:09
if you use that somewhere upstream and
01:08:11
the dagger compiler is running there
01:08:13
it will just see that it doesn't have a
01:08:16
corresponding factory generated for it
01:08:19
generate it for you upstream but now
01:08:20
it's generating a file
01:08:22
that has no source element in your
01:08:25
current compilation set
01:08:27
and that's basically something that i
01:08:29
think maybe like
01:08:30
once every month or so uh we
01:08:34
you know we have a steady flow of new
01:08:36
modules coming in and
01:08:37
this one always comes up as a accidental
01:08:40
uh and it's easy to happen because it's
01:08:42
not like it like fails your build if you
01:08:45
but uh yeah that makes a big difference
01:08:49
because at the end of the day it's like
01:08:51
our monolithic app module
01:08:53
that is now running not incrementally
01:08:55
and that's where like 90
01:08:57
of our code is still and uh fixing that
01:09:01
takes an incremental build from like you
01:09:03
know a minute 20 seconds down to as low
01:09:06
depending on what kind of files you're
01:09:10
yeah it sounds like it sounds like
01:09:11
either failing faster or having a lint
01:09:14
warn people would be a great way to
01:09:17
yeah the way that we've solved it
01:09:18
basically now is we have a
01:09:21
uh we call just slack plugin that is a
01:09:24
plugin that sort of like helps manage
01:09:25
all of our projects
01:09:26
and if you want to add dagger to a
01:09:30
we actually don't expose the like raw
01:09:32
dagger dependencies instead we have like
01:09:35
so it's like slack and then inside like
01:09:38
features dagger enabled
01:09:40
um and that will do all the appropriate
01:09:43
it's nice because it also handles like
01:09:45
you know if you're in an android project
01:09:46
if you're in a plain java project versus
01:09:48
things like that
01:09:53
israel did you have to comment on that
01:09:57
not about that one i mean that one is a
01:09:59
really good way to handle
01:10:01
the problem by it's like so i had a i
01:10:04
forgot to mention that
01:10:05
configuration phase on the radial bill
01:10:08
is not cacheable as
01:10:10
of now it's coming but not as of now so
01:10:13
that means that when you add a module
01:10:16
you're impacting
01:10:17
every single task that you run on gradle
01:10:18
so i mean even if you clean you may be
01:10:21
um so like that's why configuration you
01:10:24
make sure in configuration is very
01:10:25
important so let's uh actually i want to
01:10:28
i want to follow up on that
01:10:29
what and everyone can answer this what's
01:10:31
the criteria that you guys
01:10:33
set for introducing a new module in the
01:10:36
when do you split an existing module
01:10:38
into multiple modules
01:10:44
i don't know if we have set criteria um
01:10:46
i mean there are i don't know if every
01:10:48
module is the same like you have
01:10:50
new features that should probably begin
01:10:54
set of modules but then you may also at
01:10:57
the same time want to refactor
01:10:59
bundles of logic that are in the main
01:11:02
to be reused elsewhere and those are at
01:11:04
least two different strategies of how to
01:11:06
modularize i mean maybe
01:11:07
other people have some good
01:11:14
uh for us yeah i think that policy of
01:11:18
every new feature the default
01:11:20
expectation is that that should probably
01:11:21
go in its own module
01:11:23
um we are in sort of as i mentioned
01:11:25
earlier we're in this sort of classic
01:11:28
we're trying to modularize but we still
01:11:29
have like 90 of the code
01:11:31
in the like historic app module
01:11:34
um and i don't know that there's as much
01:11:38
of a like rule or criteria for moving
01:11:41
as much as like thunderous applause when
01:11:43
someone does actually take the time to
01:11:45
go move something out
01:11:47
um yeah there will be some like you know
01:11:49
what should go here what should go there
01:11:51
kind of discussion but
01:11:53
uh in general i think we've just
01:11:57
tried to promote it whenever a good
01:11:60
opportunity comes up and not really
01:12:01
worry about like
01:12:02
bike shedding like the design of you
01:12:04
know what goes in different modules
01:12:06
yeah that's fair i think here we need to
01:12:10
on allowing every feature team to
01:12:14
create their own modules when they need
01:12:16
it but at the same time we need to start
01:12:18
for each module we create they are
01:12:22
a bunch of tasks that are created for
01:12:24
those modules so we need to make sure
01:12:26
that we are not like bug smart is going
01:12:28
uh one task for each module that we
01:12:31
create right so like we need to make
01:12:32
sure that we are not creating like
01:12:34
500 new tasks per module that there is
01:12:36
no a lot of like over
01:12:38
weight on creating a module because then
01:12:40
everything in the configuration
01:12:42
especially is going to be more uh
01:12:44
expensive so you know we did
01:12:47
we we worked on measuring how much each
01:12:50
module impacts our build because
01:12:53
because we are close to 500 and
01:12:57
we wanted to be sure that that was not a
01:12:60
and i think we were creating like 70
01:13:02
tasks per module
01:13:04
and we were able to you know by doing
01:13:07
the bed mode or engineering mode that
01:13:08
nelson was recommending we were able to
01:13:10
disable some plugins that
01:13:13
then it creates less transfer modules is
01:13:16
at some point um yes it's microseconds
01:13:19
but like microseconds
01:13:20
per 400 it's less microseconds and they
01:13:23
become more seconds right so
01:13:25
yeah so you need to balance the
01:13:28
scalability with
01:13:29
that with the flexibility for the
01:13:33
yeah i think that that point about
01:13:36
being mindful the plugins that you add
01:13:38
is really important um
01:13:39
if you use that dependency analysis
01:13:42
nelson mentioned in his talk it actually
01:13:46
basic detection for certain types of
01:13:47
like known slow plugins that
01:13:49
you could basically remove because it
01:13:53
sees them as unused
01:13:54
um capped is the sort of elephant in the
01:13:58
with that um captain general if you can
01:14:02
makes a huge difference like even if
01:14:03
you're using api and implementation
01:14:05
um if if you have some downstream
01:14:08
dependency where the
01:14:09
uh you have it's coming through as an
01:14:12
implementation dependency for something
01:14:14
even if you change that the class path
01:14:16
still changes for capped
01:14:18
and capturing runs all of itself again
01:14:21
it's uh yeah it's worth
01:14:24
doing like a one-time audit i think
01:14:28
analysis plug-in just to see you know
01:14:31
if nothing else at least removing the
01:14:32
unused ones um it'll make a bunch of
01:14:34
recommendations for other things you can
01:14:37
going to be more involved the first time
01:14:40
it's i've found it to be really useful
01:14:45
i see a question here about why disable
01:14:48
debug versus release does it make any
01:14:50
um i think the answer is more
01:14:56
i don't what our team does is
01:15:00
we disable debug because release would
01:15:04
impact our customers that's what they
01:15:05
would actually see
01:15:08
debug will have a lot of developer
01:15:11
if something were to break we are
01:15:14
you know fix it very quickly um but if
01:15:18
something to production the the feedback
01:15:21
making that fix propagating it through
01:15:23
the play store and ensuring that it's qa
01:15:26
it's just a longer feedback loop so we
01:15:27
really want to avoid
01:15:29
having release broken more more
01:15:31
sensitively than if we just break
01:15:33
ourselves and we sent a pr
01:15:35
um to fix it so again it's about our
01:15:38
philosophy on that um
01:15:39
maybe there's uh other philosophies
01:15:41
across the panel here
01:15:44
um the what we do at slack that i'm
01:15:48
pretty happy with is just
01:15:49
all of our libraries are set to be
01:15:52
single variant so the only thing that
01:15:54
different flavors is the actual app
01:15:56
module which again 90
01:15:58
of the code is there anyway so we're not
01:15:60
getting as much of a benefit as we'd
01:16:01
like but at least in terms of like
01:16:02
configuration setup
01:16:04
um yeah every library is just set to
01:16:07
we had a couple of libraries that were
01:16:09
relying on being able to have like debug
01:16:11
and release variants but
01:16:13
you can also just split those up into
01:16:16
uh three smaller artifacts with like an
01:16:18
api release version in a debug version
01:16:20
we do this for like flipper for instance
01:16:24
debugging tool where in the production
01:16:28
provide a no op version of it and in
01:16:31
we have the actual implementation of it
01:16:35
and those are easy to control with you
01:16:36
know debug implementation versus release
01:16:46
when looking at these flavors just
01:16:48
important to be mindful
01:16:49
of where you put them and how you're
01:16:53
uh there's a lot of apps where you know
01:16:56
the structure of your code
01:16:57
if you need the flavor just to change
01:16:60
you know the app icon for different
01:17:03
then it might make sense to just have a
01:17:06
a build flag that will change the icon
01:17:09
instead of recompiling your code twice
01:17:11
to to have a different flavor so it's
01:17:15
important to be mindful of the tools
01:17:16
you're using because if you add a build
01:17:20
all your code is twice all your
01:17:23
like everything is is multiplied so just
01:17:27
it yeah the tool you're using is
01:17:30
is what what you want to happen and of
01:17:33
course in really small projects it
01:17:34
doesn't matter that much to have
01:17:36
all these build flavors but as you start
01:17:39
you know to slack or square dropbox size
01:17:43
like then it starts to matter
01:17:47
i saw a question that uh i don't know
01:17:49
where it went but it was about kt lint
01:17:53
and i think a few of us were actually
01:17:56
touching on that one all right go ahead
01:17:59
yeah the uh so the question was
01:18:02
around like kt lint format from the
01:18:06
kt lint cradle plugin takes a long time
01:18:09
it has to run configuration for
01:18:12
and i was going to say that our solution
01:18:15
for that is that we just don't use it
01:18:18
and by rather we use it for checks on ci
01:18:21
but for actual formatting we just set up
01:18:23
a commit hook and check in the kt lint
01:18:25
uh jar directly and it just runs that
01:18:28
during the commit hook so you don't have
01:18:31
to pay the cost of doing
01:18:32
gradle configuration every time we
01:18:34
started with gradle configuration and
01:18:35
then people were like hey why are my
01:18:37
git commits taking two minutes i don't i
01:18:39
don't understand
01:18:40
and uh that's that's worked pretty well
01:18:44
sort of the same with detect not for
01:18:46
formatting but just
01:18:47
running a subset of detect checks on
01:18:50
every commit hook like the most common
01:18:52
uh quickest ones and so i i don't have
01:18:55
numbers to back this up but
01:18:57
before one of the ci checks that people
01:18:59
get hit by most often was like
01:19:00
you know kt lin format failed which text
01:19:03
now those are almost never
01:19:07
failing checks that people run into
01:19:08
anymore yeah i think
01:19:12
any static analysis tool that
01:19:15
you want to run you don't really want to
01:19:17
run it while compiling
01:19:18
so i move it at the last point in the
01:19:21
chain when do it when you really need it
01:19:23
so like you need it for the code review
01:19:25
you needed to mention it master
01:19:27
it so like as such said we move it to
01:19:31
uh git commit uh hook yeah the same
01:19:35
i think here uh just one second what
01:19:37
zach said basically we have a setup in
01:19:39
which we are not specifically using
01:19:41
but we're using google java formatter um
01:19:45
which i find it's like super great
01:19:46
because it gives you deterministic
01:19:49
always and it's great to have that kind
01:19:51
of formatting tool um and basically what
01:19:54
uh it's an upload book we're using a
01:19:58
it's an asp tool for managing multiple
01:19:60
git repositories
01:20:01
but basically whenever you want to push
01:20:03
something some cl
01:20:04
we run these these checks and just do
01:20:07
that one thing when it comes to
01:20:08
static code analysis i think like one
01:20:12
that is sometimes like missed in the
01:20:13
discussion is also just relying on the
01:20:16
and lint in the ide to to do the right
01:20:21
i think like it's super helpful that
01:20:22
like while you're working on the code
01:20:24
just you can fix it
01:20:25
straight away so it's not necessary that
01:20:27
you have to run this
01:20:29
you know from scratch kind of thing you
01:20:31
can just rely on the id
01:20:33
you know providing you with suggestions
01:20:36
uh write code yeah
01:20:39
we to on that note this is a bit of a
01:20:42
touchy topic but
01:20:43
like android lens for example hasn't
01:20:45
we've written custom
01:20:46
lint checks um and they
01:20:50
they constantly uh need maintaining when
01:20:52
a new version of the android gradle
01:20:54
plugin comes out and and sometimes like
01:20:56
breaks our ci like right now our lowest
01:20:59
our slowest running shards on ci
01:21:01
including the espresso test chart
01:21:04
is the are the lynch charts um and
01:21:07
we're actually considering disabling it
01:21:09
on ci which we don't want to do for
01:21:11
obvious reasons like then we're kind of
01:21:13
flying blind on some things but
01:21:15
um we would i know like we've there's
01:21:19
mention of this and some of the google
01:21:21
groups were would be really nice maybe
01:21:24
um roadmap there to hopefully make that
01:21:27
a little more extensible
01:21:36
oh sorry go ahead i was going to say lin
01:21:41
the more that you can reduce we'll say
01:21:44
developer cycles of like going to ci and
01:21:47
then lint failing and then them coming
01:21:48
back to fix it and then going back again
01:21:50
uh the better just because uh
01:21:53
yeah i started about design lint gets a
01:21:55
little bit slower every update
01:21:57
um with agb4 it got a lot slower we're
01:21:60
still trying to figure out why
01:22:01
so it's really powerful for yeah you're
01:22:04
never going to find the more
01:22:06
uh apps spot to inform people about
01:22:10
lint issues than in their ide and where
01:22:14
so leaning on that um
01:22:17
has been it's been nice for us at least
01:22:21
and talking about uh under limb on the
01:22:23
ide i encountered that that makes
01:22:25
uh especially coding files a little bit
01:22:33
because seeing i think
01:22:36
there is some issues i actually reported
01:22:37
but like uh that's why
01:22:39
i have to then disable on the id and i
01:22:44
i don't know i don't know all those are
01:22:46
lints or some of those might be intellij
01:22:48
inspections but uh whenever i'm waiting
01:22:50
for the i in the upper right of my id
01:22:52
it's a hover and i see slow inspections
01:22:55
counter um i just get a coffee
01:22:59
i have a i have those disabled too i
01:23:02
it's pretty much been for me now at this
01:23:04
point there's some known issues
01:23:07
in the koflin plugin itself
01:23:10
like the intellij plugin that
01:23:13
they're they exist on youtrack you can
01:23:14
follow along with them there
01:23:17
yeah i think my favorite one right now
01:23:18
is optimizing imports
01:23:21
will take like 15 seconds on like a
01:23:25
which uh it's sort of alarming but
01:23:27
anyways we should we should get back to
01:23:29
questions yeah there was there was a
01:23:32
follow-up there from somebody
01:23:33
i'm just going to read it here when
01:23:34
modularizing how strictly when deciding
01:23:36
and forcing whether or not
01:23:37
a module has an android plug-in enabled
01:23:40
library app or whether it should be
01:23:42
actually this is a direct follow-up but
01:23:45
it was just came in i thought it would
01:23:47
kind of keep that discussion going
01:23:55
i was going to say we don't have like a
01:23:57
set policy on it i would say that
01:23:59
the default right now for like
01:24:02
historical reasons
01:24:03
is to just make it an android project um
01:24:08
jrod mentioned this earlier they're like
01:24:10
if you can just make it a plain old java
01:24:12
or plain old kaufman project then
01:24:14
it is going to be faster by virtue of
01:24:16
having less overhead
01:24:18
so that's something that we want to try
01:24:21
to explore doing with
01:24:22
the help of the dependency analysis
01:24:24
plug-in in the future
01:24:26
basically detecting like could this
01:24:27
project be a plain
01:24:30
jvm project and if it's not using
01:24:34
from android but um a member of our team
01:24:38
benoit just wrote a blog post on this
01:24:40
um uh it describes our architecture and
01:24:43
it's opinionated everyone has their own
01:24:45
architecture but ours
01:24:47
tends to be where we have some concept
01:24:50
of a presenter controller
01:24:52
that is android uh unaware it is a
01:24:55
completely jvm and so the idea is that
01:24:57
that presenter contains
01:24:59
all of your business logic um and
01:25:02
rendering that to an ascii terminal an
01:25:06
platform because you're using kotlin
01:25:07
multi-platform or an android device
01:25:09
it is unaware and then that can be a jvm
01:25:13
um and then you would probably have an
01:25:15
analogous views module we we are single
01:25:17
activity that's another
01:25:19
opinionated uh architecture that we use
01:25:22
and because we're single activity
01:25:23
um all our activities are really in that
01:25:25
kind of app hairball module
01:25:27
and then we'll delegate all our features
01:25:30
specific views you know
01:25:31
the cache card views the boost views
01:25:34
those will all be in a
01:25:36
views android library module and so that
01:25:39
makes sense right you need context you
01:25:40
need resources you need
01:25:42
uh fonts etc so that would all live
01:25:45
so then the boundary conditions there
01:25:47
are going to be like how do you
01:25:49
uh something that is font-like or
01:25:51
image-like well so we create you use
01:25:53
concealed classes and like an icon
01:25:56
class and like if we have let's say the
01:25:59
icon has three different modes we'll
01:26:00
have three different values in that
01:26:02
sealed class and we propagate that
01:26:04
from the presenter to the view
01:26:06
internally to the view the view will
01:26:09
to say a picasso you know image renderer
01:26:13
you know what have you so that's keeping
01:26:15
the android boundaries only within the
01:26:16
view and then just creating some
01:26:19
lightweight mapping layer will allow you
01:26:22
more now of the android platform out of
01:26:25
your build modules
01:26:26
so that's how you achieve that goal or
01:26:28
one way to achieve it
01:26:31
excellent we spent a lot of time earlier
01:26:35
um in the discussion talking a little
01:26:38
bit about a lot about plugins in fact
01:26:39
features plugins and i think this is
01:26:41
something that maybe uh
01:26:43
ivan and nelson could maybe talk a
01:26:45
little bit about it's i know it's a
01:26:46
little bit departure from what we were
01:26:48
just talking about but um talking about
01:26:51
what are some of the kind of the issues
01:26:53
that your teams uh google and gradle are
01:26:56
uh with sort of community plug-ins and
01:26:60
um love to kind of get your your take
01:27:07
um it's a good one i mean i i'd say
01:27:11
that when talking about the plugins that
01:27:13
you apply to your build
01:27:14
i i i'd like to see more people thinking
01:27:17
about them in the same way that you're
01:27:19
thinking when you're adding a library
01:27:21
to your application right like you would
01:27:24
audit there figure out you know what's
01:27:26
the quality because it
01:27:28
does what it says it does and just apply
01:27:31
some level of scrutiny there like when
01:27:34
something to your build that may impact
01:27:35
the the build performance
01:27:37
ultimately so and i think that's that's
01:27:39
on the on the folks
01:27:41
you know that's i would say that's
01:27:42
responsibility of the folks who are
01:27:43
maintaining the building their companies
01:27:44
or like if there's not i guess all the
01:27:47
um so some of the issues that we're
01:27:50
seeing is i'd say like on the adp
01:27:54
side we were not as good when it comes
01:27:56
to talking about our apis and how people
01:27:58
should use those
01:27:59
apis and that has led to lots of
01:28:02
people sort of scrambling just to do
01:28:07
and that is something that we're trying
01:28:08
to address in 4.1
01:28:10
actually there's like a subset of the
01:28:11
new apis that we're working on and
01:28:13
for that too should have the finished
01:28:15
version of those apis allowing
01:28:17
plug-in authors to to customize their
01:28:20
android part of the build in in a
01:28:22
reliable way and in a way that does not
01:28:24
impact the build um i did that's like on
01:28:28
i also say that i think the
01:28:31
documentation on the gradle side
01:28:33
while it's pretty good for some things
01:28:34
i'd say like to when it comes to plug-in
01:28:37
i think it could be more opinionated and
01:28:39
more like tutorial based
01:28:40
and just like to tell people how exactly
01:28:44
and to be fair like things have been
01:28:45
changing quite a lot recently and i
01:28:47
think there's lots of improvements there
01:28:49
the one that comes to mind immediately
01:28:52
like we are running all of our builds
01:28:53
there's like a flag dash dash warning
01:28:55
mode and like we're running
01:28:57
all of our tests with dash dash warning
01:28:59
mode equals fail
01:29:00
what this means is basically gradle runs
01:29:02
some checks uh dynamically and then if
01:29:04
it detects that you're doing something
01:29:06
that you shouldn't you're just gonna
01:29:08
all right and that's how we we catch
01:29:10
lots of users on our end i mean we also
01:29:13
introduce bugs um so you know i think
01:29:18
that helps a lot and also i'd say for
01:29:20
the plug-in authors just like keeping up
01:29:22
to date with all of the new stuff it can
01:29:24
be a bit overwhelming
01:29:26
but i think for instance when it comes
01:29:28
to configuration caching the new stuff
01:29:30
that it should be like in syntax 6
01:29:33
i think that's really worth the
01:29:35
investment and i think
01:29:37
for the plug-in authors i i think it's
01:29:40
for the older users of their plugins
01:29:41
it's going to be a huge benefit
01:29:43
if all of the plugins are actually
01:29:45
compatible with configuration caching
01:29:47
because it's going to impact build
01:29:49
like positively quite a lot
01:29:53
you're saying we shouldn't use the
01:29:54
internal packages that we see
01:29:57
oh dot dot internal like yeah
01:30:02
yeah those are really good points i just
01:30:04
wanted to add a little bit to that
01:30:05
i think as a plug-in author it's
01:30:09
really difficult to keep up with all the
01:30:12
api changes that are happening like lazy
01:30:16
task configuration avoidance like
01:30:18
property providers
01:30:20
configuration caching like all these
01:30:24
and a lot of times plugins want to
01:30:26
maintain some backward compatibility
01:30:29
to be compatible with larger projects
01:30:32
so it it sometimes is a difficult choice
01:30:36
plug-in maintainers like do they want to
01:30:39
and support larger projects or
01:30:43
update to the new apis and use the
01:30:46
of those apis um one one of the
01:30:50
things my team actually does right now
01:30:53
when we see one of these issues with
01:30:55
some of our larger customers
01:30:57
we actually try and fix it in the open
01:31:00
so das for example on my team worked on
01:31:03
the spotless plugin
01:31:04
actually it's currently working on the
01:31:05
spotless plugin to make it incremental
01:31:08
um some of the like some of the the
01:31:12
you know if you're just working on a
01:31:13
plug-in you're probably using it on your
01:31:14
small project but
01:31:15
sometimes people take this small plug-in
01:31:17
and apply it to like
01:31:19
a massive project and then it has
01:31:21
scaling problems and that's
01:31:23
we just have to work and fix those
01:31:25
scaling problems
01:31:27
um yeah so task configuration avoidance
01:31:30
another one my team sees is uh
01:31:35
this is more for larger projects too but
01:31:37
remote cache misses so when
01:31:40
some task input to your task is not
01:31:43
compatible with your remote build cache
01:31:45
one example is using absolute paths as
01:31:50
and this is something that i think it's
01:31:52
really hard to test for and most
01:31:54
gradle plugin authors are completely
01:31:56
blind to because
01:31:58
while you're only testing it on your
01:31:59
local machine so that's
01:32:01
another one that my team helps out with
01:32:05
and we also have one for the android
01:32:07
gradle plugin another
01:32:09
one i just want to note is please file
01:32:13
for all these things whether it's a
01:32:15
plug-in you know you see performance
01:32:18
it doesn't matter if it's with gradle if
01:32:21
the plug-in with android gradle plug-in
01:32:23
like the feedback is
01:32:25
really valuable to use to improve like
01:32:28
are having that issue and things like
01:32:33
so one question that i often get from
01:32:35
people when i give similar feedback is
01:32:39
if i can't come up with a sample repro
01:32:41
or if i can't determine whether it's
01:32:44
kotlin or agp's fault how do i do that
01:32:48
maybe advice on that because it that
01:32:52
probably be part of the barrier to
01:32:54
getting those issues filed is now you
01:32:56
you know um you file on all the issue
01:32:59
trackers and the authors are like oh
01:33:00
this is an hour problem it's this
01:33:02
problem it can be a little hard to
01:33:04
be motivated to do that
01:33:08
yeah that's a really hard one that's
01:33:10
yeah yeah this is
01:33:11
the beginning where it's like all right
01:33:13
there's jetbrains there's google there's
01:33:16
um honestly it's it
01:33:19
i i don't think i have a good answer for
01:33:21
that i'm not going to try and bullshit
01:33:26
what we did recently was we found an
01:33:30
on a plug-in and we just got like two
01:33:34
build scans one with and one without the
01:33:38
we beat a little bit you know we read
01:33:41
the code and see oh i think this is the
01:33:43
problem and then we remove the line and
01:33:45
it was obvious that was the problem
01:33:46
but i guess at that point you are just
01:33:48
submitting the fix i know but uh
01:33:51
i i guess we want to know as
01:33:54
owners of an application if the plug-in
01:33:56
is the problem or not because
01:33:58
the reason that we have the plugin is
01:33:59
because it gives us some features right
01:34:01
so i think that's something we need we
01:34:04
have to deal but like uh
01:34:06
uh a b performance measurement should
01:34:10
you know enable and disable the plugins
01:34:12
should be obvious if it's like a big
01:34:14
issue right so yeah
01:34:22
uh just to add something here like i'd
01:34:25
definitely please do five bucks like i'd
01:34:28
say it's even better to file bug in the
01:34:30
for the wrong company at the wrong
01:34:32
component rather than just staying quiet
01:34:34
i mean what i try to do and what my team
01:34:37
tries to do is like
01:34:38
we see some report a bug report and then
01:34:41
then we will try to figure out whether
01:34:42
it's you know issuing in the
01:34:44
maybe ide whether it's in the calling
01:34:46
compiler whether it's cradle or some
01:34:48
third-party plug-in but at the same time
01:34:52
please try to you know add some data to
01:34:55
like just describing this doesn't work
01:34:59
full stop and creating a bug is
01:35:01
good but like you know we're
01:35:04
not that many action items on our end so
01:35:07
just try to add some data and then
01:35:10
someone will hopefully help you to in
01:35:13
you know divide you should track her if
01:35:15
you got if you got it wrong
01:35:17
yeah the the thing i was going to say uh
01:35:20
related to that is
01:35:21
basically it's better to file with like
01:35:25
than to not have it filed anywhere at
01:35:28
because once you have it filed somewhere
01:35:30
if someone else runs into the same issue
01:35:32
they can then chime in on it with