Vector memory mechanism and Performance Analysis

Source: Internet
Author: User

Some good company campus recruitment process (including the test, interview), often involves the use of Vector in STL (mainly the test) and its performance (interview) analysis. Today I read related articles and wrote a few small test programs to run. In summary, we hope to help people who need it.

A vector is simply a dynamic array with a pointer pointing to a continuous memory space. When the space is insufficient to hold data, another larger space will be automatically applied, then copy the original data and then release the original space. when the data is released or deleted, the storage space will not be released, but the data in it will only be cleared. Next, I will talk about this in detail.

Note: The related programs in this article are all tested in Windows 7 + vs2008.

I. First, let's look at the memory allocation mechanism of vector:

 

vector<int> arr;ofstream wf("1.txt");for(int i=0;i<100;++i){arr.push_back(i);wf<<"capacity="<<arr.capacity()<<",size="<<arr.size()<<end;}wf.close();

Capacity () returns the size of the space actually applied for in the buffer of the current vector object (the memory space maintained for the vector is called the buffer), while size () the returned value is the number of data stored in the current Object Buffer. capacity is always greater than or equal to size. When the size and capacity are equal, the vector will be expanded.

 

Let's take a look at the data in 1.txt:

Capacity = 1, size = 1
Capacity = 2, size = 2
Capacity = 3, size = 3
Capacity = 4, size = 4
Capacity = 6, size = 5
Capacity = 6, size = 6
Capacity = 9, size = 7
Capacity = 9, size = 8
Capacity = 9, size = 9
Capacity = 13, size = 10
Capacity = 13, size = 11
Capacity = 13, size = 12
Capacity = 13, size = 13
Capacity = 19, size = 14
Capacity = 19, size = 15
Capacity = 19, size = 16
Capacity = 19, size = 17
Capacity = 19, size = 18
Capacity = 19, size = 19
Capacity = 28, size = 20
Capacity = 28, size = 21
Capacity = 28, size = 22
Capacity = 28, size = 23
Capacity = 28, size = 24
Capacity = 28, size = 25
Capacity = 28, size = 26
Capacity = 28, size = 27
Capacity = 28, size = 28
Capacity = 42, size = 29
Capacity = 42, size = 30
Capacity = 42, size = 31
Capacity = 42, size = 32
Capacity = 42, size = 33
Capacity = 42, size = 34
Capacity = 42, size = 35
Capacity = 42, size = 36
Capacity = 42, size = 37
Capacity = 42, size = 38
Capacity = 42, size = 39
Capacity = 42, size = 40
Capacity = 42, size = 41
Capacity = 42, size = 42
Capacity = 63, size = 43
Capacity = 63, size = 44
Capacity = 63, size = 45
Capacity = 63, size = 46
Capacity = 63, size = 47
Capacity = 63, size = 48
Capacity = 63, size = 49
Capacity = 63, size = 50
Capacity = 63, size = 51
Capacity = 63, size = 52
Capacity = 63, size = 53
Capacity = 63, size = 54
Capacity = 63, size = 55
Capacity = 63, size = 56
Capacity = 63, size = 57
Capacity = 63, size = 58
Capacity = 63, size = 59
Capacity = 63, size = 60
Capacity = 63, size = 61
Capacity = 63, size = 62
Capacity = 63, size = 63
Capacity = 94, size = 64
Capacity = 94, size = 65
Capacity = 94, size = 66
Capacity = 94, size = 67
Capacity = 94, size = 68
Capacity = 94, size = 69
Capacity = 94, size = 70
Capacity = 94, size = 71
Capacity = 94, size = 72
Capacity = 94, size = 73
Capacity = 94, size = 74
Capacity = 94, size = 75
Capacity = 94, size = 76
Capacity = 94, size = 77
Capacity = 94, size = 78
Capacity = 94, size = 79
Capacity = 94, size = 80
Capacity = 94, size = 81
Capacity = 94, size = 82
Capacity = 94, size = 83
Capacity = 94, size = 84
Capacity = 94, size = 85
Capacity = 94, size = 86
Capacity = 94, size = 87
Capacity = 94, size = 88
Capacity = 94, size = 89
Capacity = 94, size = 90
Capacity = 94, size = 91
Capacity = 94, size = 92
Capacity = 94, size = 93
Capacity = 94, size = 94
Capacity = 141, size = 95
Capacity = 141, size = 96
Capacity = 141, size = 97
Capacity = 141, size = 98
Capacity = 141, size = 99
Capacity = 141, size = 100

