1. Explicitly registered Evenhandler to explicitly unregister to avoid memory leaks
An event that registers a member method with an object causes the latter to hold a reference to the former. The former is not garbage collected until the event is logged off.
private void Form1_Load () { ... Register Event Commandremotingcontext.cmdchanged + = new Recivercmdstatechangedeventhandler (this. commandremotingcontext_cmdchanged); ......} private void form1_fromclosed () { ... Release the event commandremotingcontext.cmdchanged-= new Recivercmdstatechangedeventhandler (this) when the form is closed. commandremotingcontext_cmdchanged); ......}
Memory leak issues caused by an event:
- Object A subscribes to events in object B
- Object A has a life span far greater than object B
- Object A does not have time to unsubscribe from Object B
- Eventually causing object B to fail to release
2. Control-bound data source bulk operations should avoid automatic refresh
3. Reduce the number of communication between client and server
- WebService calls are not as small as possible, and the amount of data being transmitted can be considered split into multiple invocations
- For short WebService calls, you should merge as much as possible to reduce the number of interactions
Multiple calls to the same WS txtcompanyname.text=scpubfunctionclient.publicwscal<string> ("Fortest", " Getcompanynamebyid "," 0001 "); Txtcompanyinnername.text=scpubfunctionclient.publicwscal<string> ("Fortest", "GetCompanyInnerNameByID", " 0001 ");//merge adjacent ws string[] result=scpubfunctionclient.publicwscal<string> (" Fortest "," Getcompanynameandinnernamebyid "," 0001 "); txtcompanyname.text=result[0];txtcompanyinnername.text= result[1];
4. Reduce the number of communication between client and server
If not necessary, try to avoid repeated calls to WebService in the loop body
The loop calls the same WS list<person> Persons;......foreach (String PersonID in Personids) {Person=hrpubwsclient.getperson (PersonID);p ersons. ADD (person);} Merging ws list<person> persons;......persons =hrpubwsclient.getpersonlist (personids);
5, the use of generics to avoid boxing, unpacking operations (reduce garbage collection pressure)
6. String manipulation:
C # string manipulation--Reduce garbage collection pressure
7. Use constants to avoid creating objects
8. Avoid unnecessary throwing exceptions
C # exception handling (Catch Throw) IL analysis
9. Delete multiple elements using RemoveAll rather than removeat
- When you delete multiple elements of a collection (such as list) using the RemoveAll method, only one resize operation is performed on the internal array of the list, which is significantly more efficient than the loop call RemoveAt.
list<string> lst = new List<string> {"1", "2", "3", "1", "2", "4"};//Not recommended: for (int i = LST.) Count-1; I >= 0; i--) { if (lst[i] = = "1" | | lst[i] = = "2") { lst. RemoveAt (i); }} Recommendation: LST. RemoveAll (s = = s = = "1" | | s = = "2");
10. C # DataSet performance Best Practices
11. Reflection and dynamic binding--Reduce CPU consumption
- The reflection technique converts static bindings during compilation to dynamic bindings that are deferred until run time.
- C # mainly supports 5 kinds of dynamic creation of objects (time consumption from the network, and I measured the gap is very large, the specific test see below):
How to create objects dynamically
|
With direct Create
|
1.type.invokemember
|
40 times times more slowly
|
2.contructorinfo.invoke
|
40 times times more slowly
|
3.activator.createinstance (Type)
|
7 times Times slower
|
4.activator.createinstance (AssemblyName, TypeName)
|
1000 times times more slowly
|
5.assembly.createinstance (TypeName)
|
40 times times more slowly |
- The use of reflection and dynamic binding should be avoided as much as possible, and if necessary, follow these guidelines:
1. Transforming dynamic bindings to early binding using interface invocation (Direct call)
2. Dynamically create objects using the Activator.CreateInstance (Type) method
3. Use the typeof operator instead of the GetType call
Small bet
The time to create an instance record by looping is as follows:
Loading the assembly, getting the type at the outside time of the loop is as follows (at which time the difference in creation is quite large):
The code is as follows:
public void Testcreateinstance () {Stopwatch watch1 = new Stopwatch (); var asmb = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); int num = 100000; Watch1. Start (); for (int i = 0; i < num; i++) {//var ASMB = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); Activator.CreateInstance (type); } watch1. Stop (); Label1. Text = "Activator.CreateInstance (type Type) Time:" + watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {activator.createinstance ("reflectiveclasslibrary", "Reflectiv Eclasslibrary.testclass "); } watch1. Stop (); Label2. Text = "Activator.CreateInstance (string assemblyname,string TypeName) Time: "+ watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {//var ASMB = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Loads the assembly ASMB. CreateInstance ("TestClass"); } watch1. Stop (); Label3. Text = "assembly. CreateInstance (String typeName) Time: "+ watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {//var ASMB = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); Object obj = type. InvokeMember (NULL, BindingFlags.Public | BindingFlags.Instance | Bindingflags.createinstance, NULL, NULL, NULL); } watch1. Stop (); Label4. Text = "Type.invokeMember (string name, BindingFlags invokeattr, Binder binder, Object target, object[] args) Time: "+ watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {//var ASMB = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); ConstructorInfo ConstructorInfo = type. GetConstructors () [0]; Constructorinfo.invoke (NULL); } watch1. Stop (); Label5. Text = "Contructorinfo.invoke (object[] parameters) Time:" + watch1. Elapsedmilliseconds + "MS"; }
Loading the assembly, getting the type in the loop internal time is as follows (at this point the difference in the creation of time-consuming gap is relatively small):
The code is as follows:
public void Testcreateinstance () {Stopwatch watch1 = new Stopwatch (); var asmb = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); int num = 100000; Watch1. Start (); for (int i = 0; i < num; i++) {var asmb = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); Activator.CreateInstance (type); } watch1. Stop (); Label1. Text = "Activator.CreateInstance (type Type) Time:" + watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {activator.createinstance ("reflectiveclasslibrary", "Reflectiv Eclasslibrary.testclass "); } watch1. Stop (); Label2. Text = "Activator.CreateInstance (string assemblyname,string TypeName) Time: "+ watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {var asmb = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Loads the assembly ASMB. CreateInstance ("TestClass"); } watch1. Stop (); Label3. Text = "assembly. CreateInstance (String typeName) Time: "+ watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {var asmb = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); Object obj = type. InvokeMember (NULL, BindingFlags.Public | BindingFlags.Instance | Bindingflags.createinstance, NULL, NULL, NULL); } watch1. Stop (); Label4. Text = "Type.InvokeMember(String name, BindingFlags invokeattr, Binder binder, Object target, object[] args) Time: "+ watch1. Elapsedmilliseconds + "MS"; Watch1. Reset (); Watch1. Start (); for (int i = 0; i < num; i++) {var asmb = Assembly.LoadFrom ("ReflectiveClassLibrary.dll"); Type type = ASMB. GetType ("Reflectiveclasslibrary.testclass"); ConstructorInfo ConstructorInfo = type. GetConstructors () [0]; Constructorinfo.invoke (NULL); } watch1. Stop (); Label5. Text = "Contructorinfo.invoke (object[] parameters) Time:" + watch1. Elapsedmilliseconds + "MS"; }
The test code is as follows:C # Reflection test Demo
12. Serialization and deserialization
- Protobuf is more efficient than XML, binary serialization, and supports a large number of data
- The size of the PROTOBUF serialization is 1/20 of the JSON 1/10,xml format, which is a binary serialized 1/10
C # serialization
C # protobuf-net serialization
13. Data compression
In order to reduce the amount of data transferred from the client to the server, it is recommended to compress the data.
Common data compression: C # file stream compression decompression
14.
C # performance Optimization best Practices