WEBVTT

00:00:00.000 --> 00:00:01.680
>> Tune into this week's
Xamarin Show where

00:00:01.680 --> 00:00:03.360
my good friend Alexi on talking

00:00:03.360 --> 00:00:06.810
about memory management for
your applications. So tune in.

00:00:06.810 --> 00:00:13.200
[MUSIC]

00:00:13.200 --> 00:00:14.280
>> Welcome back, everyone,

00:00:14.280 --> 00:00:15.405
to The Xamarin Show.

00:00:15.405 --> 00:00:16.650
I'm your host James Montemagno.

00:00:16.650 --> 00:00:17.820
Today, my best friend in

00:00:17.820 --> 00:00:21.270
the entire world Alexi with
me. How is it going, buddy?

00:00:21.270 --> 00:00:22.905
>> I'm good. How about you?

00:00:22.905 --> 00:00:24.960
>> I'm doing fantastic.
It's a beautiful day

00:00:24.960 --> 00:00:26.640
here in Redmond, Washington everyday.

00:00:26.640 --> 00:00:27.325
>> It is.

00:00:27.325 --> 00:00:29.085
>> Now, you're from our mobile

00:00:29.085 --> 00:00:31.065
customer advisory
team, is that correct?

00:00:31.065 --> 00:00:31.920
>> That is correct.

00:00:31.920 --> 00:00:33.450
>> So what does that mean?

00:00:33.450 --> 00:00:35.370
>> It means that we work with

00:00:35.370 --> 00:00:38.250
our clients and we
advise them obviously.

00:00:38.250 --> 00:00:41.645
But mostly, we work with developers
and see how they use tools,

00:00:41.645 --> 00:00:44.300
how they work with our Xamarin tool,

00:00:44.300 --> 00:00:47.560
and what are the common
pitfalls they face with.

00:00:47.560 --> 00:00:48.420
>> Perfect.

00:00:48.420 --> 00:00:50.205
>> Today, I want to talk about

00:00:50.205 --> 00:00:52.355
one of them is the memory management.

00:00:52.355 --> 00:00:53.780
>> Got you. Yeah. It's very important

00:00:53.780 --> 00:00:55.730
because we often talk
about all the cool,

00:00:55.730 --> 00:00:57.155
fancy features you can do,

00:00:57.155 --> 00:01:00.440
but we wanted to have this
best practices series

00:01:00.440 --> 00:01:02.340
because you run into trouble.

00:01:02.340 --> 00:01:03.820
It happens. It's so easy to do.

00:01:03.820 --> 00:01:06.345
Memory management,
honestly, I'm a noob.

00:01:06.345 --> 00:01:07.770
I really don't know. I'm just like,

00:01:07.770 --> 00:01:09.560
"They're going to kill
my app in five seconds.

00:01:09.560 --> 00:01:11.705
It doesn't matter, right?" But
I shouldn't think that way.

00:01:11.705 --> 00:01:14.210
>> That is true. That's what we see

00:01:14.210 --> 00:01:16.850
because nobody cares about
the memory management.

00:01:16.850 --> 00:01:21.300
We have so much memory
and you never check them.

00:01:21.300 --> 00:01:24.750
I mean, when was the last time you
checked your app memory usage?

00:01:24.750 --> 00:01:26.250
>> The last time I got a crash.

00:01:26.250 --> 00:01:29.510
Actually, I had a very
good example of this.

00:01:29.510 --> 00:01:31.910
I'll tell you this. This
is real-world example.

00:01:31.910 --> 00:01:35.120
I got a bug in Xamarin Essentials

00:01:35.120 --> 00:01:38.375
that says when I call
this method 20,000 times,

00:01:38.375 --> 00:01:41.570
my app crashes and it
was because I wasn't

00:01:41.570 --> 00:01:45.155
properly disposing of a
native Android object,

00:01:45.155 --> 00:01:46.775
a window, a display.

00:01:46.775 --> 00:01:48.170
So what's happening is,

00:01:48.170 --> 00:01:50.480
I would keep creating it
and it would never get

00:01:50.480 --> 00:01:53.135
garbage collected ever because
I was never disposing of it.

00:01:53.135 --> 00:01:54.890
>> That's what we're going
to talk about today.

00:01:54.890 --> 00:01:56.925
>> Yes. Awesome. Let's do
it. What do you have for us?

00:01:56.925 --> 00:02:00.435
>> So we have this small
simple app with two windows,

00:02:00.435 --> 00:02:02.745
main screen and detail screen.

00:02:02.745 --> 00:02:06.375
That's a very common pattern
UI navigation controller.

00:02:06.375 --> 00:02:09.600
This is a plain Xamarin
iOS application, right?

00:02:09.600 --> 00:02:10.305
>> Okay.

00:02:10.305 --> 00:02:12.440
>> What we're going
to do is introduce

00:02:12.440 --> 00:02:14.930
memory leaks in many,
many different ways.

00:02:14.930 --> 00:02:19.025
But first, I want to talk about
the differences from native world

00:02:19.025 --> 00:02:23.960
and managed world
performance and memory.

00:02:23.960 --> 00:02:25.340
So whenever you have a process,

00:02:25.340 --> 00:02:27.995
operating system giving
you a memory chunk.

00:02:27.995 --> 00:02:31.370
You should be aware about that
because once you run out of memory,

00:02:31.370 --> 00:02:33.670
your app crashes or
operating system kills it.

00:02:33.670 --> 00:02:35.355
In managed memory,

00:02:35.355 --> 00:02:40.260
our Xamarin Mono getting these
small piece of this memory.

00:02:40.260 --> 00:02:41.630
That's when we should be

00:02:41.630 --> 00:02:43.670
cautious about how we
use that piece as well.

00:02:43.670 --> 00:02:44.030
>> Okay.

00:02:44.030 --> 00:02:46.640
>> So you still should be
aware about native memory,

00:02:46.640 --> 00:02:48.905
and now once you work with Xamarin,

00:02:48.905 --> 00:02:50.320
also aware about management part.

00:02:50.320 --> 00:02:52.740
>> Got it. So you have
native memory, iOS,

00:02:52.740 --> 00:02:55.980
Android bits and pieces,
.NET managed memory?

00:02:55.980 --> 00:02:56.640
>> That's right.

00:02:56.640 --> 00:02:57.090
>> Perfect.

00:02:57.090 --> 00:03:00.530
>> Whenever you create an object
and you create, let's say,

00:03:00.530 --> 00:03:02.330
a UI button, you actually create

00:03:02.330 --> 00:03:04.950
a native UI button and
managed UI button class.

00:03:04.950 --> 00:03:06.680
They have different memory impact.

00:03:06.680 --> 00:03:10.310
They could cause different
memory issues because there is

00:03:10.310 --> 00:03:14.135
also a native way to collect
garbage and managed way.

00:03:14.135 --> 00:03:20.385
In Mono, we use Mono single
generation garbage collector.

00:03:20.385 --> 00:03:23.460
In the native world, iOS use ARC,

00:03:23.460 --> 00:03:26.680
Android use its own
garbage collector,

00:03:26.680 --> 00:03:29.420
but they should work together
side by side and we should

00:03:29.420 --> 00:03:32.300
have them because you can
introduce issues by using that.

00:03:32.300 --> 00:03:32.690
>> Got it.

00:03:32.690 --> 00:03:34.640
>> So the first and

00:03:34.640 --> 00:03:36.950
the most simple approach to introduce

00:03:36.950 --> 00:03:40.830
a memory issues is a subscription
without unsubscription.

00:03:42.040 --> 00:03:45.680
Garbage collector should know
when there is a garbage.

00:03:45.680 --> 00:03:47.180
But how could he know?

00:03:47.180 --> 00:03:49.565
It should be able to build

00:03:49.565 --> 00:03:53.915
a reachability tree graph
and it starts from routes.

00:03:53.915 --> 00:03:57.320
Our static events, static variables,

00:03:57.320 --> 00:03:59.350
static events or thread roll calls,

00:03:59.350 --> 00:04:01.910
they're all reachable routes and

00:04:01.910 --> 00:04:05.005
garbage collector treats
them as not garbage.

00:04:05.005 --> 00:04:06.810
So whenever you subscribe like this,

00:04:06.810 --> 00:04:09.560
let's take connectivity plugin.

00:04:09.560 --> 00:04:11.960
I know, James, you're
familiar with this plugin.

00:04:11.960 --> 00:04:13.400
>> I am. Yes. Very much so.

00:04:13.400 --> 00:04:14.960
I do like that. In
here, we're just what?

00:04:14.960 --> 00:04:16.220
Subscribing to an event,

00:04:16.220 --> 00:04:18.610
and it could be any
events like click event,

00:04:18.610 --> 00:04:20.360
you have a sensor change event.

00:04:20.360 --> 00:04:22.715
Basically, anything ever in .NET.

00:04:22.715 --> 00:04:25.970
>> Yes. It's specific
not only to Xamarin.

00:04:25.970 --> 00:04:27.830
It's any static event

00:04:27.830 --> 00:04:31.745
in .NET and connectivity
here is just an example.

00:04:31.745 --> 00:04:35.390
What I am trying to say, it
could be any static event or

00:04:35.390 --> 00:04:38.960
any singleton provided event.

00:04:38.960 --> 00:04:40.880
So whenever we subscribe like that,

00:04:40.880 --> 00:04:42.520
and let's say we have

00:04:42.520 --> 00:04:47.100
this small little piece of
ConnectivityChanged handler.

00:04:47.100 --> 00:04:49.655
We introduce a small memory leak.

00:04:49.655 --> 00:04:54.290
It is small because our view is
pretty simple and lightweight,

00:04:54.290 --> 00:04:55.400
but it's a memory leak.

00:04:55.400 --> 00:04:57.685
>> So it's a memory leak, why though?

00:04:57.685 --> 00:05:00.860
>> Because this connectivity and

00:05:00.860 --> 00:05:03.830
ConnectivityChanged event
is a static reference

00:05:03.830 --> 00:05:05.270
for our garbage collector.

00:05:05.270 --> 00:05:06.980
Once our garbage
collector is trying to

00:05:06.980 --> 00:05:08.810
identify if it's a garbage or not,

00:05:08.810 --> 00:05:11.015
it is not because

00:05:11.015 --> 00:05:14.540
ConnectivityChanged event has
a reference to this handler,

00:05:14.540 --> 00:05:17.375
and this handler actually handles

00:05:17.375 --> 00:05:21.080
the reference to our
DetailsViewController.

00:05:21.080 --> 00:05:24.680
>> I see. Got it. So we've
created this event inside of

00:05:24.680 --> 00:05:29.600
this ViewController and I've
subscribed but never unsubscribed.

00:05:29.600 --> 00:05:31.970
So it's always has this
reference immediately.

00:05:31.970 --> 00:05:34.940
So garbage collectors says,
"Hey, what's available?"

00:05:34.940 --> 00:05:37.030
It goes, "You can't have that."

00:05:37.030 --> 00:05:38.205
>> That is correct.

00:05:38.205 --> 00:05:40.580
>> I want to make sure that
that is correct because I

00:05:40.580 --> 00:05:42.185
believe that's how
it works in my mind.

00:05:42.185 --> 00:05:43.150
I want to make sure I'm right.

00:05:43.150 --> 00:05:47.225
>> The single task garbage collector
does is to deallocate memory,

00:05:47.225 --> 00:05:48.605
and to do that properly,

00:05:48.605 --> 00:05:50.540
garbage collector should know how to

00:05:50.540 --> 00:05:52.730
properly identify if
it's garbage or not.

00:05:52.730 --> 00:05:53.180
>> Got it.

00:05:53.180 --> 00:05:55.790
>> So to build a reachability tree,

00:05:55.790 --> 00:05:59.270
a garbage collector
uses static routes or

00:05:59.270 --> 00:06:01.430
just routes and static events

00:06:01.430 --> 00:06:03.500
or any static property
as one of the route.

00:06:03.500 --> 00:06:06.460
Also local variables,
a lot of other stuff.

00:06:06.460 --> 00:06:07.020
>> Got it.

00:06:07.020 --> 00:06:11.820
>> So let me just run it
and show how it works.

00:06:11.820 --> 00:06:14.745
Do you think we will
see any difference?

00:06:14.745 --> 00:06:17.540
>> I don't know. I mean,
hopefully not because

00:06:17.540 --> 00:06:20.090
it's so simple is what I'm thinking.

00:06:20.090 --> 00:06:22.160
Now, my fear though is that

00:06:22.160 --> 00:06:24.200
since we're registering over
and over and over again,

00:06:24.200 --> 00:06:26.750
if we do change events,

00:06:26.750 --> 00:06:28.850
we're probably getting
in a lot of events.

00:06:28.850 --> 00:06:30.635
>> Yeah. Let's verify it.

00:06:30.635 --> 00:06:33.560
So I've moved to Details page.

00:06:33.560 --> 00:06:36.185
I'm going to disconnect my Wi-Fi now.

00:06:36.185 --> 00:06:38.510
>> In here, we're using
the iOS Simulator.

00:06:38.510 --> 00:06:41.975
So it's actually using
the machine's Internet.

00:06:41.975 --> 00:06:46.460
>> Yes. We just got an event here
that are ConnectivityChanged.

00:06:46.460 --> 00:06:51.910
Let's go back a few times
and a few more times,

00:06:51.910 --> 00:06:54.630
and I'm back on the main page.

00:06:54.630 --> 00:06:58.215
I'm not delicate in
anything right now,

00:06:58.215 --> 00:07:01.280
and I assume that my details
page are no longer there, right?

00:07:01.280 --> 00:07:01.430
>> Yeah.

00:07:01.430 --> 00:07:02.810
>> My subscription handler

00:07:02.810 --> 00:07:04.805
shouldn't work because
I didn't do anything.

00:07:04.805 --> 00:07:07.015
Let's turn on the Wi-Fi.

00:07:07.015 --> 00:07:09.510
>> Okay. So we actually created

00:07:09.510 --> 00:07:11.910
this ConnectivityChanged
on the second page.

00:07:11.910 --> 00:07:12.420
>> Second page.

00:07:12.420 --> 00:07:13.665
>> Well, I'm on the first page.

00:07:13.665 --> 00:07:17.440
>> Yes. So we do not expect
our handler to work,

00:07:17.440 --> 00:07:18.645
but look what we got.

00:07:18.645 --> 00:07:21.090
We just got four handlers
running our code,

00:07:21.090 --> 00:07:23.600
and it could be any
code updating database,

00:07:23.600 --> 00:07:25.505
saving settings, whatever.

00:07:25.505 --> 00:07:28.070
The issue here not only
with memory management

00:07:28.070 --> 00:07:30.635
because it does take some memory.

00:07:30.635 --> 00:07:34.970
It also an issue because we have
some code to be executed as well.

00:07:34.970 --> 00:07:37.445
>> Then does that mean
that the Details page,

00:07:37.445 --> 00:07:39.350
now it can never be
garbage collected?

00:07:39.350 --> 00:07:42.455
So now I just have this
Details page always in memory.

00:07:42.455 --> 00:07:43.400
>> Unfortunately, yes.

00:07:43.400 --> 00:07:44.660
>> Oh my goodness, that's bad.

00:07:44.660 --> 00:07:47.385
>> That's bad. As a developer,

00:07:47.385 --> 00:07:49.560
we not always see that.

00:07:49.560 --> 00:07:54.280
As a user, I see my app crashes
like once a week, whatever.

00:07:54.280 --> 00:07:56.675
I'll just restart it
and continue to use it.

00:07:56.675 --> 00:07:58.220
That's why it's not reported,

00:07:58.220 --> 00:08:00.350
it's not taken very seriously,

00:08:00.350 --> 00:08:03.950
but it is an issue especially if you

00:08:03.950 --> 00:08:08.330
get a huge image there
which affects your memory.

00:08:08.330 --> 00:08:10.910
So I'm going to uncomment
this line of code,

00:08:10.910 --> 00:08:14.680
which actually adds some memory load

00:08:14.680 --> 00:08:19.740
here and it is loading an
image from the Internet.

00:08:19.740 --> 00:08:22.265
We're just taking a random image.

00:08:22.265 --> 00:08:24.815
Let me show that it's truly random.

00:08:24.815 --> 00:08:27.035
Let's see what we get here.

00:08:27.035 --> 00:08:29.510
I'm always worried about it.

00:08:29.510 --> 00:08:32.210
Okay. So we have this random image,

00:08:32.210 --> 00:08:34.370
and that's what we're
going to load in

00:08:34.370 --> 00:08:37.190
our app every time we
go into Details page.

00:08:37.190 --> 00:08:37.610
>> Okay.

00:08:37.610 --> 00:08:40.395
>> Let me show it over here.

00:08:40.395 --> 00:08:42.970
>> This is totally something
that what always happen, right?

00:08:42.970 --> 00:08:45.220
Because go to a Details page,

00:08:45.220 --> 00:08:46.740
probably load some information,

00:08:46.740 --> 00:08:48.080
might be pulling some
information from

00:08:48.080 --> 00:08:51.095
a database on that screen,
and that could be bad.

00:08:51.095 --> 00:08:53.930
>> Imagine yourself you're
using Instagram app.

00:08:53.930 --> 00:08:55.330
You have a Details page there.

00:08:55.330 --> 00:08:56.710
You tap and follow,

00:08:56.710 --> 00:08:58.435
go into details, gone back.

00:08:58.435 --> 00:09:00.720
Go check another folder,
go into details,

00:09:00.720 --> 00:09:03.920
gone back, and in a week your app
crashes and nobody knows why.

00:09:03.920 --> 00:09:06.680
That's when memory issues
could come into play.

00:09:06.680 --> 00:09:09.180
>> Got you.

00:09:09.180 --> 00:09:11.855
>> I won't show you that
memory leak is still there

00:09:11.855 --> 00:09:14.650
because I want to show
you the profiler,

00:09:14.650 --> 00:09:16.375
how you can identify these issues.

00:09:16.375 --> 00:09:17.800
To identify these issues,

00:09:17.800 --> 00:09:19.990
you have a few tools.

00:09:19.990 --> 00:09:23.350
First of all, it's native tools,
iOs provides instruments,

00:09:23.350 --> 00:09:25.520
and second one is managed tool,

00:09:25.520 --> 00:09:27.005
which is Xamarin Profiler.

00:09:27.005 --> 00:09:27.990
>> Got you.

00:09:27.990 --> 00:09:29.520
>> Why do you think we need both?

00:09:29.520 --> 00:09:32.985
>> Well, they do different things.

00:09:32.985 --> 00:09:36.090
>> Yeah. Actually,
because of this image.

00:09:36.090 --> 00:09:38.025
Remember. I was talking about that.

00:09:38.025 --> 00:09:41.565
They actually can know
about its own part.

00:09:41.565 --> 00:09:44.190
So Xamarin Profiler knows nothing

00:09:44.190 --> 00:09:47.100
about the memory native
objects created there,

00:09:47.100 --> 00:09:50.010
and native instruments doesn't
know about managed memory.

00:09:50.010 --> 00:09:52.685
It just say there's some
chunk of object created.

00:09:52.685 --> 00:09:54.710
When Mono creates an object,

00:09:54.710 --> 00:09:57.275
it still bind it somehow
to native objects.

00:09:57.275 --> 00:09:59.210
So those you will be able to see,

00:09:59.210 --> 00:10:00.500
but all the rest won't be.

00:10:00.500 --> 00:10:01.220
>> Okay. Cool.

00:10:01.220 --> 00:10:02.945
>> So let's see the Xamarin Profiler.

00:10:02.945 --> 00:10:06.550
It is easier to comprehend
at the beginning,

00:10:06.550 --> 00:10:10.955
and it also shows you nice
namespace and like naming.

00:10:10.955 --> 00:10:12.815
So you can identify your object.

00:10:12.815 --> 00:10:16.715
There is a small button "Run"
and "Start Profile" in here.

00:10:16.715 --> 00:10:20.050
You need an enterprise
license to do that.

00:10:20.050 --> 00:10:23.870
But it's very convenient and
I encourage you to do that.

00:10:23.870 --> 00:10:25.190
So once you do that,

00:10:25.190 --> 00:10:26.825
it actually builds the app with

00:10:26.825 --> 00:10:31.130
some additional metadata and
code embedded into your app.

00:10:31.130 --> 00:10:33.580
So we could see and
track the objects.

00:10:33.580 --> 00:10:36.140
>> Now one thing while this
is building and deploying is,

00:10:36.140 --> 00:10:38.030
we're running on a
simulator which means it

00:10:38.030 --> 00:10:40.520
has the full horsepower of this.

00:10:40.520 --> 00:10:45.320
Is it okay that I'm doing it
and profiling it on my device,

00:10:45.320 --> 00:10:49.150
or is it better to do it on a
physical iPhone, for instance?

00:10:49.150 --> 00:10:50.570
>> That's a good question because you

00:10:50.570 --> 00:10:52.340
can do different kinds of profiling.

00:10:52.340 --> 00:10:52.940
>> Interesting.

00:10:52.940 --> 00:10:54.230
>> If you're profiling CPU,

00:10:54.230 --> 00:10:56.480
it's not a good idea
to do it on simulator

00:10:56.480 --> 00:10:58.820
because you haven't the
full power of the device.

00:10:58.820 --> 00:11:01.340
But if you're doing a memory
profiler and allocation,

00:11:01.340 --> 00:11:04.355
you will get the same issues
on simulator and on device.

00:11:04.355 --> 00:11:04.730
>> Perfect.

00:11:04.730 --> 00:11:10.300
>> I like doing it on the laptop
because it just starts faster.

00:11:10.300 --> 00:11:13.010
It does not translate the code

00:11:13.010 --> 00:11:16.085
into native instructions and just
simulates and run instantly.

00:11:16.085 --> 00:11:18.470
So whenever you do memory profiling,

00:11:18.470 --> 00:11:20.180
if you run apps so many times,

00:11:20.180 --> 00:11:23.045
so you're going to like it.

00:11:23.045 --> 00:11:25.085
Let me do the same test.

00:11:25.085 --> 00:11:27.980
So I've opened the Details page once,

00:11:27.980 --> 00:11:29.840
and you see this small peak here.

00:11:29.840 --> 00:11:33.590
It means that we increased our
memory usage significantly.

00:11:33.590 --> 00:11:35.915
But you don't see this
memory increase here.

00:11:35.915 --> 00:11:38.510
It's still like the biggest object is

00:11:38.510 --> 00:11:40.730
systems tree and somewhere here.

00:11:40.730 --> 00:11:43.155
Let me do it a few more times.

00:11:43.155 --> 00:11:45.815
I'll increase it again.

00:11:45.815 --> 00:11:47.610
You will see the spike here,

00:11:47.610 --> 00:11:49.735
but you don't see any spikes here.

00:11:49.735 --> 00:11:53.330
Which means that when we allocate
in something in native memory,

00:11:53.330 --> 00:11:56.220
it does not reflect
it in managed world,

00:11:56.220 --> 00:11:59.419
but we see the total memory is
growing and not deallocating,

00:11:59.419 --> 00:12:00.720
which is the most important thing.

00:12:00.720 --> 00:12:01.455
>> I see.