There is a lot of data, and the extraction is like this:

Capacity = 1
Capacity = 2
Capacity = 3
Capacity = 4
Capacity = 6
Capacity = 9
Capacity = 13
Capacity = 19
Capacity = 28
Capacity = 42
Capacity = 63
Capacity = 94
Capacity = 141

Do you see the rule? Yes, that is, each expansion increases the current space by 50% (except for the first time );

9 + 9/2 = 13; 13 + 13/2 = 19; 19 + 19/2 = 28 ......

In fact, we can see the source code of STL, specifically under the compiler directory you mentioned to install, for example, my vs2008 is under the installation directory \ Vc \ include. You can also right-click # include <vector> In vs to open it. Of course, the STL source code on Windows is P. j. written by plauger (PS: a doctor from cool B, Baidu you know), we all say that the readability is very poor. I also think that we should look at STL source code in GCC for these cainiao.

\ Vc \ include \ vector is expanded as follows:

 

If (_ COUNT = 0) // here we make a judgment, but we do not do anything. I don't know why ???????; Else if (max_size ()-size () <_ count) // The maximum capacity that the compiler can apply for cannot be mounted, and an exception _ Throw (length_error, "vector <t> too long"); _ xlen (); // result too longelse if (_ capacity <size () + _ count) // The current space is insufficient, need to resize {// not enough room, reallocate_capacity = max_size ()-_ capacity/2 <_ capacity? 0: _ capacity + _ capacity/2; // try to grow by 50%, resize 50% if (_ capacity <size () + _ count) // after resizing 50%, the capacity is equal to the current number of data plus the number of new data _ capacity = size () + _ count; pointer _ newvec = This-> _ alval. allocate (_ capacity); // apply for a new space pointer _ PTR = _ newvec; _ try_begin_ptr = _ umove (_ myfirst, _ vec_iter_base (_ Where), _ newvec ); // copy prefix // copy the original data to the new memory _ PTR = _ ucopy (_ first, _ last, _ PTR ); // Add new stuff // copy the new data to the end of the new memory _ umove (_ vec_iter_base (_ Where), _ mylast, _ PTR ); // copy suffix_catch_all_destroy (_ newvec, _ PTR); this-> _ alval. deallocate (_ newvec, _ capacity); // release the originally applied memory _ reraise; _ catch_end

Right, that is, each expansion of 50%. The buffer size does not change when the data in the container is deleted, but only the data is clear. The vector will automatically release the buffer only when the Destructor is called.

 

Let's look at its destructor code:

 

