As we all know, the performance problem is the inevitable problem that all practical applications must face in the iterative process. For such problems, it may be possible to simply put more hardware resources into practice. But overall, the marginal cost of such practices is rising. In other words, with the rise in performance requirements, the same performance gains are needed, and the cost of hardware upgrades will be higher. Therefore, performance optimization is the technology that every operation/software developer must master.
. Net Profiling
in the application performance optimization practice, the first thing to face is hot spot , which determines the location of the code that brings great resource dissipation. It is quite difficult to locate resource hotspots without using external tools. It requires the client to have an overall grasp of the application implementation itself, to understand the path and details of each functional module code within the application architecture. At the same time, the parties must also be certain of the performance of the third-party function library that the application realizes depends on. For those with a certain scale of application systems, the number of engineers with the aforementioned qualities is numbered. And even these cream of outstanding talent, its hot-spot prediction can not guarantee that must be accurate.
Profiling technology is proposed in order to solve the hot spot , it is to help engineers to understand the application behavior by the actual running data of the program, which greatly simplifies the work of the engineers. For more mature technology stacks like. Net, experts such as Bill Chiles and Zhao recommend that engineers use actual Profiling data to locate performance bottlenecks. In practice, the ability to get. Net Profiling data is implemented as a COM component entity called Profiler. In the following, we will discuss the implementation of the Profiler itself.
Profiling API
The. NET Profiler is essentially a plug-in to the CLR that uses the Profiling API to maintain communication with the CLR and to obtain runtime data for. NET Apps. Typically, the Profiler entity behaves as a dynamic-link library (a. dll file), which the CLR loads at runtime (a detailed configuration of the CLR load Profiler can refer to this document) and sends information to the library at a specific stage of the program's run and accepts the information returned by the library.
It is important to emphasize that, although called the Profiling API, the CLR's interface can do more than simply measure the runtime and memory dissipation of an application. In practice, the profiling API can perform many advanced functions such as code coverage, runtime insertion, and so on. However, as the MSDN Profiling review document emphasizes, Profiling should be transparent to the application itself. That is, developers should not rely on or be affected by the Profiler in their own logic when writing an application.
For the. Net technology stack, because the environment itself introduces advanced features such as application domain, GC, managed exception handling, and JIT, the Profiling can only show up to the time or memory consumed by the application running. To be able to really show runtime behavior, the Profiling API provides an interface for data that contains these attributes. This makes the Profiling API design not as intuitive as many people think.
Common. Net Profiler implementations take the following architecture:
650) this.width=650; "src=" Https://i-msdn.sec.s-msft.com/dynimg/IC13527.jpeg "title=" "style=" Height:auto; vertical-align:middle;border:0px; "/>
. Net Profiler Architecture
,icorprofilercallback and ICorProfilerInfo are the two most commonly used in the Profiling API. When the app is running, the Profiler DLL is loaded into the process where the app resides. By implementing an interface for a specific function under ICorProfilerCallback, the Profiler DLL receives notification of the action execution when the application runs. For example, if the ICorProfilerCallback::AssemblyLoadFinished interface is implemented in the profiler DLL, the profiler DLL is used every time that an assembly is loaded in the application run The implementation code of the interface is called. Similarly, the Profiler DLL can be achieved by implementing the interface under the ICorProfilerInfo to obtain the state of the monitored application.
It is necessary to add that the ICorProfilerCallback interface described above actually has an interface definition of 7 versions such as ICorProfilerCallback ~ ICorProfilerCallback7. High-grade interface versions are backwards compatible, but new feature extensions are available. However, higher-numbered interfaces are often required to be supported by newer versions of the CLR (such as calling ICorProfilerCallback7 to deploy the. Net Framework 4.6.1 above in the environment), which needs to be paid more attention to when actually used.
Currently, the Profiling API can be called by any unmanaged COM-compatible language. In addition, the implementation of the API itself is very efficient and does not incur an additional performance burden that is large enough to cause profiling to fail. As a result, a sample profiler can be fully implemented based on the Profiling API (for a discussion of the Profiling model, refer to section 2.1 of this document).
features currently supported by the Profiling API
-
CLR startup and shutdown
-
Application Domain creation and shutdown
-
Assemblies loading and unloading
-
Modules (module) the creation and destruction of
-
COM vtable
li>
JIT compiling and code-pitching
-
Loading and unloading of the class
-
Thread creation and destruction
-
Function entry and return
-
Managed code execution switch to unmanaged code
-
Run-time
-
Run-time heap memory information with GC activity
With the evolution of. Net technology, the future Profiling API may be able to provide more information. However, the following feature points are not implemented by the Profiling API, and should be avoided when applied:
Execution information for unmanaged code
Profiling of an application that modifies its own code at run time (such as AOP)
Boundary inspection
Remote profiling
Profiling in high Reliability environment
Thread-related
For a process that loads a Profiler DLL, the new thread itself generates various event notifications defined under the ICorProfilerCallback interface when a new thread is created. In this process, the Profiler does not have to explicitly specify a ThreadID to make the Profiling API effective. Similarly, Profiler can simply use thread-local storage in code, without having to bother with global redirection of storage locations.
Of course, there are some points that need to be heeded in the context of concurrency. For example, the Profiling API itself does not guarantee thread safety for data structures, so we need to lock the profiler code conflict areas where parallel access is possible to ensure that the profiler behaves as expected. Similarly, for multi-threaded scenarios, the Profiler should not assume that there is a certain sequence of ICorProfilerCallback interfaces. For example, a program with two threads of the same thread might run with a functionenter before generating icorprofilercallback::jitcompilationfinished.
There is also a thread-related problem that comes from the COM interface. As we said above, the Profiler is actually implemented as a COM component, but in fact the CLR does not initialize COM at runtime. This is to avoid the CLR calling [Coinitialize][ref12] to specify the application threading model before the application code specifies the threading model. Similarly, inside the Profiler, do not call CoInitialize to avoid conflicts with the application code.
Call Stack
Getting the call stack information is a critical requirement when applying Profiling. To meet this requirement, the Profiling API is available to Profiler writers in two ways: stack snapshots and reflection stacks.
A stack snapshot is a trace of the call stack for a particular thread at a particular point in time. It is important to note that the Profiling API only supports tracing of Oberto tube functions. If the Profiler needs to track the unmanaged functions on the stack, it needs to provide a stack walker itself. Readers interested in the implementation details of the Profiler stack snapshot mechanism can refer to divID Broman's blog content.
Frequent use of stack snapshots brings excessive additional performance loss to the CLR. Therefore, if a stack trace is required frequently, the Profiler should pass FunctionEnter2, FunctionLeave2, FunctionTailCall2, and icorprofilercallback::exception* A series of interfaces constructs a reflection of the current application call stack. This allows the Profiler to perform stack-tracking operations with low consumption.
other places to be aware of
As previously emphasized, Profiler is an unmanaged DLL library that is loaded into the CLR while the app is running and under the same process space as the app. Thus, the Profiler DLL is essentially not controlled by access to managed code. The only limitation of its operation is that the OS user running the Profiler must have sufficient permissions. Therefore, for the technician to deploy the Profiler, it is important to understand the possible risks and prepare early. For example, you can add a Profiler DLL to an Access control list (ACL) to prevent malicious users from exploiting it.
Also, the Profiler DLL, as a plug-in for the CLR, may cause the CLR itself to crash, and be careful when implemented. For the Profiler running in a tight stack of memory space, be wary of applications crashing due to ICorProfilerCallback causing stack overflow. In this resource-constrained environment, it is best to minimize the resource dissipation of the Profiler itself. Try to avoid situations in which an application that would otherwise be able to run cannot run because of Profiler.
Conclusion
In this paper, the general situation of. Net Profiling technology is described, and some important technical points are expounded. Hope to help readers understand. Net Profiling technology. Later, we will go into the code implementation level and discuss the implementation of the. Net Profiling in detail.
OneAPM to help you easily lock . NET application performance bottlenecks, through a powerful Trace record-by-layer analysis until the row-level problem code is locked. Displays the system response speed at the user's point of view, and counts user usage in geographic and browser dimensions. To read more technical articles, please visit the OneAPM official blog.
This article turns from OneAPM Official Blog
. NET Profiling technology required as a. NET Siege master