00:12:01.455 --> 00:12:04.015
>> We come back with this snapshot.

00:12:04.015 --> 00:12:05.710
Memory snapshot actually runs

00:12:05.710 --> 00:12:07.875
the garbage collection
on managed site.

00:12:07.875 --> 00:12:10.195
So we do this snapshot.
I'll do another one.

00:12:10.195 --> 00:12:11.755
I'll explain it later,

00:12:11.755 --> 00:12:14.500
to deal with the finalization cue.

00:12:14.500 --> 00:12:17.475
But basically, now it's clean memory.

00:12:17.475 --> 00:12:19.605
We'll make sure that
our garbage collector

00:12:19.605 --> 00:12:22.270
already ran and deallocated
all the acquired object.

00:12:22.270 --> 00:12:23.920
We still see the memories there.

00:12:23.920 --> 00:12:25.845
So it still went down.

00:12:25.845 --> 00:12:28.755
To know what is going on here,

00:12:28.755 --> 00:12:32.005
we just go here and
use the filter button.

00:12:32.005 --> 00:12:35.265
We're trying to identify
only R objects,

00:12:35.265 --> 00:12:38.110
and I also want to see on
the live objects here.

00:12:38.110 --> 00:12:40.980
So I hit this "Apply"
button, and voila,

00:12:40.980 --> 00:12:43.575
we see two details controller
hanging in memory,

00:12:43.575 --> 00:12:47.160
even though I don't
have details in place.

00:12:47.160 --> 00:12:48.570
>> Super sample, so you said,

00:12:48.570 --> 00:12:50.289
find everything in my name-space,

00:12:50.289 --> 00:12:51.610
filter down on that.

00:12:51.610 --> 00:12:54.820
Literally what we see here
is Detail View Controller 2.

00:12:54.820 --> 00:12:55.225
>> Yeah.

00:12:55.225 --> 00:12:56.650
>> But it should be gone.

00:12:56.650 --> 00:13:00.015
>> I will start with the biggest
objects you have in these pages.

00:13:00.015 --> 00:13:00.280
>> Yeah.

00:13:00.280 --> 00:13:02.865
>> It is true for Android as well.

00:13:02.865 --> 00:13:04.030
You just search for activities,

00:13:04.030 --> 00:13:05.395
view models, or whatever,

00:13:05.395 --> 00:13:07.875
because once you have a view
model hanging in there,

00:13:07.875 --> 00:13:11.320
it starts to link all
the other objects.

00:13:11.320 --> 00:13:13.380
All the services, all the bindings,

00:13:13.380 --> 00:13:16.605
all the UIs, and you will
get a lot of memory.

00:13:16.605 --> 00:13:17.500
>> Got it.

00:13:17.500 --> 00:13:19.465
>> Let me show that it is true.

00:13:19.465 --> 00:13:23.260
I will open it one more
time, hit the "Snapshot".

00:13:23.260 --> 00:13:25.455
We see three instances here.

00:13:25.455 --> 00:13:28.569
I'm going back, hitting "Snapshot",

00:13:28.569 --> 00:13:30.030
and it stays in memory.

00:13:30.030 --> 00:13:30.660
>> Got you.

00:13:30.660 --> 00:13:32.500
>> So let's fix this memory issue.

00:13:32.500 --> 00:13:33.700
>> I'm ready.

00:13:33.700 --> 00:13:36.470
>> How would you fix that?

00:13:41.220 --> 00:13:43.525
This is a details page,

00:13:43.525 --> 00:13:45.460
so we need to unsubscribe
at some event.

00:13:45.460 --> 00:13:49.325
>> Got you. So the real issue here
is I've subscribed to an event.

00:13:49.325 --> 00:13:49.970
>> Yes.

00:13:49.970 --> 00:13:52.135
>> Then we should unsubscribe, right?

00:13:52.135 --> 00:13:54.550
>> That is correct. This
is a good practice.

00:13:54.550 --> 00:13:56.370
Whenever you see this plus equal,

00:13:56.370 --> 00:13:59.490
you just search if
there is a minus equal,

00:13:59.490 --> 00:14:01.980
if it's not, you
should introduce that.

00:14:01.980 --> 00:14:02.595
>> Got it.

00:14:02.595 --> 00:14:05.020
>> This is first indication
that you have a memory leak.

00:14:05.020 --> 00:14:05.340
>> Got it.

00:14:05.340 --> 00:14:10.460
>> The only exception is when
you subscribe on the main page,

00:14:10.460 --> 00:14:12.285
like our main page here,

00:14:12.285 --> 00:14:14.725
and you're sure that this page

00:14:14.725 --> 00:14:18.010
won't be able to go
away anytime soon.

00:14:18.010 --> 00:14:20.115
>> Maybe you have it at
your App Delegate levels.

00:14:20.115 --> 00:14:21.530
You're like, I actually
want this to be

00:14:21.530 --> 00:14:23.290
a global event for all times.

00:14:23.290 --> 00:14:25.845
But also maybe when your app
goes into the background,

00:14:25.845 --> 00:14:27.295
you should also unsubscribe.

00:14:27.295 --> 00:14:28.345
>> That's true.

00:14:28.345 --> 00:14:28.675
>> Yeah.

00:14:28.675 --> 00:14:29.700
>> Not to execute.

00:14:29.700 --> 00:14:31.750
>> So now you're saying
when it appears,

00:14:31.750 --> 00:14:33.855
it will subscribe, and disappear,

00:14:33.855 --> 00:14:35.935
unsubscribe, and then you
remove the one up top.

00:14:35.935 --> 00:14:37.990
>> Yes, I removed from the Cloud,

00:14:37.990 --> 00:14:39.710
because we want to
run it every time we

00:14:39.710 --> 00:14:42.040
appear and every time we disappear.

00:14:42.040 --> 00:14:43.850
Plus equal to subscribe,

00:14:43.850 --> 00:14:45.640
minus equal to unsubscribe.

00:14:45.640 --> 00:14:48.735
Nothing complicated, just want to

00:14:48.735 --> 00:14:52.045
make sure we don't need any
instruments once you go through it.

00:14:52.045 --> 00:14:52.720
>> Cool.

00:14:52.720 --> 00:14:55.110
>> So I'm doing the same stuff,

00:14:55.110 --> 00:14:59.490
going to details,
showing that it is true.

00:14:59.490 --> 00:15:02.980
Taking snapshot,
filter into my events.

00:15:02.980 --> 00:15:05.300
Sorry. It just clicked.

00:15:08.700 --> 00:15:12.170
Let's see on the live objects.

00:15:12.420 --> 00:15:15.345
We should see the details
because we're currently on

00:15:15.345 --> 00:15:17.475
details page. We're going back.

00:15:17.475 --> 00:15:18.990
We hit a "Snapshot"

00:15:18.990 --> 00:15:20.880
and what do we expect here?

00:15:20.880 --> 00:15:23.715
First, garbage collection actually

00:15:23.715 --> 00:15:26.065
put these objects into
finalization cue,

00:15:26.065 --> 00:15:27.625
but second should cue 1,

00:15:27.625 --> 00:15:30.340
or probably still the same one.

00:15:30.340 --> 00:15:31.570
>> Now it has gone.

00:15:31.570 --> 00:15:33.910
>> Yes. So let me talk about

00:15:33.910 --> 00:15:36.940
finalization cue in a
second, but for now,

00:15:36.940 --> 00:15:40.395
the idea is that we've
lost our details view,

00:15:40.395 --> 00:15:43.135
and our memory usage coming down.

00:15:43.135 --> 00:15:43.770
>> Beautiful.

00:15:43.770 --> 00:15:46.150
>> That's how we fix memory leaks.

00:15:46.150 --> 00:15:49.420
>> Yeah. You subscribed your
events. Unsubscribe from events.

00:15:49.420 --> 00:15:51.630
>> Basic rule of thumb.

