mergeconflict293 === [00:00:00] James: Frank while we're on the topic of in-app subscriptions. From last week, I have an update update. Frank [00:00:14] Frank: feedback, feedback, feedback from you. Can't wait, follow up feedback. Uh, You are rich now and you're retiring from the podcast. Don't tell me the bad news, James. [00:00:26] James: No, I haven't rolled it out yet, but I have, I have officially 100%. Got it all implemented testing. The conundrum that I ran into is that I don't have an Android device that runs the latest version of Android. And I really want to test my app on Android because I've retarded. Recompiled and permissions and odd things may have changed. So I'm waiting to release iOS and Android, even though Android or iOS is updated and ready to go. It's approved and ready to release. Oh, Android. I'm waiting to test it on this, um, use cracked screen device that I got on eBay for a hundred dollars because [00:01:06] Frank: otherwise, um, okay. Uh, yeah, that's interesting. So it's just the latest one. You do have some Androids, you are testing on some Androids already. I assume. [00:01:15] James: Correct. I have an Android. Do you have an Android? Eight and Android 10. Uh, Heather has an Android and 11, I think. And then I'll have an Android 12. So we'll have between the family of all the Android test devices, we'll have all the different varieties that are be [00:01:32] Frank: out there. Um, that's something you can't really test in the emulator cause it's an app purchase and all that. Right. [00:01:38] James: And the Bluetooth, that's the big change. Okay. So there's that. Now I won't say this. There's a few gotchas that I've learned since class a podcast. If, of course, of course. I don't think I mentioned the last podcast that, um, you, you have to did I mention last podcast, how you have to complete. Check the subscriptions like transaction logs, different from iOS and Android because iOS returns all of them, but Android only returns one active one and you have to programmatically calculate. Forward in time when the subscription cancels. Cause they won't tell you. No, [00:02:17] Frank: I don't think you explained it was quite that bad. Well, how, how I understood it was you wrote a somewhat complicated algorithm for the apple side, because he had to figure out which are the ones in the receipt you could ignore and which ones were actually active. And I was under the assumption that that logic would pour it over to the Android. [00:02:34] James: I, I think that I hadn't tested it on Android and then I did test it on Android, Frank. And let me tell you how. It doesn't work that way at all. Uh, so what happens with James? [00:02:44] Frank: Please tell me how does it work? [00:02:47] James: So how it works on Android Frank is that you query the purchases and it will only give you back active purchases, which sounds pretty okay. Right. Because if you have it exactly. [00:03:01] Frank: Okay. Purchases count for subscriptions in this case. Okay. Correct. [00:03:05] James: Here's the conundrum Frank is that they do not append or change any data when a renewal occurs. [00:03:16] Frank: Oh, so there's only what, like, is there any date attached to it? Like the original purchase date? Is that it? That [00:03:23] James: is correct. It is the original purchase date, which, which, which, so here's what I ended up having to do. Okay. But the [00:03:31] Frank: logic is. Is there an active receipt or not your, your Boolean logic is just doesn't exist or not. Right then? Yes, that is okay. Okay. I solved that. I was getting nervous here. I was like, is he accumulating time? What's he going to do? Oh, [00:03:45] James: I do that. But then Frank, it actually gets better because I need to calculate the new expiration date. [00:03:51] Frank: Do you go? [00:03:52] James: Uh, yeah, because I don't want to check it every single time they opened the application. [00:03:57] Frank: Um, cause it's a network thing. Yeah, [00:04:00] James: it's actually a cash thing, but it would just be annoying to do that every time they open the app, [00:04:04] Frank: but okay. But don't you just do your forgiveness thing? Why don't you just check every five days or something like that? [00:04:09] James: I, yeah, I do, but here's what I do, Frank, is what I do. I could do that as a backup, but what I do is I say, well, it's very simple. I know when you originally purchased it. So it's going to expire if I keep adding one month. Right. And then once I add one month, if that's in the future, then add five more days and that's the actual. [00:04:29] Frank: Okay. That works. That works. Oh, we'll do it in a while loop. You could probably just do a modular. It'd be off by a couple of days, but who cares about calendars? [00:04:40] James: I'm going to send you the I'm gonna send you the logic. It's very simple. I got you. That's that's it. [00:04:49] Frank: It's a very simple loop. Everyone. It's wild. The date is less than now. Add some time. It's fine. It'll it'll probably work. I can give you a few edge cases where that won't work, but fine. Just do a modulus, but okay. Fine. Yeah. Um, excellent. Excellent. That works. Um, interesting. Okay. So do you only check until that date expires, then you don't check again? Correct. Oh, okay. So you're not checking Willy nilly. You just do it when you think it might be [00:05:20] James: expired. Okay. Correct. Yeah. And as long as it's there, it's totally there until they get to go. And I just forgot the new sub date. Uh, here's, here's the other thing I want to tell you. I want to resell you even further on subs because once you figure out the crazy logic and you have it in your app, there are these really amazing things, Frank, that are going to blow your mind because they're called introductory offers. Do you know about these? [00:05:42] Frank: Uh, you were mentioning them. We knew about there was a free for a short time. Is that the introductory offer or we talk an app or we talk in Google. Uh, at [00:05:52] James: least apple, probably on Google too, but it doesn't matter because here's the thing, because you know how if someone buys your app and then they don't like it, then they leave a bad review and then they request money back. Like in your instance, like you want to like upgrade to pro and get a bunch of stuff with introductory offers. You can do so many cool things. One, you can just give a full month for free three days for free. You can give whatever time for free. It doesn't matter. Or Frank, you can say, Hey. I'm going to give you 50% off for the first three months, or I'm going to say, instead of buying one month by 12 months at a reduced fee, so you can have all of these cool tiers and options to upsell to get people in. Or you can just, again, give them a free trial. Like you might just want to be like free trial. And I was looking at this and it's so cool. It just is automatically in the system. And apple takes cares. Uh, it takes care automatically of the. Of knowing, let's say you give them a three-day trial of basically giving you a new receipt in three days when they actually purchased it and calculating and things like that. So it's really cool that the, what I'm saying, there's a whole bunch of really cool things. If you're worried about, oh, well, people will upgrade to pro, but then to be disappointed who give them a free trial and they'll be much happier, which is pretty cool. And you can do like, the easiest thing would be, if you have a one month subscription, give them a one month free trial. You know, then you have to worry about extra math in your application because it would still expire in a month and you'd be. So, boom, there you go. [00:07:25] Frank: Love it. Um, real quick questions follow up. Uh, these are not promo codes. These are something you add to the UI within your app and something you just tag on to the purchase. I'm assuming is that [00:07:38] James: how it's literally even better than that, Frank? Uh, so you go into your subscription and you say, please add an introductory offer to this in-app subscription. Um, and what happens when the user goes to buy. They will be automatically gifted the introductory offer. But additionally, when you query your products from the app store, if there is an introductory offer, it will give you information about the introductory offer. So there's like a that says it's a free trial reduced rate or bundle, and then it gives you information for how long, pretty much inside of it. So you can then display that in the UI. Um, however you want. So you might say pro is 9 99. Or, you know, ant or sign up now and get three days for free. Right. And then, boom, you're good to go. [00:08:25] Frank: Great. Okay. When I query my products, it comes as extra information. So I just have to display that information. And then when they purchase, it's already automatic. If it's art, if it is. [00:08:36] James: Exactly. You got it. Yeah. Easy peasy. And then additionally, if you, um, you can also promote in that purchases in the store, by the way. So you can, you can use, add some additional metadata. You have to do some other handling and the stop of your app, but if you promote your subscription, it shows up in the app. So if they were typing an ICER, could the OCI I circuit, and then I circuit pro subscription or whatever. I'm just pretending that that exists as there's a free trial. It'll also say free, free trial. Just to get it right now and then it'll tell you work too. So anyway, we just wanna let you know [00:09:06] Frank: lots of cool stuff. Absolutely fantastic. I think, I think I'm going to experiment. I'm either going to experiment first with continuous or I started at 3d and I haven't decided which one, but new version of continuous, I think I'll find out, but probably be a little bit of time, but thank you for the follow-up. I plan on getting to it eventually. [00:09:26] James: Yeah. I feel like continuous is a great model because you could put in different pro features. Right. And then, but everyone that already exists today, they could, you know, basically have the pro version somehow. And then, you know, that's a loop, use [00:09:41] Frank: a loop somehow. Now I think I'm going to do a little bit of a software. And just do it a whole different SKU. Um, I've been wanting to do it for awhile anyway. Um, I was going to do that just as, you know, visual studio, 2001 visual studio, 2013, you know, purchase it again. But for the next skew, I'm gonna start with, um, an app purchase [00:10:03] James: for sure. Ah, that makes a lot of sense because then if you do subscription. Uh, there and you have a free unlock. It could be like the same price as if the other ski or whatever. Yeah. Because I [00:10:14] Frank: want to have a free version of it too. That's just like basic, maybe literally basic. [00:10:20] James: And I imagine like me giving you two bucks a month or whatever that seems to be doable. Yeah, take my money. Frank, take me [00:10:26] Frank: on the lookout. Frank's trying to monitor, [00:10:30] James: Hey, you gotta do it. You gotta do it. Seattle prices. Uh, all right, Frank, that was my topic, which was 10 minutes of our introductory cause I just, I wrote an entire blog post. I'll put it in the show notes as well. I went, I spent a lot of time diving in on this and spent a lot of time this weekend. So I was excited. Follow up in, no, we spent an hour on it last week, which is totally worth everybody's time to go listen to that podcast. Um, but if you haven't definitely go listen to it now, now you'll understand I'm talking about, but Frank, what have you been up to? Because I've just been testing in app subscriptions and that is not fun, but I'm assuming you're having more fun than me maybe. [00:11:04] Frank: Oh, I am having way more fun than you. I want to talk about something I love talking about, which is performance optimizing. Okay, it's great. It really is great. Uh, so James, uh, we, we can, I'm curious what your experiences here, but I'll say off the top of my head, I don't actually performance optimize my code that often I always had to do. Once for I circuit because it's a simulation engine, I had to make sure it runs efficiently. So I do performance checks with that kind of thing. Um, but most of my other apps, I don't really feel a need for it. But what I really want to talk about is there is a new way, at least new to me. And therefore I want to make sure everyone knows about it to do performance traces of apps in.net and.net six and everything moving forward. And I'm very excited by it because I love performance. Okay. [00:11:59] James: Uh, I'm a big fan of performance, but I never know how to properly trace performance or measure performance. So, Frank, I feel like I'm going to learn a lot [00:12:06] Frank: today. Oh yes. You are in the right place. You are in the right place. Uh, so let me go back with the great old saying, if you want to make your code fast, don't guess where the code is slow. And it was funny. I was just working on a recent little bit of a side project, not one of my real project. I mean, not, not something that pays the bills, but it was a Ray tracer and what's more fun than to try to make a Ray tracer fast. Right. It's a classic kind of optimization thing, but I was a little frustrated because I didn't have good tools for it. And. Writing optimized code, but I really, I was having a hard time measuring, like, was my code having an impact or not? I had no idea what was slow. I would change a bunch of things and the speed wouldn't change. And then I was like, I forgot the first rule of performance stuff, which is measure, measure, measure, measure. Don't even try to solve performance problems until you've measured first. So what tools have you used in the past? Anything [00:13:09] James: measure performance? [00:13:12] Frank: Exactly. No. Okay. Silence, crickets, insert cricket sound there. Let me tell you, James there, I'm going to change your mind on this because it is stupid easy now with a really good UI. So let me tell you. Let me tell you, and I'm sorry. I think this has been out since dotnet three.net core three, and I'm a little bit late to the game, but there is a tool called dotnet hyphen trace.net dash trace. It exists. Uh, you can.net global tool installed it's from the dotnet team or Microsoft or something. And what it does is it runs your app and collects profiling information from your. Profiling information. The stuff that I'm interested in that I'm talking about right now is CPU stuff. So you know what functions are running at the whole time and it's a sampling profiler. So the goal with a sample profile is it shouldn't affect the performance of your app, or if it does affect a performance Europe, it should be very minor. The downside of it is that it has to collect tons and tons and tons and tons of data. And what do you do with that? All right. I mean, [00:14:31] James: Data. Yeah. Whenever I get logs, whenever I get things, even when I'm debugging and you're getting all this performance analysis, I'll put like from visual studio, like if you're, you know, getting all the stuff, like, I don't know what to do with this. I have like profile my apps and I've like looked at different things. I'm like, I don't know what I'm looking at here. There's just too much. There's like literally too much data. Like sometimes you complain, there's not enough. Too much. I don't know what to do with it. And I just want to close it and get rid of it forever. [00:14:58] Frank: Yeah. And that's basically where I always was with this dotnet trace because when you, sorry, so everyone, uh, dot net, hyphen trace space, collect space, your app, give it something to run and it'll collect this giant log file called uh, I forget what they call it. A net trace or something. I'm like, why is it called a net trace? I'm trying to do a CPU trace, you know, I'm totally confused. But I read the docs. I read the docs for [00:15:23] James: you don't have to change. I was good. Okay. [00:15:24] Frank: Good. What I found was, um, I guess if you're a windows user, you're all set. There is an app out there called perfect. Phew. I've never used it. I've never seen it, but I guess that can vote these files. So this is one of those cases where I'm not minutes out putting a file of it for a tool that Microsoft people have kind of, it's technically a standard out there, but. I was Googling around and I'm like, there doesn't seem to be a Mac viewer for it or anything. [00:15:53] James: Huh? There's a lot of weird, sounds like an opportunity for you to build one. Frank, [00:15:57] Frank: I started to think that too, right. I mean, who doesn't want to write a profiling tool that, that won't suck down six months of my life or anything as a, as a little disheartened, but then I noticed there's a second command and dotnet hyphen trace don't know. Convert. [00:16:15] James: Ooh, I like that. I feel like we're kind of into that world of machine learning models, but there trace all this [00:16:23] Frank: and it is a lot of data, everyone. Oh, let me describe a proper way to use these tools. Um, it turns out they're the happiest when you just kind of run your app and then your app terminates. So what I found, uh, Writing like a little console app version of my app that just runs a couple functions, the functions, I want to trace kind of like what you would do if you're doing benchmark.net to measure the overall performance of it. But, uh, anyway, it's so that way you're just kind of limiting the logs. I find like run something for about five seconds and that should give you, you know, plenty of a log to go trace. so.net. That's true. Uh, Space convert to speed scope, speed scope ever heard of speed [00:17:10] James: scope? No, I have not heard of speed scope, scope at all, but I do see that. I see that there's a net trace speed scope. And another one too. I don't know if you're gonna get to the other one too, but I don't know what a speed scope is. We are also converting the files are air reversible, by the way, they did not make a backup. [00:17:29] Frank: Yeah. Uh, you know what I do though? I converted the speed scope and then I delete that net trace file because speed scope files are G. [00:17:39] James: Oh, that's convenient and [00:17:41] Frank: everyone can read Jason. That's great. That's a great format. Um, there are going to be huge though, everyone. So imagine what's happening here. So, uh, 10,000 times a second, it is printing out the stack of your app on every thread. So imagine how much data that is and it's collecting and it's collecting it. Okay. So it's collected in this weird. And we can convert it to this other weird format. I still don't know what to do now. So I started to search like, how do you view speed scope files on a Mac? And it turns out there is a website, James speed scope.app, [00:18:17] James: and I'm looking at it right now. [00:18:19] Frank: It might be one of the greatest websites ever created. It's a little bit confusing because you go to this website and they're just like, Hey, just drop your file here, buddy. And you're like, what, what do you mean? Just drop my file here that I just dropped your file here and trust us. It'll be fine. And I don't. Yeah, I don't, I don't. I'm like, oh God, am I going to have to create an account and get a subscription? Is it going to be a free trial? You know, how long would the free trial last for. But no, it all seems to run clients' side. What you do is you take your ridiculous hundreds of megabytes, um, pro traits file, and you dump it on this website and it creates one of the best visualizations I've seen for doing performance analysis of an app. So I just want to make it clear the happiest moment in my life as I finally get. Decent UI for X very easily, honestly, very easily collecting a trace of my app in the past. If I wanted to do this, my, my favorite UI was instruments. You'll tend to X code and I would literally port things over to iOS just so I could run them on iOS, just so I could use X codes, performance tools, because their UI was that good. Now no more, no more, James. Now we have speed scope, uh, somewhat speed scope. We'll show you is pretty fantastic. It's a timeline for every thread and you can see exactly what functions it's executing at least. One 10000th of a second resolution. Uh, and, uh, yeah, you can see what code is calling, what code, where all the time is being spent, what they're doing. Uh, it can get a little bit busy because it has multiple threads. There are a few UI elements that I feel like I'm missing, like a. Profiler. We'll just tell you, look, you're spending all your time in this function or you're spending on that function, you know, boil it down for me. It doesn't have quite all the good boil it down for me features, but with a little bit of practice and everything, you can kind of get used to it. Um, have you managed to collect a trace within the last five seconds and look at on speed scope, James [00:20:38] James: speed's cup has an example of that. You can click. And you can, you can, uh, organize this by time order left heavy or sandwich, which has a sandwich. Emote emoji. And that's very favorable for me. [00:20:52] Frank: They do. They love their emojis here. And I will say, I, I love this UI, but it's not exactly intuitive. So I highly recommend that everyone go read the manual. [00:21:06] James: Okay. Th this is a tool that you need to know. Yeah. Is it until that you need to know how it works before you started using it. [00:21:13] Frank: It's true. It's true. But in its simplest form, it is just a timeline from left to right. Is your app's execution. And you can see exactly what your app was doing during that execution time. So you can zoom out, zoom out really far back. And see kind of, okay. It was, you know, loading a file for this amount of time. It was rendering an image for that amount of time. It was doing the network for that amount of time and you can get that high level perspective. And then when you decide, oh, you know, it feels like it's spending too much time in that part. What you can do is double click on those stack traces and zoom in and zoom in and zoom in and try to figure out. What's causing the delays in your app. And it's usually something like you're copying buffers around or you're waiting on a network connection. It's it's usually a wait and there's usually a wait handle involved. And you're just sitting there stalling the threat. [00:22:07] James: I wish that I could see the example. One seems it has a lot of it's Java app, I think has a lot of stuff in it. I don't actually know what's going on, Frank. So there's like a funnel there's colors. There's the guest smaller at some point. [00:22:23] Frank: Imagine if you single stepped through your entire app, once DACA one step, one step, and on every step you just recorded the stack. [00:22:34] James: Oh, [00:22:35] Frank: I see. Got it. Imagine that's all this thing is displaying for. Without the inefficiencies of doing that. So yeah, this is a Java app. Um, maybe it's a little hard to read the example here. I would send you my file, but I don't know if I can do it on air in all that time, but what, um, what you'll see in these kinds of apps is they'll break it down by each thread and you'll get to see what is a thread doing. So you usually start with the main thread of your app. The very first. That's created. And in most apps it's, you know, reading some files, do some processing, right? Some files out that's what a script would do, uh, for ice circuit. It's the simulation engine. So it goes into a loop and it's simulating, simulating, simulating. I can see exactly how long. Each function is taking during that simulation. And then I use my own judgment and decide if it's taken too long or not, you know, meeting the performance criteria that you set and then you dig in and you try to figure out why and answer the question. Why, yeah, [00:23:41] James: this is helpful if obviously, you know your code, cause you wrote your code. So your, these calls, these things are looking pretty familiar. And then if something looks a little out of place, like, Hm, it's really weird that it's. Half a second to read this file from disk. That doesn't make any sense, you know, and then you, like, you can go back to the code, fix something, run it again, retrace it, and then compare and contrast that by. [00:24:07] Frank: Yeah. Yeah, exactly. And some things are hard. Sometimes you feel like you're playing detective, but like you have so much data that you really can feel like you're playing detective. Other things are really obvious. So I was working on that Ray tracer and I noticed a long stretch of the. Didn't have a busy stack. You're looking at this and you know, the stack changes over time. It looks like a mountain range, but then there was a section of my app. That was just, it wasn't a mountain range. It was a flat desert desert of what in God's name is going on here. And when you have something flat, that just means there is a single function that is just taking a long time. Huh? Or in my case, it was a single function. It took a long time and then ended it again and then edited again again, again, again, again, again, again, and it was just this infinite desert of boring computation and you know what I did, I did a parallel for each over those 10 things do them in parallel instead. And I cut that time down and. Maybe a fifth, something like that just by using more threads. So it's a good place to see paralyzation opportunities too. If you run one of these traces and see a giant flat desert of doing nothingness, I think I could probably use some other threads or some other cores to do this in parallel. [00:25:26] James: Well, I think also the, these things come really into play with. Graphic intensive types of applications or computational applications where you can take advantage of those multiple, multiple threads. But at the same time, you know, I also think of it as I have looked at some of my code in the past where I do a wait, do something await, do something, await, do something. And then I do something at the end. And what I don't really realize is that I could. Ron, all those tasks at the same time, like you're saying. And so even in an application where maybe you're making some web requests, why not make all those web requests at the same time, or why not do X, Y, Z at the same time like that, you know, a good example, you know, just animations, like play all the animations at the same time as that of doing certain things in a waiting and. Abusing that poor TPL. Um, those multiple, I guess that's not threads, but they're tasks on a thread and there, I guess it could be multiple threads, but you know what I mean? Like there's those things too, which might show up, but you could say, oh, it's super weird that this one method of refreshed data is taking five seconds. Oh, well, why is it taking five seconds? Well, because I'm doing these calls inside of, instead of doing them all simultaneous, right? That could be your problem is three seconds. Doesn't seem like a lot, but it could be one side. [00:26:51] Frank: Absolutely. That's a big that's. That's [00:26:52] James: literally. 200%, 5000000000% faster. [00:26:58] Frank: Yeah. Or if you have an app, like I circuit that has a simulation, that simulation loop is attempting to run 50,000 times per second. So anything that's slow inside of that loop shows up like a big red herring. You know, I, I zoom into one of these things and there's a. Oops, you messed up. You know, it's, it's very obvious that I made a mistake because nothing in this simulation engine is allowed to take up time just by kind of definition. So, yeah. And, and that case, it's almost, um, it's important to the app because if the simulation route doesn't run fast enough, it can fall behind on audio and things like that. And then it's not real time anymore. So it's not just me being a performance freak. I am guilty, but, uh, it actually affects the correctness of the app too, if it's too slow. [00:27:50] James: Sorry, my, well, my favorite part of this app, I'm selling the speed scoped out app. Is that, so you just go to speed, scoped out apple, put I'll put it in the show notes. If I remember, uh, and. [00:28:01] Frank: Sorry. I want to make it clear too. What's so cool about this as how easy it is to get a trace from dotnet to, so everyone just go trace your app. It'll just be fun. If you have an app called trace your app and throw it in the speed scope. Don't look at the example. It'd be way more interesting with your own app. Yeah. [00:28:16] James: Yes. Go for the example or your own app. There's like the, this plateau, it's a reverse plateau and a reverse mountain, if you will. Yeah. And. Um, the cool part is, is like it's an, a big view on the bottom and like a mini histogram on top. But the cool part is that at any point you can click. Select a box, a range, and the whole thing moves so beautifully. It's just like a colorful rainbow of goodness and joy when you're do you know what I mean? Do you know what I'm talking [00:28:48] Frank: about here so late? So this is why you need to read the help file because there are actually a lot of keyboard shortcuts for moving that view around, like it actually responds to the. The cursor keys. So you can use wives deed to move plus and minus to zoom in and enhance very important because sometimes you need the, uh, larger outer perspective. Sometimes you need to see exactly which functions are being called. You can double click on a function and zoom in to just that function to see everything that it's calling and what's taking time there. And yeah, there's, there's a million things to read in here. Now you were saying before about tasks and threads. And I would admit that's where it gets a little bit bad. This tool is obviously very generic. Um, you can just throw anything at it and it can, it'll display this beautiful graph, but it doesn't know about how, like you said, the TPL works and tasks work and all that stuff. So it's, uh, your code that actually does a way away away await is going to be scattered over a bunch of threats. And at the very top of the app, you can select which threads you're going to be viewing. And as far as I can tell, it's only one at a time. Maybe there's other ways to use this app. So I'll say that async code can be a bit tricky to work out here, but you know, James, you and I could write our own UI for this and we'll work out all that async craziness and we'll restore the graphs to beautifulness. [00:30:20] James: How does, does, does it hurt with all my apps or. [00:30:25] Frank: Uh, okay. So I, my example was I did.net six is far as I know. This has been a feature of.net core since version three. Hmm. Okay. So I'm very late to the game, but you know, what's cool. Now dotnet six includes apple apps and things like that. So yeah, this, this works on all the dotnet core stuff. So anything you have, this will work on your ASP's. This will work on your, I don't know what else [00:30:53] James: am I, Andrew? [00:30:54] Frank: Probably maybe, I don't know, hashtag I don't know how Android emulators work and all that kind of stuff. Um, it's easiest, uh, on your computer itself. This is where Mac catalyst is such a huge advantage to me because I can take my iOS apps, run them as Mac catalyst apps and get these beautiful performance traces. But if you have an iOS app, I highly recommend just using X coats instruments because it's freaking out. [00:31:19] James: That makes sense. That makes sense. How does this differ? Do you know, from dotnet monitor [00:31:27] Frank: different things? Um, so.net comes with a diagnostics port. That's call it, built into it and you can actually go get a library out there. I think it's called like.net diagnostics client or something like that. Yeah. And. Interrogate any process and hook into the diagnostic port, which gives you event streams, which is what this is doing. You can actually write your own profile are pretty simple using this technique. Um, and there are multiple events streams. So what I've been talking about it on this whole show is CPU profiling, but another big one that you often want to do and.net is memory profiling. See what you're allocating, how often you're allocating, how much pressure are you putting on the garbage collector? Because that stuff can add up. If you ever get a garbage collector, pause, you'll want to go do that. You're probably doing something silly with allocations. Uh, it can do that. It can do all sorts of stuff. I'm always surprised at how much is in that diagnostic. So the dotnet monitor. I think that that's just yet another interface into all that. [00:32:34] James: Okay. Gotcha. Yeah, it says it it's a set of local and production and diagnostic artifact, collecting of logs, traces, processed thumps, and simplifies exposing consistent HTTP API, regardless of where your API runs. Oh, so maybe it's like also in production, if you have a web server or something, or I [00:32:53] Frank: can send the Brunetti's it's probably set up to wow. Yeah, server environment, because otherwise it's pretty, what you're doing is always a local process. So that's probably doing the heavy lifting of a remote process. So what I'm talking about is stuff running on your machine. That's the easiest way to, [00:33:10] James: yes. I'm curious, Frank. I have to try, this is if I run a dotnet six Android app on windows 11 inside Android, some system for windows, which has a pitch. Ghana down at [00:33:26] Frank: trays. It maybe, maybe hashtag maybe. Okay. So I've read a few of the docs just cause I was trying to understand how this diagnostic stuff worked. Um, on Mac and Linux, it uses a domain socket, uh, to communicate. That's a pretty traditional thing in Unix world in windows that uses a named. So as long as that name pipe is getting transported, you might, I don't know. You might have to do some fancy things, but I think the potential is there because as far as I can tell all these dotnet processes have this type of plastic for it open and it's not a port, you know, know what I mean? [00:34:06] James: Yeah. That's pretty cool. Yeah. It says that on Don at five and later the diagnostic port, it's a feature that was added allows you start tracing from app startup. You collect command and you pass that a diagnostic port or something like that. [00:34:22] Frank: Yeah, crazy. It's actually kind of funny. Um, the, it starts the trace very early on in the apps boot up. So you can actually see kind of dotnet loading itself in the very beginning of your app. You're like, oh, it's creating all these strings. Cause it needs a bunch of Springs. Uh, so you could see like the first, like 10 milliseconds of your app or just. Dot net booting up itself. It's really fun. Uh, you can see your link expressions, compiling, how long they take and all that kind of stuff. I know it's I, and there are, and there are other tools out there. Everyone visual studios built in debugger does profiling. Automagically it's amazing. I love visual studios built in profiler. Uh, JetBrains has something called doc tray. Uh, I've had some success with it in the past. What I love is that this is just baked in to dotnet itself. It's Amanex, it's on the Mac. And even though it outputs a weird log file, it's really easy to convert into something that's actually viewable. I love that. [00:35:20] James: No, it's cool because there's actually all of these different done at CLI global tools and Dynatrace is just one of them. No, I'm going to list off all the other ones on the documentation, at least because there's Donna counters.net coverage, done a dump, done a Jeezy dumped on a trace. Of course, Donna stack done assemble done at SOS and dotnet DS router. [00:35:41] Frank: There are a lot of fancy little tools out there. It turns out I've used SOS. SOS is a debugger add in so that you can debug.net code from a native debugger. That's always good to have. [00:35:56] James: Um, Frank, oh my gosh. Dow dotnet Diaz. Router. Are you ready for [00:36:01] Frank: this? Uh, I'm trying to get from a name I'm trying to get from. Uh, I don't have anything. Okay. What do you got? [00:36:08] James: BS, router connects diagnostic tools like dotnet trays and Donna counters to Don and applications running on Android, iOS and T O S. Regardless of whether they're running as an emulator simulator or the device itself, diagnostic tools uses local. Process communication, IPC named pipes, Unix, domain sockets to connect and communicate to the.net runtime, an applications running in a sandbox environment, such as emulators, simulators and devices need alternative ways to communicate this thing injects itself in between the existing diagnostic tooling in dotnet mobile applications and creates a representation. Application the Diaz, router enables diagnostic tools to communicate with a remote.net runtime as if it's running on the local machine. [00:36:57] Frank: Well, jeepers creep. Well, I guess we know what we're talking about next week. That is amazing. I mean, it makes sense because from what I've heard. Shoving shuffling this data all around. You know, the runtime can collect it. It just needs to get it off the device. So that is doing some insane networking, scary process stuff. To get the data off of a device. I love it. Please do it and report back. [00:37:23] James: Wow. And it's all open source. Um, get github.com/done it slash diagnosis. [00:37:29] Frank: Yeah, that's what I, I, you know, all the pain of dotnet six and trust me, there has been a lot of pain. The nice thing is, and this is where, like, this is why I wanted to do this show. These little happy things where like, oh gosh, at least I get to use this ridiculously powerful tool. Now that works very reliably on all sorts of. Apps. That's pretty cool. And I got a new favorite speed. New favorite web apps. Speed scoped out app [00:37:54] James: everyone. Yeah, that's so crazy. Wow. I, I mean, I have to imagine that the, the, the, the teams have been this cool part is what you said earlier is, oh, it exports to this windows thing. Like obviously the Donna team used for like ever, but like, obviously these are tools that like the dotnet teams probably use themselves and they just made them available to every. [00:38:12] Frank: Oh, yeah. Yeah. You can definitely tell sometimes there is that, uh, and they, they kinda want you running your own tools too. So, and the way, like, you know, maybe you want to collect performance logs without as much detail on all this. Uh, they made that diagnostics client. Pretty easy to use. I would say I didn't write a big, complicated thing with it, but you can definitely write your own kind of profile or stuff with it if you care. But otherwise, um, yeah, you can tell that this is a dev tool stuff. Watch out. Uh, the documentation as a dev tool is a little bit behind the current version. There are command line arguments that have changed and all that stuff. So I highly recommend just looking at the source code for it and seeing what the command line arguments are. [00:38:57] James: From there, there is documentation on the Don and Mallory repo that is profiling, Don Moe apps, which use Donna DS router and Don at trace. And they show you how to do [00:39:08] Frank: blog entry coming up. We got to refine it though. If it sounds a little complicated, we just need like a, we need to write a Maui app that can profile Maui apps. That's what we need. Yeah. [00:39:18] James: Yes, that is true. I know. Just incredible. That's just, I don't know. That's cool to me. [00:39:25] Frank: It is. Yeah. I I'm so excited to have this, honestly, because I was just never able to profile my, uh, dot net core apps. Like I said, I was porting things to iOS to profile them and that's just silly. Uh, so this is exciting. Can I also just, uh, to end the show, give a big shout out to Rio. The jet, the jet, the jet, it turns out it's pretty good at its job. I was trying to outsmart it as being all like computer science-y and hackery. And I was like, I'm going to write the register level code to make this loop faster, and I'm going to make the math better. And I'm going to, I'm going to do all this complicated stuff to like speed it up. That's the profiler was telling me I could speed it up. And after all that effort, rewriting the code to use all the latest x86 intrinsics and vector operations and all that stuff. It was IR measurably slower slash faster than the Rio version of it, which was a simple C-sharp for a loop over an array. So everyone, your simple C-sharp for loops over an array are very fast. Thanks to readmit. Good job using. [00:40:32] James: all right. Well, we've now officially done that trace what they're done at DNS router. So that is going to do it for this week's merge conflict. Hope everyone enjoyed our subscription update and also a profile. I mean, we talked about provolone for a half an hour and literally provides never fun to talk about it. And I had a blast because I just discovered all sorts of fun things that I'm sure the team that worked on are going to be like excited. Hopefully if they, I don't know if they listen to our podcast by novice. Shout out to all of them. Uh, that, cause that's really, really neat stuff because we're like, I wonder if this works. Oh, it does someone thought about that? So, alright. That's gonna do it for this week's podcast. Franklin did it. So until next time, this has been an emerge conflict. I'm James Montoya [00:41:09] Frank: Magno and I'm Frank Krueger. Thanks for listening.