. NET provides List objects to provide Scalable Data Storage. However, it is believed that many users can directly create a list object using the default constructor. However, this operation may cause some risks. As a result, Lis increases CPU loss and GC pressure during the expansion process, the severity of the problem depends on the actual application scenarios, if a large number of such operations exist in highly concurrent applications, the problem will become more serious.
First, you need to understand the list storage mechanism. If the size is not specified during initialization, an array with a size of 4 is allocated by default, when the value of the added information exceeds this value, the system will scale up by multiple times. The default rules are 4, 8, 16, 32 ...; during the process of capacity expansion, an array of the extended size will be built and the old data will be copied. Arraylist and list <t> actualCodeProbably as follows:
Public Virtual int add (object Value) {If (this. _ size = This. _ items. length) {This. ensurecapacity (this. _ SIZE + 1);} This. _ items [this. _ SIZE] = value; this. _ version ++; return this. _ SIZE ++;} private void ensurecapacity (INT min) {If (this. _ items. length <min) {int num = (this. _ items. length = 0 )? 4: (this. _ items. length * 2); If (Num <min) {num = min;} This. capacity = num ;}} Public Virtual int capacity {get {return this. _ items. length;} set {If (value! = This. _ items. length) {If (value <this. _ SIZE) {Throw new argumentoutofrangeexception ("value", environment. getresourcestring ("argumentoutofrange_smallcapacity");} If (value> 0) {object [] array = new object [value]; If (this. _ size> 0) {array. copy (this. _ items, 0, array, 0, this. _ SIZE) ;}; this. _ items = array; return;} This. _ items = new object [4] ;}}
The Code clearly shows that a new data group and replication exist during the expansion, so the problem arises. For a simple application scenario, the Data Query page returns the list, suppose there are 20 records on each page. When we add 20 objects when building the list by default, this list will face three expansion operations: 8, 16, 32. to test the situation, list the code of the two conditions respectively.
Static void test1 (object state) {for (INT I = 0; I <count; I ++) {var items = new list <testobj> (); for (int K = 0; k <20; k ++) {items. add (New testobj () ;}} static void Test2 (object state) {for (INT I = 0; I <count; I ++) {var items = new list <testobj> (20); For (int K = 0; k <20; k ++) {items. add (New testobj ());}}}
The operation of the above two methods is a good time difference, and the test time does not include GC loss, in the case of high concurrency, the performance loss caused by GC pressure is far more than that. In fact, most objects that can be resized and stored in. Net have this problem. In the face of these problems,. Net also reserves some constructor methods for the use of these classes to meet the actual situation faced by the application.
When you are writing. netProgramWhen you find performance problems, you can look at the. NET code. In fact, many situations are caused by your lack of understanding. The above is closely a timing test. In actual situations, we need to perform more tests to find out the cause. Memory and GC are often the killer of. NET performance.