00:15:51.630 --> 00:15:54.915
>> That's really funny too
because one, it cause two issues.

00:15:54.915 --> 00:15:56.800
We saw that you were keeping it alive

00:15:56.800 --> 00:15:58.750
because these events keep going.

00:15:58.750 --> 00:16:00.715
So now you're firing
them multiple times,

00:16:00.715 --> 00:16:04.290
but also, anything on that page
is going to be left in memory.

00:16:04.290 --> 00:16:06.685
>> That's right. That's why
we added a heavy image,

00:16:06.685 --> 00:16:08.205
and it's still in the memory.

00:16:08.205 --> 00:16:08.830
>> Got it.

00:16:08.830 --> 00:16:10.570
>> Let me show you Instruments.

00:16:10.570 --> 00:16:13.390
So I'm going to introduce
back our memory leak.

00:16:13.390 --> 00:16:13.800
>> Sure.

00:16:13.800 --> 00:16:15.985
>> Just removing unsubscribing event.

00:16:15.985 --> 00:16:18.435
I'm going to deploy to my simulator,

00:16:18.435 --> 00:16:21.330
and instruments works fairly easy.

00:16:21.330 --> 00:16:23.355
You just pick the target from

00:16:23.355 --> 00:16:25.930
the simulator and the
app, and that is it.

00:16:25.930 --> 00:16:28.435
That's all you need to start
the Instruments profiler.

00:16:28.435 --> 00:16:30.175
Even though it's Xamarin App,

00:16:30.175 --> 00:16:32.150
you can start it right
from the Instruments,

00:16:32.150 --> 00:16:33.615
which knows nothing about Xamarin.

00:16:33.615 --> 00:16:35.310
>> Where does Instruments come from?

00:16:35.310 --> 00:16:38.709
>> Apple. It's an Apple
tool, comes with Xcode,

00:16:38.709 --> 00:16:41.950
and it has a lot of
tooling inside of it.

00:16:41.950 --> 00:16:43.450
>> So it's just built in
because you already have

00:16:43.450 --> 00:16:45.415
Xcode installed? So
everybody has this?

00:16:45.415 --> 00:16:46.015
>> It's free.

00:16:46.015 --> 00:16:48.925
>> It's free. Cool. So anybody
can use this right now today?

00:16:48.925 --> 00:16:53.880
>> Yes. You can actually
see these activities,

00:16:53.880 --> 00:16:57.920
even though those created by managed
world like details activity,

00:16:57.920 --> 00:17:00.525
it is still represented
by a native object.

00:17:00.525 --> 00:17:00.930
>> Got it.

00:17:00.930 --> 00:17:02.855
>> So let's look for that object.

00:17:02.855 --> 00:17:07.240
We call it Details View Controller.

00:17:07.240 --> 00:17:09.595
Let me create a few of them.

00:17:09.595 --> 00:17:11.030
>> This is actually
really cool because

00:17:11.030 --> 00:17:12.240
I've never used Instruments,

00:17:12.240 --> 00:17:15.295
don't tell anybody, in years.

00:17:15.295 --> 00:17:18.440
I don't think everyone is giving
me a detail. So it exists?

00:17:18.440 --> 00:17:20.070
>> Yes, it exists.

00:17:20.070 --> 00:17:22.335
>> That makes sense
because Xamarin is native,

00:17:22.335 --> 00:17:23.770
so it creates a native object.

00:17:23.770 --> 00:17:26.380
>> Yes. You don't need to do

00:17:26.380 --> 00:17:27.885
a memory snapshot here

00:17:27.885 --> 00:17:29.975
because we don't have
garbage collection here.

00:17:29.975 --> 00:17:33.780
IOS uses hierarchy, which is
automatic reference counter.

00:17:33.780 --> 00:17:35.605
Basically, whenever
you create an object,

00:17:35.605 --> 00:17:37.065
it increments the counter,

00:17:37.065 --> 00:17:39.550
whenever you don't use or it

00:17:39.550 --> 00:17:42.505
goes away from the scope of
usage, it decrements the counter.

00:17:42.505 --> 00:17:43.845
Once the counter is zero,

00:17:43.845 --> 00:17:46.495
the object is garbage, and
it could be collected.

00:17:46.495 --> 00:17:48.075
So it's fairly easy to start

00:17:48.075 --> 00:17:51.735
the Instruments with the app
just by clicking this button.

00:17:51.735 --> 00:17:53.505
It starts the app,

00:17:53.505 --> 00:17:55.860
it shows you the memory usage here.

00:17:55.860 --> 00:17:57.690
Let's open the Details page.

00:17:57.690 --> 00:18:00.425
>> Got you. Instruments
comes from Apple?

00:18:00.425 --> 00:18:02.040
>> Instruments comes from Apple.

00:18:02.040 --> 00:18:03.350
It's a free tool from Apple.

00:18:03.350 --> 00:18:04.490
You can use this right now.

00:18:04.490 --> 00:18:05.390
>> Cool.

00:18:05.390 --> 00:18:06.970
>> You see we also have

00:18:06.970 --> 00:18:10.140
this memory footprint right
here once we open Details page.

00:18:10.140 --> 00:18:12.120
Let's open it one more time.

00:18:12.120 --> 00:18:15.140
>> So this is very similar
to the Xamarin profiler,

00:18:15.140 --> 00:18:16.870
but this is going to be showing us

00:18:16.870 --> 00:18:19.240
the native stack for all
intents and purposes.

00:18:19.240 --> 00:18:21.500
>> That's right. Unfortunately, it

00:18:21.500 --> 00:18:24.090
knows nothing about
Xamarin and managed world,

00:18:24.090 --> 00:18:27.025
so you won't be able to see
the managed object it created.

00:18:27.025 --> 00:18:28.990
So you see the spike,

00:18:28.990 --> 00:18:30.850
and you see it doesn't go away.

00:18:30.850 --> 00:18:33.350
So let me do it a third time,

00:18:33.350 --> 00:18:35.145
and just show the objects.

00:18:35.145 --> 00:18:38.455
So let's see. There is
a small filter button.

00:18:38.455 --> 00:18:43.170
We go to all allocations here,

00:18:43.170 --> 00:18:45.165
and hit the "Details".

00:18:45.165 --> 00:18:45.820
>> Okay.

00:18:45.820 --> 00:18:47.555
>> This is three pages right here,

00:18:47.555 --> 00:18:48.660
they're all in memory,

00:18:48.660 --> 00:18:50.650
and they allocate in memory.

00:18:50.650 --> 00:18:54.070
I won't be showing how we deallocate
it because it's the same fix,

00:18:54.070 --> 00:18:57.020
we just unsubscribe,
managed world unsubscribes

00:18:57.020 --> 00:19:00.120
from the object. Object
considered to be garbage.

00:19:00.120 --> 00:19:04.660
Then our garbage collector
collects that information,

00:19:04.660 --> 00:19:06.460
then native can collect
because nothing

00:19:06.460 --> 00:19:08.490
from manage world
already holding to that.

00:19:08.490 --> 00:19:10.780
>> Makes sense. So very
much the same fix,

00:19:10.780 --> 00:19:12.255
but another way to detect it.

00:19:12.255 --> 00:19:15.045
>> That's right. So this is

00:19:15.045 --> 00:19:19.345
about differences between
managed and native world.

00:19:19.345 --> 00:19:22.120
My next examples will
be mostly about managed

00:19:22.120 --> 00:19:25.320
world because you can
introduce issue in any,

00:19:25.320 --> 00:19:26.905
and it's not related to Xamarin.

00:19:26.905 --> 00:19:29.570
Like you said, it could be
subscribing to static event,

00:19:29.570 --> 00:19:32.745
it could introduce
issue even anywhere.

00:19:32.745 --> 00:19:35.410
So the next thing is

00:19:35.410 --> 00:19:38.210
about subscription, and
without unsubscriptions.

00:19:38.210 --> 00:19:39.315
But in this case,

00:19:39.315 --> 00:19:42.820
we are actually
subscribing implicitly,

00:19:42.820 --> 00:19:44.480
we don't use plus equals.

00:19:44.480 --> 00:19:46.015
So it's harder to find.

00:19:46.015 --> 00:19:48.710
In this case, we run this
notification center trying to

00:19:48.710 --> 00:19:51.795
identify whenever our app is rotated.

00:19:51.795 --> 00:19:53.695
We add in this observer.

00:19:53.695 --> 00:19:57.525
This is a singleton default center.

00:19:57.525 --> 00:19:59.700
We're saying that, I want to get

00:19:59.700 --> 00:20:02.595
any information whenever
orientation changed,

00:20:02.595 --> 00:20:04.140
and here's my handler for that.

00:20:04.140 --> 00:20:04.650
>> Got it.

00:20:04.650 --> 00:20:06.690
>> The handler itself,
it's fairly easy.

00:20:06.690 --> 00:20:08.125
We'll do nothing there,

00:20:08.125 --> 00:20:11.665
we'll just print it to debug.

00:20:11.665 --> 00:20:12.465
>> Got it.

00:20:12.465 --> 00:20:15.525
>> Let me remove the
connectivity stuff because

00:20:15.525 --> 00:20:18.630
we want to introduce different
kinds of memory issue.

00:20:18.630 --> 00:20:21.525
I also comment out our
image because we don't need

00:20:21.525 --> 00:20:24.430
to show the memory
footprint, it is there.

00:20:24.430 --> 00:20:28.390
We will experiment just with
UI view controllers and views.

00:20:28.390 --> 00:20:30.650
>> Very cool. So this
is very similar,

00:20:30.650 --> 00:20:32.870
but this pattern, you
could be subscribing,

00:20:32.870 --> 00:20:34.605
maybe even passing in an action.

00:20:34.605 --> 00:20:38.340
Or in this case, what it does
it says here's your callback.

00:20:38.340 --> 00:20:40.010
Delegates are very similar,

00:20:40.010 --> 00:20:41.115
I think to this patterns.

00:20:41.115 --> 00:20:42.480
So it's just something
I'm used to as well.

00:20:42.480 --> 00:20:45.590
>> That's right. That was

00:20:45.590 --> 00:20:47.864
their main idea because
when you're subscribing,

00:20:47.864 --> 00:20:51.405
you're passing the reference to
the UI View Controller as well.

00:20:51.405 --> 00:20:53.425
This is just a different
way to pass the reference.

00:20:53.425 --> 00:20:55.260
It's not that obvious sometimes.

00:20:55.260 --> 00:20:57.955
So we have our subscription,
it's running here.

00:20:57.955 --> 00:20:59.305
It's running just once.

00:20:59.305 --> 00:21:01.780
Let's close and open it again.

00:21:01.780 --> 00:21:03.525
Now, we have a double click.

00:21:03.525 --> 00:21:05.230
Let me clear to show you this.

00:21:05.230 --> 00:21:07.240
Rotating once, getting two,

00:21:07.240 --> 00:21:11.655
which means we have some UI View
Controller hanging in memory,

00:21:11.655 --> 00:21:13.535
while still processing the first one.

00:21:13.535 --> 00:21:13.980
>> Got it.

00:21:13.980 --> 00:21:15.430
>> It could be an issue if you have

00:21:15.430 --> 00:21:19.660
some database update logic
or HTTP request overtime.

00:21:19.660 --> 00:21:21.340
Like in a day of use,

00:21:21.340 --> 00:21:24.810
your app is not killed, you
deactivate, reactivate.

00:21:24.810 --> 00:21:26.740
It will have all this
View still in memory,

00:21:26.740 --> 00:21:28.265
and in a week, it could crash.

00:21:28.265 --> 00:21:28.785
>> Yeah.

00:21:28.785 --> 00:21:30.105
>> So how to fix that?

00:21:30.105 --> 00:21:31.550
It's very easy.

00:21:31.550 --> 00:21:34.145
>> I assume that you unsubscribe?

00:21:34.145 --> 00:21:35.835
>> That's right. That's harder to

00:21:35.835 --> 00:21:38.685
unsubscribe because you
don't have plus equal.

00:21:38.685 --> 00:21:42.010
Let me show also what you
actually send in here.

00:21:42.010 --> 00:21:43.365
So when you subscribe,

00:21:43.365 --> 00:21:46.395
you're passing up the method name.

00:21:46.395 --> 00:21:48.215
You're actually passing an action,

00:21:48.215 --> 00:21:51.745
and compiler is doing a
great job of hiding that,

00:21:51.745 --> 00:21:54.150
and making our lives easier.

00:21:54.150 --> 00:21:55.945
>> Compiler is very nice.

00:21:55.945 --> 00:21:57.255
>> Very nice to us.

00:21:57.255 --> 00:22:00.415
That's why we like to be developers.

00:22:00.415 --> 00:22:04.360
So it actually asks for
action with NSNotification.

00:22:04.360 --> 00:22:07.840
So I'm signing NSNotification here,

00:22:07.840 --> 00:22:13.365
and then using this notation,
pasting this object.

00:22:13.365 --> 00:22:16.560
So instead of the method name,

00:22:16.560 --> 00:22:19.225
we're actually passing
an action and object,

00:22:19.225 --> 00:22:20.960
which holds the reference to

00:22:20.960 --> 00:22:23.610
these metadata on how
to call the method.

00:22:23.610 --> 00:22:26.555
So we don't pass the method,
it's just a reference.

00:22:26.555 --> 00:22:30.060
In our case, the most important
part when passing this reference,

00:22:30.060 --> 00:22:32.155
which is UIV controller,

00:22:32.155 --> 00:22:34.170
and that's why it's held in memory.

00:22:34.170 --> 00:22:35.260
>> Got it.

00:22:35.260 --> 00:22:35.865
>> Okay.

00:22:35.865 --> 00:22:36.670
>> Makes sense. Yeah.

00:22:36.670 --> 00:22:38.595
>> I won't be showing the details

00:22:38.595 --> 00:22:40.390
because the memory
leak is still there

00:22:40.390 --> 00:22:43.975
because we saw these
thing to save some time.

00:22:43.975 --> 00:22:45.500
I want to focus on

00:22:45.500 --> 00:22:48.830
the worst-case scenario which
you should be aware of.

00:22:48.830 --> 00:22:54.250
When native world doesn't place
nicely with the managed world.

00:22:54.250 --> 00:22:56.280
>> Got you. When the
two worlds collide.

00:22:56.280 --> 00:23:00.265
>> That's correct because whenever
we have managed object created,

00:23:00.265 --> 00:23:02.155
and there is a native object created,

00:23:02.155 --> 00:23:05.690
and he/she trying to
deallocate native objects,

00:23:05.690 --> 00:23:07.495
our managed world thinks,

00:23:07.495 --> 00:23:09.330
I'm still not done with this object.

00:23:09.330 --> 00:23:11.270
Please hold on, don't

00:23:11.270 --> 00:23:13.765
collect the object because
I'm still working with that.

00:23:13.765 --> 00:23:14.525
>> Got you.

00:23:14.525 --> 00:23:15.805
>> It could be opposite,

00:23:15.805 --> 00:23:19.130
when a native world
could create an object,

00:23:19.130 --> 00:23:20.265
and now a managed world thinks,

00:23:20.265 --> 00:23:22.450
it's not done, still
there, so let's hold.

00:23:22.450 --> 00:23:25.015
Even if you don't have other
references to this object,

00:23:25.015 --> 00:23:29.015
it could hold it, it could
keep it not as a garbage.

00:23:29.015 --> 00:23:29.820
>> Got you.

00:23:29.820 --> 00:23:31.460
>> I could explain it with

00:23:31.460 --> 00:23:34.640
these small little image
of immortal objects.

00:23:34.640 --> 00:23:37.230
So don't create immortal
objects. Those are bad.

00:23:37.230 --> 00:23:38.435
>> It sounds cool.

00:23:38.435 --> 00:23:39.963
>> Yeah.

00:23:39.963 --> 00:23:43.355
It happens when you
have these two worlds.

00:23:43.355 --> 00:23:46.925
Native, you see on the right the
native View Controller and Views,

00:23:46.925 --> 00:23:49.640
and from the left you have

00:23:49.640 --> 00:23:52.580
managed world C Sharp who is
View Controllers and Views.

00:23:52.580 --> 00:23:55.640
Whenever you don't know what is
happening on the native world,

00:23:55.640 --> 00:23:58.070
you cannot collect
it from this world.

00:23:58.070 --> 00:24:00.905
I'll show you one example
how you can do that.

00:24:00.905 --> 00:24:03.275
So in my example,

00:24:03.275 --> 00:24:07.235
I want to add here a small
little button "Save",

00:24:07.235 --> 00:24:11.375
and just want to close the
View once user hits that.

00:24:11.375 --> 00:24:13.925
Let's assume that the
"Save" button will also do

00:24:13.925 --> 00:24:17.330
some saving logic database
or HTTP calls whatever,

00:24:17.330 --> 00:24:19.055
it just not going back

00:24:19.055 --> 00:24:22.145
and it actually executes
some additional action.

00:24:22.145 --> 00:24:22.775
>> Okay.

00:24:22.775 --> 00:24:24.980
>> As details of these button,

00:24:24.980 --> 00:24:26.300
we send in the handler.

00:24:26.300 --> 00:24:31.205
This handler is saying that
please close these controller.

00:24:31.205 --> 00:24:33.395
>> Looks perfectly legitimate to me.

00:24:33.395 --> 00:24:35.255
>> Yes. We'll introduce
a memory leak.

00:24:35.255 --> 00:24:36.230
>> Okay.

00:24:36.230 --> 00:24:42.515
>> You're bad. It will unfortunately
and it's a common pattern.

00:24:42.515 --> 00:24:45.005
We we don't have any
static event like here.

00:24:45.005 --> 00:24:47.195
We don't have any
single tone like here.

00:24:47.195 --> 00:24:49.025
We're just keeping this button here,

00:24:49.025 --> 00:24:51.650
this is just a local item.

00:24:51.650 --> 00:24:54.260
Okay James, now we
created a button and

00:24:54.260 --> 00:24:56.735
we want to add it to
our navigation view.

00:24:56.735 --> 00:25:00.440
So we said in it through the
navigation item also don't use

00:25:00.440 --> 00:25:05.225
any static references nothing
like that and just it.

00:25:05.225 --> 00:25:08.015
Now we have the sub button
and let's start the profiler.

00:25:08.015 --> 00:25:09.890
>> Yeah and again,
super similar pattern.

00:25:09.890 --> 00:25:11.285
I create a button,

00:25:11.285 --> 00:25:15.800
add a button, and then I pop the
View Controller seems normal.

00:25:15.800 --> 00:25:18.185
>> Have a delegate which doesn't use

00:25:18.185 --> 00:25:20.540
any external or static references

00:25:20.540 --> 00:25:23.225
and doesn't pass any reference
from our controller.

00:25:23.225 --> 00:25:23.750
>> Got you.

00:25:23.750 --> 00:25:27.090
>> Should work fine,
right? Let's see.

00:25:27.280 --> 00:25:32.780
So profiler will show the objects

00:25:32.780 --> 00:25:34.760
created at the very beginning and I'm

00:25:34.760 --> 00:25:37.790
going to start tracking
them at the very beginning.

00:25:37.790 --> 00:25:39.530
So I've hidden snapshots right

00:25:39.530 --> 00:25:42.455
now and filtering to my objects only.

00:25:42.455 --> 00:25:45.380
Again is very common
pattern to troubleshoot

00:25:45.380 --> 00:25:48.800
memory issues just to
see only my objects.

00:25:48.800 --> 00:25:52.235
Then I'm gone once there.
This is my button.

00:25:52.235 --> 00:25:55.565
You see, this is a new control
nicely our application.

00:25:55.565 --> 00:25:56.870
We have this in memory,

00:25:56.870 --> 00:25:58.745
which is true, we expect that.

00:25:58.745 --> 00:26:03.410
Going back, let's hit one
more time and one more time.

00:26:03.410 --> 00:26:04.430
>> One more time because I know.

00:26:04.430 --> 00:26:05.195
>> One more time.

00:26:05.195 --> 00:26:06.380
>> Okay, and still there.

00:26:06.380 --> 00:26:08.270
>> One more time, it is still there.

00:26:08.270 --> 00:26:11.030
So let's open it and lot more times.

00:26:11.030 --> 00:26:14.090
Let's also close it
different way going back,

00:26:14.090 --> 00:26:17.390
going to save, it actually
basically doing the same.

00:26:17.390 --> 00:26:20.090
Let's hit the "Memory
snapshot" one more

00:26:20.090 --> 00:26:22.610
time and oh wow we
have five instances of

00:26:22.610 --> 00:26:24.920
pages hanging there in
memory and if you have

00:26:24.920 --> 00:26:28.130
a huge image there it
will have a lot of memory

00:26:28.130 --> 00:26:28.550
>> Got it.

00:26:28.550 --> 00:26:32.615
>> So that's a very common pattern

00:26:32.615 --> 00:26:36.800
because it doesn't obvious that
you have a memory leak here.

00:26:36.800 --> 00:26:39.830
The issue here is
that UIBarButtonItem

00:26:39.830 --> 00:26:43.910
actually holds to
some native resource,

00:26:43.910 --> 00:26:45.485
it's bound to native resource.

00:26:45.485 --> 00:26:49.100
If we don't clearly say that
I no longer need this button,

00:26:49.100 --> 00:26:51.020
you will introduce
this immortal object.

00:26:51.020 --> 00:26:53.135
>> Got you. So how do
I solve this thing?

00:26:53.135 --> 00:26:56.240
>> To solve that, let's use

00:26:56.240 --> 00:26:59.900
our ViewDisappear event and
do something with our button.

00:26:59.900 --> 00:27:00.150
>> Okay.

00:27:00.150 --> 00:27:01.220
>> So we have two options,

00:27:01.220 --> 00:27:02.735
we could either use

00:27:02.735 --> 00:27:05.299
Clicked event and
subscribe and unsubscribe,

00:27:05.299 --> 00:27:07.160
but we will be back to

00:27:07.160 --> 00:27:10.400
our first item when we subscribe
without unsubscribing.

00:27:10.400 --> 00:27:12.560
Let's do something more interesting.

00:27:12.560 --> 00:27:14.030
We'll just dispose the button.

00:27:14.030 --> 00:27:15.680
>> I like that. I'm
done with it, right?

00:27:15.680 --> 00:27:18.320
>> Yes, we kind of saying
managed world that,

00:27:18.320 --> 00:27:20.495
"I'm done with the button
please dispose it."

00:27:20.495 --> 00:27:24.365
It's not obvious because
lots of views and wrappers

00:27:24.365 --> 00:27:26.540
in Xamarin iOS have
this dispose method and

00:27:26.540 --> 00:27:29.015
you don't really know whenever
you should call that.

00:27:29.015 --> 00:27:30.815
So it's interesting case.

00:27:30.815 --> 00:27:32.975
But let's do that and let's run.

00:27:32.975 --> 00:27:34.700
That's the only action I've added

00:27:34.700 --> 00:27:37.500
since the previous application run.

00:27:38.290 --> 00:27:42.530
I'm starting the profiler
and doing the same use case.

00:27:42.530 --> 00:27:44.000
We're going to track the objects from

00:27:44.000 --> 00:27:46.310
the very beginning and make
sure they are disposed.

00:27:46.310 --> 00:27:48.050
>> Very cool. This is nice.

00:27:48.050 --> 00:27:49.670
So you could have, like you said,

00:27:49.670 --> 00:27:53.270
instead of passing
that entire action in,

00:27:53.270 --> 00:27:55.130
you can just similar to how we

00:27:55.130 --> 00:27:57.605
do Connectivity,
subscribe, unsubscribe,

00:27:57.605 --> 00:28:00.590
I would have figured it
out, but in this case,

00:28:00.590 --> 00:28:03.125
you're already did it so
you just dispose of it.

00:28:03.125 --> 00:28:04.010
>> That's right.

00:28:04.010 --> 00:28:04.875
>> Cool.

00:28:04.875 --> 00:28:08.455
>> Yeah, because we don't
expect it to be unsubscribed.

00:28:08.455 --> 00:28:10.840
It's not kind of a subscription,

00:28:10.840 --> 00:28:14.230
we just pass and delegate
inside of local object.

00:28:14.230 --> 00:28:16.045
In case of NotificationCenter,

00:28:16.045 --> 00:28:18.790
it's kind of subscription because
we pass in the local object

00:28:18.790 --> 00:28:21.760
into some static
instance or singleton.

00:28:21.760 --> 00:28:24.760
In this case, we just used
in our local resources,

00:28:24.760 --> 00:28:26.395
we do not expect a memory leak.

00:28:26.395 --> 00:28:26.680
>> Got you.

00:28:26.680 --> 00:28:28.630
>> But unfortunately I can see

00:28:28.630 --> 00:28:32.660
this barrier a lot and people
getting into these situations.

00:28:32.680 --> 00:28:37.530
So let's do the same trick.

00:28:37.750 --> 00:28:41.760
I wish it could save this data.

00:28:41.950 --> 00:28:46.310
So we have just one View
Controller and delegate.

00:28:46.310 --> 00:28:48.290
Let's hit "Save".

00:28:48.290 --> 00:28:51.215
Let's go back.

00:28:51.215 --> 00:28:54.005
Let's actually stay at details page.

00:28:54.005 --> 00:28:56.975
Hit "Memory snapshot" and we see one.

00:28:56.975 --> 00:28:59.315
Let me click it a few more times.

00:28:59.315 --> 00:29:02.735
We'll talk about that. So we
have just one instance here.

00:29:02.735 --> 00:29:10.805
I click "Save", click "Snapshot"
and it disappears scan.

00:29:10.805 --> 00:29:12.380
Okay? Memory leak fixed.

00:29:12.380 --> 00:29:13.250
>> Very Cool. Nice.

00:29:13.250 --> 00:29:14.900
>> Immortal object was killed.

00:29:14.900 --> 00:29:16.445
>> Killed. Very cool.

00:29:16.445 --> 00:29:17.810
Otherwise, this is awesome.

00:29:17.810 --> 00:29:20.600
So very simple, look at your events,

00:29:20.600 --> 00:29:22.850
but also look at how you're passing

00:29:22.850 --> 00:29:24.890
these actions around and even I

00:29:24.890 --> 00:29:26.870
wouldn't even think about that
button to be honest with you

00:29:26.870 --> 00:29:29.315
because the constructor
is passing this thing.

00:29:29.315 --> 00:29:29.600
>> Yes.

00:29:29.600 --> 00:29:30.725
>> So very cool.

00:29:30.725 --> 00:29:33.350
>> I would also recommend to

00:29:33.350 --> 00:29:36.425
our developers to use it more
often to like once a week,

00:29:36.425 --> 00:29:39.545
every sprint and then to
see the memory usage,

00:29:39.545 --> 00:29:41.585
you can see it as a UI test run.

00:29:41.585 --> 00:29:45.590
It shows this little
memory working set.

00:29:45.590 --> 00:29:48.050
So you just see over
months if it's grows or

00:29:48.050 --> 00:29:51.530
not and if it grows you
probably have a memory leak.

00:29:51.530 --> 00:29:53.360
>> You showed iOS.

00:29:53.360 --> 00:29:54.560
Now what about for Android?

00:29:54.560 --> 00:29:57.500
Is there any specific other
tools there that you can use?

00:29:57.500 --> 00:29:59.465
>> It's a great question
because, Android,

00:29:59.465 --> 00:30:02.000
everything we talked about
iOS applies for Android.

00:30:02.000 --> 00:30:02.150
>> Got you.

00:30:02.150 --> 00:30:03.440
>> Just have different tool for

00:30:03.440 --> 00:30:07.145
Android native profiler
called Android Profiler.

00:30:07.145 --> 00:30:08.390
It is really cool.

00:30:08.390 --> 00:30:09.740
It shows you a lot of

00:30:09.740 --> 00:30:12.380
information but you have still
to have to use it who is

00:30:12.380 --> 00:30:14.330
the Xamarin profiler in conjunction

00:30:14.330 --> 00:30:16.790
because of managed
world and native world.

00:30:16.790 --> 00:30:17.930
>> Got you. It simply it

00:30:17.930 --> 00:30:19.340
sounds it was cool that
there's great tools

00:30:19.340 --> 00:30:22.400
available no matter where
you're at, iOS, Android.

00:30:22.400 --> 00:30:23.240
>> That's correct.

00:30:23.240 --> 00:30:24.005
>> I can go ahead and do that.

00:30:24.005 --> 00:30:25.820
Honestly, just looking
at some of these,

00:30:25.820 --> 00:30:28.160
I'm pretty sure my code,
there's a lot of bad stuff.

00:30:28.160 --> 00:30:29.480
So when I stream next,

00:30:29.480 --> 00:30:31.790
it's going to be all
fixing my memory leaks.

00:30:31.790 --> 00:30:32.180
>> Okay.

00:30:32.180 --> 00:30:34.280
>> Very cool. Anything else Alexi
that you want to talk about?

00:30:34.280 --> 00:30:35.315
>> That all for today.

00:30:35.315 --> 00:30:37.865
>> Awesome. Well, thanks
everyone for tuning in.

00:30:37.865 --> 00:30:40.010
Alexi, thank you so much for
showing up all this stuff.

00:30:40.010 --> 00:30:42.305
>> Thank you guys. Thank
you James for letting me.

00:30:42.305 --> 00:30:43.970
>> Absolutely, and make sure

00:30:43.970 --> 00:30:45.920
that you check out all
the show notes below,

00:30:45.920 --> 00:30:47.420
open all the source
code, all the links

00:30:47.420 --> 00:30:48.980
for all the documentation down there.

00:30:48.980 --> 00:30:51.740
You can also go to aka.ms/Xamarin

00:30:51.740 --> 00:30:54.485
best practices for the entire series.

00:30:54.485 --> 00:30:55.790
So make sure you subscribe

00:30:55.790 --> 00:30:57.695
today wherever you're
watching right now.

00:30:57.695 --> 00:30:59.090
I'm James Montemagno.

00:30:59.090 --> 00:31:01.790
This has been The Xamarin
Show and thanks for watching.

00:31:01.790 --> 00:31:02.480
>> Thank you guys.

00:31:02.480 --> 00:31:09.230
[MUSIC]

00:31:09.230 --> 00:31:11.120
>> Hey, James here.
Just wanted to check in

00:31:11.120 --> 00:31:13.175
and thank you for
watching this video.

00:31:13.175 --> 00:31:16.265
Now do all the things that you
know you want to do such as like,

00:31:16.265 --> 00:31:18.710
subscribe, and ding
that notification bell,

00:31:18.710 --> 00:31:20.825
become part of the
notification squad.

00:31:20.825 --> 00:31:22.190
While you're here, check out

00:31:22.190 --> 00:31:25.400
all these awesome videos
that I've already coded.

00:31:25.400 --> 00:31:29.040
Click on that thing. Click
it, watch it, do it.

