C # Performance Optimizations

Source: Internet
Author: User
Tags rowcount
Performance is an important indicator of the quality of a software product, and the function of the product has the same important status. Users in the selection of a software product when the basic will be tested to compare the performance of similar products. As one of the important factors in purchasing that software.

What does the performance of software mean?
1. Degraded memory consumption
In software development, memory consumption is generally considered as a secondary consideration, because now the computer generally has a larger memory, in many cases, the means of performance optimization is to exchange space for time. But it's not that we can splurge on memory. If you need to support a use case with a large amount of data, the operating system will have frequent internal and external exchanges if memory is exhausted. resulting in a sharp drop in execution speed
2. Improve execution speed

Load speed.

The response speed of a particular operation. Include, click, keyboard input, scrolling, sort filter, etc.


The principle of performance optimization

Understanding Requirements
Taking MultiRow products as an example, one of the performance requirements for multirow is: "Millions of rows of data are bound to smooth scrolling." "The development process of the entire MultiRow project has been to consider this goal.

Understanding bottlenecks
Based on experience, 99% of the performance cost is due to 1% of the code. So, most of the performance optimizations are for this 1% bottleneck code. Concrete implementation is divided into two steps. First, identify bottlenecks and, second, eliminate bottlenecks.

Avoid excessive
The first thing you have to realize is that performance optimization is inherently cost-conscious. This cost is not only reflected in the work done to optimize performance. It also includes complex code written for performance optimizations, additional maintenance costs, introducing new bugs, additional memory overhead, and more. A common problem is that some students who have just come into contact with software development will have unnecessary complexity in some of the unnecessary points mechanically performance optimization techniques or design patterns. Performance optimization often requires a trade-off between revenue and cost.


How to discover performance bottlenecks

As mentioned in the previous section, the first step in performance optimization is to identify performance bottlenecks, which are some of the practices that focus on locating performance bottlenecks.

1. How to get memory consumption

The following code can get the memory consumption of an operation.

Write some code here that might consume memory, for example, if you want to understand how much memory is required to create a gcmultirow software, you can execute the following code long start = GC. Gettotalmemory (True); var gcMulitRow1 = new Gcmultirow (); Gc. Collect ();//Ensure that all memory is reclaimed by GC gc.waitforfullgccomplete (); Long end = GC. Gettotalmemory (true); long usememory = End-start;

2. How to get time consumption
The following code can obtain an operation time consumption.

System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch (); watch. Start (); for (int i = 0; i < i++) {     gcmultirow1.sort ();} Watch. Stop (); var usetime = (double) watch. elapsedmilliseconds/1000;

This takes an operation Loop 1000 times, and then divides the time spent by 1000来 to determine the final consumed time. Can be more accurate and stable results, excluding unexpected data.

3. Discover performance issues through Codereview.
In many cases, performance issues can be discovered through Codereview. For large data volumes of the cycle, pay particular attention to. The logic within the loop should be executed as fast as possible. 4.ANTS Performance Profiler
The ANTS Profiler is a powerful performance testing software. can help us find performance bottlenecks very well. Using this software to locate performance bottlenecks can be a multiplier effect. Skilled in using this tool, we can quickly and accurately locate the code with the performance problem. It's a powerful tool, but it's not perfect. First of all, this is a fee software, the department has only a few license numbers. Second, the software works by adding some hooks to the IL to record the time. Therefore, in the analysis, the execution speed of the software is slower than the actual operation of the data obtained is not completely accurate, should be the software analysis of data as a reference to help quickly locate the problem, but do not rely entirely on, but also with other techniques to analyze the performance of the program.

Methods and techniques for performance optimization

After the performance problem has been fixed, there are many ways to solve it. This section describes some of the techniques and practices of performance optimization.

1. Optimizing the program Structure

For the program structure, it should be considered at design time to assess whether performance requirements can be met. If you later discover performance issues you need to consider adjusting the structure for a very large overhead. Example:


1.1 Gcmultirowgcmultirow to support 1 million rows of data, assuming that there are 10 columns per row, you need 10 million cells and a lot of properties on each cell. Without any optimizations, the memory overhead of a gcmultirow software can be quite large when the volume of data is large. The scenario used by Gcmultirow is to use a hash table to store row data. Only rows that have been changed by the user are placed in the hash table, and the templates are used directly instead for most of the rows that have not changed. It achieves the purpose of saving memory.


1.2 Spread for Wpf/silverlight (SSL) WPF has different representations and WinForm, and is implemented by combining the view elements. SSL also supports millions data volumes, but cannot assign a view to each cell. So SSL uses Virtualizepanel to implement the drawing. The idea is that each view is a cell display module. Can be separated from the cell's data module. Such You only need to create a view for the displayed cell. When scrolling occurs, a portion of the cell rolls out of the screen, and some cells roll into the screen. At this point, let the cell and view of the rolling out screen separate. Then reuse this part of the view to the new cell that enters the screen. So loop. This requires only hundreds of view to support a lot of cells.


2. Caching

Caching (cache) is the most commonly used optimization method in performance optimization. It is often useful to get some data, and it takes longer to get the data each time. At this point, the first time you get it, you will use the normal method, and then cache the data when you get it. The cached data is then used. If you use the Cache optimization method, you need to pay special attention to the synchronization of cached data, that is, if the real data changes, you should clear the cache data in a timely manner to ensure that the cache does not use the wrong data. Example:


2.1 There are more scenarios for using caching. The simplest case is to cache in a field or temporary variable.

for (int i = 0; i < Gcmultirow.rowcount; i++) {     //do something;}


The above code is generally no problem, however, if the number of rows Gcmultirow is larger. When the RowCount property is slower, it needs to use caching for performance optimizations.

int rowCount = gcmultirow.rowcount;for (int i = 0; i < RowCount; i++) {   //do something;}


2.2 Using object pooling is also a common caching scheme, a little more complicated than using field or temporary variables. For example, in MultiRow, drawing edges, drawing backgrounds, requires a lot of brush and pen. These GDI objects are created each time they are used, and are destroyed when they are exhausted. The process of creating and destroying is relatively slow. The scenario used by Gcmultirow is to create a gdipool. Essentially some dictionary, use color to do key. So only the first time you need to create, and then directly use the previously created. The following is the code for Gdipool:

public static class Gdipool {     dictionary<color, Brush > _cachebrush = new Dictionary<color, brush> (); 
  
   dictionary<color, pen> _cachepen = new Dictionary<color, pen> ();     public static pen Getpen (color color)    {        pen pen;        If_cachepen.trygetvalue (color, out pen))        {            return pen;        }        Pen = new Pen (color);       _cachepen.add (color, pen);        return pen;    }
  

2.3 Lazy Construction
Sometimes, some object creation takes a long time. This object may not be used in all scenarios. At this point, the use of Lai construction method can effectively improve performance. Example: Object A needs to create object B internally. Object B has a long construction time. General Practice:

public class a{public   b _b = new B ();}


In general, the construction speed of a is slowed down by the construction of object a while constructing object B. Optimization practices:

public class a{   private B _b;   Public b bproperty   {       get      {         if (_b = = null)         {             _b = new B ();         }         return _b;}}   }


After optimization, you do not need to create a B object when you construct a, you need to construct a B object only when you need to use it.


2.4 Optimization algorithm optimization algorithm can effectively improve the performance of specific operations, the use of an algorithm should understand the application of the algorithm, the best situation and the worst case. Taking Gcmultirow as an example, the first multirow sorting algorithm uses a classical fast sorting algorithm. This does not seem to be a problem, but for tabular software, the user's usual operation is to sort the ordered tables, such as switching between sequential and reverse order. The worst-case scenario for a classic fast-sorting algorithm is basically an orderly one. So the classic fast sorting algorithm is not suitable for multirow. Finally, the problem is solved by the modified sorting algorithm. The improved fast sorting algorithm uses 3 midpoints instead of a midpoint of the classic fast-track algorithm. Each interchange is selected from 3 midpoint. In this way, the chaotic sequence and the basic order of the situation are not the worst case of the algorithm, thus optimizing the performance.


2.5 Understanding the data structures provided by the framework we are working on the. NET Framework platform, which has a lot of data structures ready to work. We should understand these data structures and improve the performance of our programs:
Example:
2.5.1 string plus operator VS StringBuilder: The manipulation of strings is one of the basic operations we often encounter. We often write such code as String str = str1 + str2. There is no problem with this operation when the string of operations is very small. But if you do a lot of things (such as the save/load of a text file, the render of ASP. NET), this can lead to serious performance problems. At this point, we should use StringBuilder instead of the string add operation.

2.5.2 Dictionary VS list Dictionary and list are two of the most common collection classes. Choosing the right collection class can greatly improve the performance of your program. In order to make the right choice, we should be more aware of the performance of the various operations of dictionary and list. 2.5.3TryGetValue for the dictionary value, the more straightforward way is the following code:

if (_dic. Containkey ("key") {    return _dic\["key" \];}


When a large number of values are required, such an extraction can lead to performance problems. The optimization method is as follows:

Object Value;if (_dic. TryGetValue ("Key", out value)) {    return value;}

Using TryGetValue can improve performance by a factor of contain and then taking the value first.


2.5.4 Choose the right key for dictionary. The performance of dictionary is greatly dependent on the performance of the Equals and GetHashCode two methods of the object that makes the key. If you can, use int to do key performance best. If it is a custom class to do key, it is best to guarantee the following two points: 1. The GetHashCode repetition rate of different objects is low. 2. The GetHashCode and Equals methods are immediately simple and efficient.

The 2.5.5 list's sort and binarysearch performance is good, and it is recommended to use it directly, rather than rewriting it, if it meets the functional requirements.

list<int> list = new list<int>{3, ten, 15};list. BinarySearch (10); For the value that exists, the result is 1list. BinarySearch (8); For non-existent values, a negative number is used to represent the position, such as Find 8 o'clock, the result is-2, the lookup 0 results is-1, and the 100 result is-4.

Copy Code

2.6 Increase response time by asynchronous
2.6.1 Multi-Threading
Some operations do take a long time, and if the user's actions are stuck during this time, the user experience will be poor. Sometimes, using multithreading techniques can solve this problem: Calculatorengine initializes all function when constructing. Because of the more function, the initialization time will be longer. This is the use of multi-threading technology, in the work thread to do the initialization of function, it does not affect the main thread to quickly respond to the user's other operations. The code is as follows:

Public Calcparser () {   if (_functions = = null)   {       lock (_obtainfunctionlocker)       {           if (_functions = = NULL)           {               System.Threading.ThreadPool.QueueUserWorkItem ((s) =                   = {if (_functions = = null)                   {                       Lock (_obtainfunctionlocker)                       {                           if (_functions = = null)                           {                               _functions = Ensurefunctions ();}}}               );       }}   }}


The slower operation here is the Ensurefunctions function, which is executed in another thread and does not affect the response of the main thread. Of course, the use of multithreading is a more difficult scenario, you need to take full account of cross-thread access and deadlock problems.

2.6.2 Plus delay time
When Gcmultirow implements the AutoFilter function, it uses a scenario similar to deferred execution to increase the response speed. The function of AutoFilter is that the user updates the filtered results according to the user's input during the input process. When the amount of data is large, a filter takes a long time and affects the user's continuous input. Using multiple lines can be a good solution, but using multithreading can increase the complexity of your program. The solution for MultiRow is to wait 0.3 seconds instead of starting the filter immediately when the user's keyboard input message is received. If the user is in continuous input, it will receive the keyboard message again within 0.3 seconds, and then wait 0.3 seconds. Filter is not triggered until there is no new keyboard message for 0.3 seconds in a row. This ensures fast response to user input.

2.6.3 Application.idle Events
In Gcmultirow's designer, the disable/enable State of the toolbar button is often refreshed based on the current state. A refresh takes a long time. If the user continuously input will have the feeling of lag, affect the user experience. The optimization scheme of Gcmultirow is the Application.idle event of the hanging system. This event is triggered when the system is idle. Receiving this event indicates that the user has completed a continuous input at this time, you can calmly refresh the state of the button.

2.6.4 Invalidate, BeginInvoke. The Postevent platform itself also provides some asynchronous scenarios.
For example, in the case of WinForm, when an area is redrawn, it is generally not applicable to refresh but invalidate, which triggers an asynchronous refresh. You can invalidate multiple times before triggering. Begininvoke,postmessage can also trigger asynchronous behavior.

2.7 Understanding Platform Features
such as WPF's DP DP is very slow relative to the CLR property, including get and set are very slow, and the general texture on get faster set is relatively slow. If a DP needs to be read multiple times, it is recommended that the CLR property do the cache.

2.8 progress bar to improve user experience
Sometimes, the above mentioned solutions have no way to quickly respond to user action, progress bar, always turn the circle of pictures, suggestive text such as "Your operation may take a long time please wait patiently". Can improve the user experience. Can be considered as a final solution.


There are many development tools written in C # that are worth mentioning ComponentOne Studio Enterprise, a focus on enterprise applications. NET full-featured control package that supports multiple platforms such as WinForms, WPF, UWP, and ASP. To help deliver rich desktop, web, and mobile enterprise applications in advance while reducing costs.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.