~vector(){// destroy the object_Tidy();}
Void _ tidy () {// free all storageif (_ myfirst! = 0) {// something to free, destroy and deallocate it # If _ Hangzhou-> _ orphan_all (); # endif/* _ has_iterator_debugging */_ destroy (_ myfirst, _ mylast); // destroy every element in the vector. This-> _ alval. deallocate (_ myfirst, _ myend-_ myfirst); // release the buffer space} _ myfirst = 0, _ mylast = 0, _ myend = 0; // return all pointer values to zero}

So, can we force release the buffer zone as needed?

 

Ii. How to forcibly release the vector Buffer:

The answer is yes. Since space is released during the destructor, we can call the destructor in another way.

 

/// Method 1,
Vector <int> (). swap (ARR); // After switching // method 2, {vector <int> temp; // The temporary object is not initialized, and its buffer size is 0, no data arr. swap (temp); // exchange data with our object, and the ARR buffer is gone .} // Temporary variables will be destructed. Temp calls the vector destructor to release space.

Iii. How to improve performance:

 

For comparison, we use three methods to store 100 pieces of data into a vector: 1. Directly push_back () each time; 2. Use resize () to allocate 100 pieces of space in advance, then push_back; 3. Use reserve to allocate up to 100 buckets in advance. In msdn, the two functions are described as follows:

Reservereserves a minimum length of storage for a vector object, allocating space if necessary.

Resizespecifies a new size for a vector.

The usage during initialization seems similar here.

 

Clock_t start = clock (); For (INT num = 0; num <10000; ++ num) {vector <int> V1; For (INT I = 0; I <100; ++ I) v1.push _ back (I);} cout <"10000 times of direct push loop:" <clock ()-start <Endl; start = clock (); For (INT num = 0; num <10000; ++ num) {vector <int> V2; v2.resize (100); For (INT I = 0; I <100; ++ I) v2.push _ back (I) ;}cout <"when the default size is Resize and then the push cycle is performed for 10000 times:" <clock () -Start <Endl; Start = clock (); For (INT num = 0; num <10000; ++ num) {vector <int> V3; v3.reserve (100 ); for (INT I = 0; I <100; ++ I) v3.push _ back (I);} cout <"first reserve the default size and then push the cycle for 10000 times: "<clock ()-start <Endl;

Results are different.

 

Reserve only keeps a minimum space, while resize reallocates the buffer. The judgment and memory processing involved are many. Of course, the difference is not big because it is empty at first.

See the differences between the two: vector: Reserve and vector: resize.

It can be seen that it is necessary to preset the space size when the data quantity can be determined. Direct push_back frequent data movement is very time-consuming (of course, small data can be ignored ).

The complete code of the test program is as follows:

 

# Include "stdafx. H "# include" btree. H "# include <vector> # include <iostream> # include <windows. h> # include <fstream> # include <time. h> Using STD: ofstream; Using STD: cout; Using STD: Endl; Using STD: vector; int _ tmain (INT argc, _ tchar * argv []) {/************************************** * ******************************** // how to force a vector memory space is released * // by default, only the Destructor is released *//********************** ******************************** * ****************/Vector <int> arr; cout <"by default, capacity = "<arr. capacity () <Endl; arr. resize (1, 100,100); arr. reserve (50); arr. resize (50); cout <"now, capacity =" <arr. capacity () <Endl; vector <int>: iterator itor = arr. begin () + 10; arr. erase (ARR. begin (), itor); cout <"capacity =" <arr. capacity () <", size =" <arr. size () <Endl; // method 1, vector <int> (). swap (ARR); // forcibly release space // method 2, {vector <int> temp; arr. swap (temp);} // Temporary Variable Cout <"capacity =" <arr. capacity () <", size =" <arr. size () <Endl; clock_t start = clock (); For (INT num = 0; num <10000; ++ num) {vector <int> V1; for (INT I = 0; I <100; ++ I) v1.push _ back (I);} cout <"10000 times of direct push loop:" <clock () -Start <Endl; Start = clock (); For (INT num = 0; num <10000; ++ num) {vector <int> V2; v2.resize (100 ); for (INT I = 0; I <100; ++ I) v2.push _ back (I);} cout <"first resize the default size and then push the cycle for 10000 times: "<clock ()-start <Endl; Start = clo CK (); For (INT num = 0; num <10000; ++ num) {vector <int> V3; v3.reserve (100); For (INT I = 0; I <100; ++ I) v3.push _ back (I) ;}cout <"when the default size is reserve and then the push cycle is performed for 10000 times:" <clock () -Start <Endl; vector <int> V4; ofstream WF ("2.txt"); int nflag = v4.capacity (); For (INT I = 0; I <100; ++ I) {v4.push _ back (I); If (nflag! = V4.capacity () {nflag = v4.capacity (); cout <"new buffer size =" <nflag <Endl; WF <"capacity =" <nflag <Endl ;}} WF. close (); cout <"max_size =" <arr. max_size () <Endl; return 0 ;}

I have read some articles from my predecessors and have limited abilities. Thank you for your advice and mutual learning.

 

 

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.