A garbage collection
Garbage collection object the liberation of the manual management work to improve the robustness of the program, but possible side effect is that the code created for the object to become free.
As the high cost of garbage collection, so C # application development a basic principle to follow is to avoid unnecessary object creation. The following lists some common situations.
1.1.1 to avoid the cycle of creating objects ★
If the object does not change state with every cycle, then repeated in a loop to create the object will lead to performance loss. Efficient approach is to create an object out of that cycle.
1.1.2 the need to create an object logic branch
If the object only in some logical branch Caibei used, it should only be created in the object logic branch.
1.1.3 to avoid creating an object using the constant
Program should not appear as new Decimal (0) code like this will lead to frequent creation and recovery of small objects, the correct way is to use Decimal.Zero constant. We have to design their own classes, they can learn the design techniques applied to a similar scene.
If the class contains a destructor, the object will be created to add Finalize queue object reference, to ensure that when the object can not reach, you can still call to Finalize method. Garbage collector during operation, will launch a low-priority thread to handle the queue. In contrast, the destructor of the object is not no such consumption. If the destructor is empty, this consumption would be pointless, would only result in performance degradation! Therefore, do not use empty destructor.
Zai reality, the many companies that had in the destructor of Bao Han handling code, but became Delete various Yuan Yin commented out or lost, Zhi Liu Xia a shell, Ci Shi Ying Zhu Yi Ba destructor delete itself Zhushidiaohuo .
Garbage collection hosted within a matter of fact only supports the recovery of other non-managed resources, such as Window GDI handles or database connections, in the destructor to release these resources have a big problem. Because the garbage collection depends on the internal tensions, although the database connection may have been the depleted, but if the memory is still enough supply, garbage collection will not run.
To prevent objects Dispose method is not called to happen, generally also provide a destructor, the release of processing resources between the two calls a public method. Meanwhile, Dispose method should call System.GC.SuppressFinalize (this), told the garbage collector will no longer deal with Finalize methods.
2 String operations
String is the same type, use the + operator to create a connection string will cause a new string. If the string is not a fixed number of connections, such as in a loop, you should use the string concatenation StringBuilder class to do the work. As an internal StringBuilder StringBuffer, join operations will not always allocate a new string space. Only when the connection string exceeds Buffer size, Buffer only apply for a new space. Typical code:
StringBuilder sb = new StringBuilder (256);
for (int i = 0; i <Results.Count; i + +)
sb.Append (Results [i]);
If the connection frequency is fixed and only a few times, this time should be directly connected with the + sign to keep procedures simple and easy to read. In fact, the compiler optimization has been done will be based on the number of calls plus the number of different parameters of String.Concat method. For example: String str = str1 + str2 + str3 + str4;
Will be compiled into String.Concat (str1, str2, str3, str4). This method will calculate the total internal length of String, allocation only once, and not, as commonly assumed distribution as three. As an empirical value, when the string concatenation operator for more than 10 times, you should use StringBuilder.
Here is a detail should be noted: StringBuilder internal Buffer default value 16, this value is too small. By the use of StringBuilder scene, Buffer certainly be re-allocated. Experience tends to be used as a Buffer of the initial value of 256. Of course, if we can calculate the final generated string length, then this value should be set according to the initial value of Buffer. Use new StringBuilder (256) will set the initial length of Buffer 256.
For example, bool.Parse method itself is case insensitive, and call not to call the ToLower method.
Another very common scenario is a string comparison. Efficient approach is to use the Compare method, this method can be done relatively neglected case, and will not create a new string.
Another is to use HashTable time, and sometimes can not guarantee whether the case passed key as expected, will tend to cast key to uppercase or lowercase method. In fact there are different structural forms HashTable, fully support the use of ignore case of the key: new HashTable (StringComparer.OrdinalIgnoreCase).
Length property of the String object compared with the 0 is the fastest way: if (str.Length == 0) followed by constant or the empty string with String.Empty more: if (str == String.Empty) or if (str = = "")
Note: C # assembly at compile time will be declared for all string constants into the retention pond (intern pool), the constant will not repeat the same distribution.
Thread synchronization is the preparation of multi-threaded program needs to first consider the issue. C # for the synchronization provides Monitor, Mutex, AutoResetEvent and ManualResetEvent object to the critical areas were packed Win32, mutex object and event object based on these types of synchronization mechanisms. C # also provides a lock statement, easy to use, the compiler will automatically generate the appropriate Monitor.Enter and Monitor.Exit call.
3.1.1 Synchronization Granularity
Size may be the method of synchronization, the method can also be a piece of code. For the method specified MethodImplOptions.Synchronized property will be marked on the method of synchronization. For example:
public static SerialManagerGetInstance ()
if (instance == null)
instance = new SerialManager ();
Typically, the scope should be reduced simultaneously, the system for better performance. Simply mark the whole method of synchronization is not a good idea, unless it can determine the method needed for each code protected by synchronization.
3.1.2 Synchronization Strategy
Use lock to synchronize, synchronization objects can choose Type, this special construction or purpose for the synchronization of the member variable.
Avoid locking Type
Lock Type object will affect all the AppDomain in the same process all instances of that type, which may not only cause serious performance problems may also lead to some unexpected behavior. This is a very good habit. Even for a type that contains only static methods should also be an additional member to construct a static variable, so that this member variable as a lock object.
Avoid locking this
Lock this will affect all the methods of the instance. Suppose the object obj are two methods A and B, which A method of using the lock (this) on the way in a piece of code to set synchronization protection. Now, for some reason, B methods have begun to use the lock (this) to set the synchronization protected and may order a completely different purpose. This, A method was disrupted, their behavior may be unpredictable. So, as a good habit, it is recommended to avoid using lock (this) in this way.
Specially constructed for the purpose of using the synchronization member variables
This is the recommended approach. Way an object is the new object, the object is only used for synchronization purposes.
If there are multiple methods need to be synchronized, and have different purposes, it would be possible to establish that these were members of several variables simultaneously.
3.1.4 set of synchronization
/ / Creates andinitializes a new ArrayList
ArrayList myAL = new ArrayList ();
/ / Creates asynchronized wrapper around the ArrayList
ArrayList mySyncdAL = ArrayList.Synchronized (myAL);
Synchronized method call will return a guarantee that all operations are thread-safe in the same collection object. Consider mySyncdAL  = mySyncdAL  + "test" the statement, read and write to use a total of two locks. Generally speaking, efficiency is not high. Recommended SyncRoot property, can do more precise control.
Access NameDataSlot of Thread.GetData and Thread.SetData method requires thread synchronization, involves two locks: one LocalDataStore.SetData methods need to AppDomain level locking, and the other is ThreadNative.GetDomainLocalStore method requires a lock in the Process. If some of the underlying infrastructure services used NameDataSlot, will cause the system to serious scalability issues.
Circumvent this problem is to use ThreadStatic variable. Examples are as follows:
public sealed class InvokeContext
private static InvokeContext current;
private Hashtable maps = new Hashtable ();
3.3.1 Create an object using the Double Check Technology
internal IDictionary KeyTable
if (this. _keyTable == null)
lock (base. _lock)
if (this. _keyTable == null)
this. _keyTable = new Hashtable ();
return this. _keyTable;
Create singleton objects is a common programming situation. After the general statement in the lock will directly create objects, but that is not safe enough. Because the lock object lock before, may already have multiple threads into the first if statement. If you do not add the second if statement, the single case of the object will be repeated to create a new instance of the replacement off the old instance. If you have a single case of object data does not allow the destruction or other reasons, you should consider using DoubleCheck technology.
Note that: the method of local variables rather than from the heap allocation from the stack, so C # will not be cleared to do the work. If you use the unassigned local variable, which will alarm during compilation. Do not have the impression that while all members of the class action variables are assigned to do two completely different mechanism!
4.2 ValueType and ReferenceType
4.2.1 in order to pass a value type parameter by reference
Value type from the call stack allocation, reference types allocated from the managed heap. When the value type used as a method parameter, the default parameter values will be replicated, this type of distribution to offset the value of efficiency advantages. As a basic skills to pass a value type parameters by reference can improve performance.
4.2.2 ValueType Equals method to provide
public struct Rectangle
public double Length;
public double Breadth;
public override bool Equals (objectob)
if (ob is Rectangle)
return Equels ((Rectangle) ob))
private bool Equals (Rectangle rect)
return this. Length == rect.Length & & this. Breadth == rect.Breach;
Avoid boxing and unboxing 4.2.3
The case of a regular set of type in use. For example:
ArrayList al = new ArrayList ();
for (int i = 0; i <1000; i + +)
al.Add (i); / / Implicitly boxed because Add () takes an object
int f = (int) al ; / / The element is unboxed
Exception is typical of modern languages. Check the error code with the traditional way of comparison, the exception is mandatory (not dependent on whether the preparation of examination error code forgotten the code), strong type, and with a wealth of unusual information (such as call stack).
Exception handling on the most important principle is: Do not eat the exception. This issue has nothing to do with performance, but for the preparation of robust and easy debugging of the program is very important. This principle another way, is not to capture those you can not handle the exception.
Eating disorders are a very bad habit, because you eliminate the clues to solve the problem. Once the error would be very difficult to locate the problem. In addition to this unusual way of eating completely, the only exception of information written to a log file but does not do more to address the practice is also wrong.
Although some of the code throws an exception, but the exception message eaten.
Disclosure of detailed information for the exception is the duty of the programmer. If you can not preserve the original meaning of the exception under the premise of additional information richer and more personalized content, then let the original exception should be much better display of information directly. Do not eat the exception.
Exception is thrown and caught exceptions are consuming relatively large operations, where possible, should be thrown through the improvement of program logic to avoid unnecessary unnecessary exceptions. Related to this was a tendency to control the use of exception handling logic. Despite the very small number of cases, this may be a more elegant solution, but ordinarily should be avoided.
If it is abnormal for packaging purposes (ie to add more information after the package into a new exception), then it is reasonable. But there are a lot of code, catch the exception does not do any processing on the re-thrown, it will unnecessarily increase the time to catch the exception and throw exception of consumption, have hurt performance.
Reflection is a very basic technology, it will compile a static during the delay bound to run into during the dynamic binding. In many scenarios (especially type frame design), access to flexible and easily expandable architecture. But the problem is caused as compared with the static binding and dynamic binding properties would cause greater harm.
typecomparison: type of judge, including the two operators is and typeof and GetType on the object instance is called. This is the most light consumption, can be optimized without the need to consider the issue. Note typeof operator than the GetType method on the object instance to be fast, as long as possible, priority typeof operator.
memberenumeration: members of the enumeration, used to access the reflex-related metadata information such as Assembly.GetModule, Module.GetType, Type object IsInterface, IsPublic, GetMethod, GetMethods, GetProperty, GetProperties, GetConstructor calls, etc.. Although the CLR metadata will be cached, but some method call consumption is still very large, but not such a high frequency of method calls, so the overall look at the performance loss is moderate.
memberinvocation: members of the call, including the dynamic creation of objects and the dynamic invocation object, there are mainly Activator.CreateInstance, Type.InvokeMember so.
3. Activator.CreateInstance (Type)
4. Activator.CreateInstance (assemblyName, typeName)
5. Assembly.CreateInstance (typeName)
3 is the fastest way, and the Direct Create the differences within an order of magnitude, about 7 times slower level. Otherwise, at least 40 times more than the slowest mode 4, three orders of magnitude slower.
Compile method call into the early binding and operation of the dynamic binding of two, known as the Early-Bound Invocation and Late-Bound Invocation. Early-Bound Invocation can be broken down into Direct-call, Interface-call and the Delegate-call. Late-Bound Invocation mainly Type.InvokeMember and MethodBase.Invoke, can also use LCG (Lightweight Code Generation) technology to generate IL code dynamically.
View from the test results, compared with Direct Call, Type.InvokeMember to nearly three orders of magnitude slower; MethodBase.Invoke Although Type.InvokeMember to three times faster than, but still slower than the Direct Call 270 times. Shows the performance of dynamic method calls is very low. Our advice: unless you meet specific needs, do not use!
1. If possible, avoid using reflection and dynamic binding
2. Ways to use interface to call the transformation of dynamic binding early binding
3. Use Activator.CreateInstance (Type) method to create objects dynamically
4. Instead of using the typeof operator call GetType
1. Type in the case has received, but the use Assembly.CreateInstance (type.FullName)
Here describe some scenarios, you can improve performance of the basic code skills. On the critical path in the code for this type of optimization is meaningful. Common code can not do requests, but develop a good habit is meaningful.
Conditions can be used to judge the loop local variables recorded. Local variables are optimized by the compiler to use registers to direct, as opposed to normal from the heap or stack allocation of variable speed. If the visit is a complex calculation of property would enhance the effect will be more apparent. for (int i = 0, j = collection.GetIndexOf (item); i <j; i + +)
Be stated that: The wording of the collection class for Count property CLR does not make sense, because the compiler has done in this way, a special optimization.
After assembling good is very inefficient to delete the wording. Some methods of its cycle length is 1 in most cases, such an approach is even more obvious inefficient:
public static string ToString (MetadataKey entityKey)
string str = "";
object  vals = entityKey.values;
for (int i = 0; i <vals.Length; i + +)
str + = "," + vals [i].