How to use dotTrace to diagnose performance issues with netcore apps
Recently doing a performance upgrade for the Newbe.Claptrap , introduce the basic usage of the dotTrace software used in the process to the developers.
#
SummarydotTrace is Jetbrains' profile software for .net applications.Helps with diagnostic analysis of time-consuming functions and memory problems in your software.
In this article, we will use Jetbrains' dotTrace software to analyze some known performance issues.This enables the reader to master the basic skills of using the software.
During the process, we will be paired with some classic interview questions to demonstrate the use of the software step by step.
This example uses Rider as the IDE for the main demonstration. Developers can also do the same with VS and Resharper.
#
How to get dotTracedotTrace is paid software.Currently, the software directly as long as dotUltimate and above licenses are purchased.
Of course, the software also includes a trial version, which allows you to start the 7-day trial for free.Jetbrains' IDE purchases are more than a year old to get the latest version of the current permanent use.
Or you can buy Jetbrains family bucket license, all at once.
#
Classic scene reproductionNext, let's take a look at how to use dotTrace through some classic interview questions.
#
When to use StringBuilderWhat a classic interview question.Friends who can see this article, I'm sure you all know that StringBuilder can reduce string direct stitching fragmentation and memory stress.
Are we real?Will it just the interviewer who wants to embarrass me and bully me with asymmetric information?
It doesn't matter, next, let's use dotTrace to analyze a wave of specific combination code.See if using StringBuilder has reduced the pressure on memory allocation.
First, let's create a unit test project and add one of the following test classes:
Then, as shown in the following image, we set the profile pattern in Rider to Timeline.
TimeLine is one of several patterns that provide a more comprehensive view of how each thread works, including multidivided data such as memory allocation, IO processing, locking, reflection, and so on.This will serve as one of the main patterns used in this example.
Next, as shown in the following image, start the profile for the corresponding test with a small icon on the left side of the unit test.
After you start profile, wait a while for the latest generated timeline report to appear.The location of the view report is shown below:
Right-click the corresponding report and select Open in External Viewer to open the generated report using dotTrace.
So first, let me open the first report and look at the report generated by the UsingString method.
As shown in the following image, select .Net Memory Allocations to see the amount of memory allocated during the test run.
Based on the figure above, we can draw the following conclusions:
- In this test, 102M of memory was allocated to String.Note that the allocation shown in dotTrace refers to all allocated memory throughout the run.This value does not decrease even if it is subsequently recycled.
- Memory is allocated as long as it is made on the CLR Worker thread.And very dense.
Tip: Timeline shows longer running times than normal testing because of the additional consumption of data that needs to be recorded during the profile process.
So we came to the first conclusion:using string for direct stitching does consume more memory allocation.
Next, let's go ahead and look at the report on the UsingStringBuilder method, as shown:
Based on the figure above, we can draw the second conclusion:Using StringBuilder can significantly reduce the memory consumed compared to string direct stitching.
Of course, the final conclusion we came to:that the interviewer was not fooling people.
#
What effect class and struct have on memoryThere are many differences between class and struct, and interview questions are frequent visitors.There is a difference in memory between the two.
So let's take a test to see the difference.
Code Essentials:
- Two tests, create 1,000,000 classes and struct to join to the List.
- After you run the test, output the size of the current heap space at the end of the test.
Following the basic steps provided in the last section, we compare the reports generated by the two methods.
UsingClass
UsingStruct
Comparing the two reports, you can draw the following conclusions:
- The memory allocation in the Timeline report contains only the memory that is allocated to the heap.
- Struct does not need to be assigned to the heap, however, the array is a reference object and needs to be assigned to the heap.
- The essence of List's self-increasing process is that the characteristics of the expansion array are also reflected in the report.
- In addition, it is not shown on the report, and as can be seen in the test printed text, the heap size after the UsingStruct run confirms that the struct will not be assigned to the heap.
#
Boxing and unboxingClassic interview question X3, come on, code, report on!
Boxing, boxing occurs
NoBoxing, no boxing
Comparing the two reports, you can draw the following conclusions:
- There is no killing without buying and selling, and there is no distribution of consumption without demolition.
#
What's the difference between Thread.Sleep and Task.Delay?Classic interview question X4, come on, on the code, on the report!
ThreadSleep
TaskDelay
Comparing the two reports, you can draw the following conclusions:
- Thread.Sleep is tagged separately in dotTrace because it is a non-performing practice that can easily cause thread hunger.
- Thread.Sleep has one more thread in sleep than Task.Delay
#
Does blocking a large number of Tasks really cause your app to stay motionless?With the conclusion of the next step, the author came up with a bold idea.We all know that threads are limited, so what if you start a lot of Thread.Sleep or Task.Delay?
Come on, code:
Here is no post report, readers can try this test, you can also write the content of the report in the comments of this article to participate in the discussion
#
Reflection calls and expression tree compilation callsSometimes we need to call a method dynamically.The most well-known way is to use reflection.
However, this is also a relatively time-consuming way to be known.
Here, the author provides an idea of using expression tree creation delegates instead of reflection to improve efficiency.
So, has there been a reduction in time consumption?Good report, I can talk myself.
RunReflection, call directly using reflection.
RunExpression, which compiles a delegate using an expression tree.
#
SummaryUse dotTrace to see how much memory and time the method consumes.The content presented in this article is only a small part of it.Developers can try to get started, which can be beneficial.
The sample code in this article can be found in the link repository below: