In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-20 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article will explain in detail how to write high-performance .NET. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.
Reduce the distribution rate
This is almost unexplained, reducing the amount of memory used, naturally reducing the pressure on GC recycling, and reducing the use of memory fragmentation and CPU. You can do this in some ways, but it may conflict with other designs.
You need to carefully examine each object as you design it and ask yourself:
Do I really need this guy?
Is this the field I need?
Can I reduce the size of the array?
Can I reduce the size of the primitives (replace Int64 with Int32, etc.)?
Are these objects used only in rare cases, or only during initialization?
Can you convert some classes into structures so that they can be assigned on the stack or become part of an object?
Do I allocate a lot of memory, but actually use only a small portion of it?
Can I get the relevant data from somewhere else?
Short story: in a function on the server side that responds to a request, we find that some memory is allocated larger than the memory segment in a request. This causes us to trigger a complete GC for each request, because CLR requires all Gen 0 objects to be in one memory segment. When the current allocated memory segment is full, a new memory segment will be opened, and the original memory segment will be reclaimed for 2 generations. This is not a good implementation because we have no choice but to reduce memory allocation.
The most important rule
There is a basic rule for high-performance programming of garbage collection, which is, in fact, a guiding rule for code design.
The object to be collected is either in generation 0 or does not exist
Collect objects in gen 0 or not at all.
The difference is that you want an object to have a very short life cycle, never touch it during GC, or, if you can't do that, they should go to 2 generations, as fast as possible, stay there forever, and never be recycled. This means that you always keep references to long-lifecycle objects. In general, it also means that objects can be reused, especially in large object heaps.
Recycling per generation of GC is more time-consuming than the previous generation. If you want to keep a lot of the first generation and a small number of second generation objects. Even if GC is enabled in the background to do second-generation recycling, it will consume a considerable amount of CPU computation, and you may prefer to consume this part of CPU to the application rather than GC.
Note you may have heard a saying that every 10 times of 0 generation recycling will produce one generation of recycling, and every 10 times of 1 generation recycling will produce 1 generation of 2 generation recycling. This is actually not true, but you have to understand that you need to generate as many times as possible fast zero-generation recycling and a small amount of second-generation recycling.
You'd better avoid first-generation recycling, mainly because objects that have been promoted from generation 0 to generation 1 will be transferred to generation 2 at this time. The first generation is a buffer for the object to enter the second generation.
Ideally, each object you allocate should end its life cycle before the next generation 0 collection. You can measure the interval between two GC and compare it with the life cycle length of objects in the application. Information on how to use tools to measure the life cycle can be seen at the end of this chapter.
You may not be used to thinking this way, but this rule cuts into all aspects of the application, and you need to think about it often and make a fundamental change in your mindset in order to achieve this most important rule.
Shorten the life cycle of an object
The shorter the scope of an object, the less likely it is to be promoted to the next generation when the next GC appears. In general, don't create objects before you need them.
At the same time, when the cost of object creation is so high, exceptions can be created earlier so that they do not interfere with other processing logic.
In addition, you need to make sure that the object leaves the scope as early as possible. For local variables, you can end their life cycle after the last use, or even before the end of the method. You can include the code with {}, which will not affect your run, but the compiler will think that the object in this scope has completed its life cycle and is no longer used. If you need to call the object's method, minimize the interval between the first time and the last time, so that GC can recycle the object as soon as possible.
If objects are associated (referenced) with objects that have been held for a long time, they need to be dereferenced. You may have more null checks (null judgments), which may make the code more complex. It can also create tension between the available state (always having full state available) of an object and efficiency, especially when debugging.
One solution is to convert the object to be emptied into another way, such as log messages, so that the relevant information can be queried later during debugging.
Another way is to add a configurable option to the code (without undoing the relationship between objects): run the program (or run a specific part of the program, such as a specific request), without dereferencing the object in this mode, but keep the object as easy to debug as possible.
Reduce the depth of the object hierarchy
As mentioned at the beginning of this chapter, GC traverses along the object's reference relationship when it is reclaimed. In server GC mode, GC runs in multithreaded mode, but if a thread needs to deal with an object at a deep level, all threads that have finished processing will have to wait for that thread to finish processing before exiting. In future versions of CLR, you don't have to pay too much attention to this problem. GC will use a better marking algorithm for load balancing in multithreaded execution. But if you have a deep level of object, you should pay attention to this problem.
Reduce references between objects
This is related to the depth of the previous section, but there are also some other factors.
If an object references a lot of objects (array, List bar), it will spend a lot of time traversing objects. It is GC that causes a long-term problem because it has a complex diagram.
Another problem is that if you can't easily determine how many reference relationships an object has, you can't accurately predict the life cycle of the object. It is necessary to reduce this complexity, not only to make the code more robust, but also to facilitate debugging and better performance.
In addition, it should be noted that references between different generations of objects can also lead to GC inefficiency, especially the reference of old objects to new objects. For example, if a Gen 2 object has a reference relationship in a Gen 0 object, then every time a Gen 0 GC occurs, you also need to scan some Gen 2 objects to see if they still hold on to the Gen 0 object reference. Although this is not a complete GC, but it is still not a job, you should try to avoid this situation.
Avoid pinning objects (Pinning)
Pinning objects ensures the security of passing data from managed code to local code. Common are arrays and strings. If your code doesn't need to interact with native code, don't worry about its performance overhead.
Pinning an object is to make it impossible to move it during garbage collection (compression phase). Although pinning objects does not incur much overhead, it interferes with GC recycling operations and increases the likelihood of memory fragmentation. GC records the location of objects when reclaiming in order to take advantage of the space between them when rearranging the allocation, but if there are many objects pinned, it can lead to an increase in memory fragmentation.
Nails can be either displayed or implicit. Shows setting with the GCHandleType.Pinned parameter when using GCHandle, or using the fixed keyword in unsafe mode. The difference between using the fixed keyword and GCHandle is whether the call to the Dispose method is displayed. Although it is convenient to use fixed, it cannot be used asynchronously, but you can still create a handle object (GCHandle) that is passed back and processed on callback.
Implicitly pinned objects are more common, but they are also more difficult to troubleshoot and remove. The most obvious example is passing objects to unmanaged code through platform invocation (P/Invoke). This is not just your code-some of the managed API that you often call will actually call native code and pin objects.
CLR will also pin some of its own data, but this is usually not your concern.
Ideally, you should try not to pin the object as much as possible. If not, follow the previous important rules and release these nailed objects as soon as possible. If the object is simply pinned and released, then there is little chance of affecting the recycling operation. You should also avoid nailing many objects at the same time. It is slightly better for nailed objects to be swapped to the second generation or allocated in LOH. According to this rule, you can allocate a large buffer on the large object heap and manage the buffer yourself according to your actual needs. Or allocate buffers on small object pairs and upgrade them to Generation 2 before nailing them. This is better than nailing the object directly to Gen 0.
This is the end of the article on "how to write High performance .NET". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.