In-depth study of STL deque containers

Source: Internet
Author: User

This document provides an in-depth analysis of STD: deque and provides a guiding ideology: when considering memory allocation and execution performance, Using STD: deque is better than STD: vector.

Introduction

This article thoroughly studies the STD: deque container. This article will discuss how to use deque better than vector in some cases. Read this articleArticleThen, the reader should be able to understand the different performance of deque and vector in memory allocation and performance in the Process of capacity growth. Since deque and vector are similar in usage, you can refer to the documentation of vector to introduce how to use STL containers.

DequeOverview

Deque and vector are both in the standard template library. deque is a dual-end queue, which is very similar to vector in the interface and can be directly replaced in many operations. If the reader has been able to effectively use the vector container, the following section provides deque member functions and operations for comparative reference.

DequeMember Functions

Function

Description

C. Assign (beg, end)

C. Assign (n, ELEM)

Assign the value of the data in the [beg; End) interval to C.

Assign a copy of n elem values to C.

C. At (idx)

Returns the data indicated by the index idx. If idx is out of bounds, out_of_range is thrown.

C. Back ()

Returns the last data and does not check whether the data exists.

C. Begin ()

Return the unique data of the iterator.

C. Clear ()

Remove all data from the container.

Deque <ELEM> C

Deque <ELEM> C1 (C2)

Deque <ELEM> C (n)

Deque <ELEM> C (n, ELEM)

Deque <ELEM> C (beg, end)

C .~ Deque <ELEM> ()

Create an empty deque.

Copy A deque.

Create a deque that contains N pieces of data, which are created by default.

Create a deque that contains n elem copies.

Create a deque in the [beg; End) interval.

Destroys all data and releases memory.

C. Empty ()

Determines whether the container is empty.

C. End ()

Point to the last data address in the iterator.

C. Erase (POS)

C. Erase (beg, end)

Delete the data at the POs position and return the location of the next data.

Delete the data in the [beg, end) interval and return the location of the next data.

C. Front ()

Return a data record.

Get_allocator

Returns a copy using the constructor.

C. insert (Pos, ELEM)

C. insert (Pos, N, ELEM)

C. insert (Pos, beg, end)

Insert an ELEM copy at the POs position and return the new data location.

Insert n ELEM data at the POs position. No return value.

Data inserted in the [beg, end) range at the POs position. No return value.

C. max_size ()

Returns the maximum number of data in the container.

C. pop_back ()

Delete the last data.

C. pop_front ()

Delete the header data.

C. push_back (ELEM)

Add a data entry to the end.

C. push_front (ELEM)

Insert a data entry in the header.

C. rbegin ()

Returns the first data of a reverse queue.

C. rend ()

Returns the next location of the last data in a reverse queue.

C. Resize (Num)

Specify the length of the queue again.

C. Size ()

Returns the actual number of data in the container.

C1.swap (C2)

Swap (C1, C2)

SWAps C1 and C2 elements.

Same as above.

DequeOperation

Function

Description

OPERATOR []

Returns a reference from a specified position in the container.

The above features are obviously similar to those of vector, so we will raise the following questions.

Question: IfDequeAndVectorWhich of the following is better when the same functions can be provided?

A: If you want to ask, use vector.

Or can you give an explanation?

I am very glad to ask you this question. Indeed, this is not an out-of-the-box question. In fact, I have explained this question in the C ++ standard. In section 23.1.1, there is a piece below:

Vector is a typical sequence method by default. For deque, It is a better choice to use insert/delete operations.

Interestingly, this article aims to thoroughly understand this sentence.

What is new?

Read the above two tables and you will find that two functions are added here for comparison with vector.

1. c. push_front (ELEM) -- insert a data in the header.

2. c. pop_front () -- delete the header data.

The call method is the same as C. push_back (ELEM) and C. pop_back (). These will tell us that deque is very useful in the future, and deque can add data before and after.

What is missing?

At the same time, you will also find that two functions are missing from the vector, and you will understand that deque does not need them.

1. Capacity () -- returns the current capacity of the vector.

2. Reserve () -- allocate space to a specified vector.

Here is the beginning of our real research. here we can see that deque and vector are completely different in managing internal storage. Deque is the memory allocated in large blocks, and a fixed amount of data is inserted each time. Vector allocates memory nearby (this may not be a bad thing ). However, we should note that when the memory added to the vector is large enough, the current memory is insufficient. The following experiment demonstrates that deque does not require capacity () and reserve.

Lab 1 -- Growing containers

Purpose

The purpose is to observe the differences between deque and vector in terms of capacity growth through experiments. Use graphs to illustrate their differences in memory allocation and execution efficiency.

Description

Testing of this experimentProgramIs to read text content from a file, each row as a data is inserted into the deque and vector using push_back, through reading the file multiple times to insert a large amount of data, the following class is used to test the content:

# Include <deque>

# Include <fstream>

# Include <string>

# Include <vector>

Static Enum Modes

{

Fm_invalid = 0,

Fm_vector,

Fm_deque

};

Class cvectordequetest

{

Public:

Cvectordequetest ();

Void readtestfile (const char * szfile, int imode)

{

Char buff [0 xFFFF] = {0 };

STD: ifstream infile;

Infile. Open (szfile );

While (! Infile. EOF ())

{

Infile. Getline (buff, sizeof (buff ));

If (imode = fm_vector)

M_vdata.push_back (buff );

Else if (imode = fm_deque)

M_ddata.push_back (buff );

}

Infile. Close ();

}

Virtual ~ Cvectordequetest ();

Protected:

STD: vector <STD: String> m_vdata;

STD: deque <STD: String> m_ddata;

};

Result

Platforms and conditions for testing program running:

CPU

1.8 GHz Pentium 4

Memory

1.50 GB

Operating System

W2K-SP4

Number of lines in the file

9874

Average number of letters per line

1755.85

Number of file reads

45

Total number of inserted data

444330

Use Windows Task Manager to record execution efficiency. The program uses the cduration class of Laurent guinnard. System resources are consumed, for example:

Note how the maximum value of memory is reached when the vector allocates memory. deque is like this. When inserting data, the memory increases linearly, first, if deque's memory allocation unit is recycled, there will be unexpected consequences. We hope its memory allocation looks the same as that of vector. Through the above test, we need further testing, assume that the memory allocated by deque is not continuous and must be released and withdrawn. We will add these assumptions to the subsequent tests, but first, let's analyze the experiment from the performance appearance.

How long does it take to allocate memory?

Pay attention to the following picture. When the vector does not insert data, it seeks to allocate more memory.


At the same time, we also noticed the time consumption of using push_back to insert a group of data. Note that each inserted group of data here represents 9874 strings, and the average length of each string is 1755.85.

Lab 2 --Vector: Reserve ()Resource

Purpose

The purpose of this experiment is to call reserve () before adding a large amount of data to the vector and compare it with deque to see how efficient their memory allocation and execution efficiency are?

Description

The tests in this experiment are basically the same as those in Experiment 1. In addition to adding the following line to the constructor of the test classCode:

M_vdata.reserve (1000000 );

Result

Platforms and conditions for testing program running:

CPU

1.8 GHz Pentium 4

Memory

1.50 GB

Operating System

W2K-SP4

Number of lines in the file

9874

Average number of letters per line

1755.85

Number of file reads

70

Total number of inserted data

691180

Use Windows Task Manager to record execution efficiency. The program uses the cduration class of Laurent guinnard. System resources are consumed, for example:

We noticed that the vector does not need to allocate unnecessary time to allocate memory, because we use reserve () the tested 691180 data records reserve sufficient memory space for each insert of a large amount of data. For the deque storage allocation assumption, observe the memory allocation graph and the previous graph in this test. We need to further quantify this test.

How can we improve the performance of memory allocation?

The following figure shows that the capacity increases as data increases:

When adding data, the efficiency of adding the capacity is basically the same in the execution of vector and deque. However, when inserting data, the vector consumes some sporadic time. See the following example:

The following table summarizes the time taken by vector and deque to insert 1755.85 pieces of data with an average length of 9874:

Vector

Deque

Mean

0.603724814 Sec

Maximum

0.738313000 Sec

Minimum

0.559959000 Sec

STD. Dev

0.037795736 Sec

6-sigma

0.226774416 Sec

Mean

0.588021114 Sec

Maximum

0.615617000 Sec

Minimum

0.567503000 Sec

STD. Dev

0.009907800 Sec

6-sigma

0.059446800 Sec

Lab 3 -- Memory reclaim

Purpose

In this experiment, we assume that the memory allocated by deque is not near, and it is difficult to recycle and perform quantitative testing and analysis.

Description

The code in Experiment 1 is used again in this experiment. To increase the efficiency of Data Execution, add a record to the call function, and perform the following operations:

For (xrun = 0; xrun <number_of_xruns; xrun ++)

{

DF = new cvectordequetest;

Elapsed_time = 0;

For (I = 0; I <number_of_runs * xrun; I ++)

{

Cout <"deque-Run" <I <"of" <

Number_of_runs * xrun <"...";

DF-> readtestfile ("F: \ huge.csv", df_deque );

Deque_data.push_back (datapoint ());

Deque_data.back (). time_to_read = DF-> getprocesstime ();

Elapsed_time + = deque_data.back (). time_to_read;

Deque_data.back (). elapsed_time = elapsed_time;

Cout <deque_data.back (). time_to_read <"seconds \ n ";

}

Vnelements. push_back (DF-> getdequesize ());

Cout <"\ n \ ndeleting ...";

Del_deque.start ();

Delete DF;

Del_deque.stop ();

Cout <del_deque.getduration ()/1000000.0 <"seconds. \ n ";

Vtimetodelete. push_back (del_deque.getduration ()/1000000.0 );

}

Result

This test is run on the same platform as the above two experiments. Except that the inserted data ranges from 9874 to 691180, it needs to be inserted 70 times, the following example shows how deque allocates memory when inserting data. deque inserts a string with an average length of 1755.85.

Although the actual consumption time is different from several curves, some curves are accurate to R2 = 95.15%. The given data points actually deviate from the statistical graph data in the following table:

Deque results

Mean

0.007089269 Sec

Maximum

11.02838496 Sec

Minimum

-15.25901667 Sec

STD. Dev

3.3803636 Sec

6-sigma

20.2821816 Sec

In the same case, it is very meaningful to compare the results of vector. The following figure compares the time consumed by the allocation of memory in the same case of vector and deque:

In this test, the data is R2 = 82.12%. This may be optimized through repeated operation of each vertex. In this case, the data points are properly labeled, and the data points actually deviate from the graph data in the following table:

Vector results

Mean

-0.007122715 Sec

Maximum

0.283452127 Sec

Minimum

-0.26724459 Sec

STD. Dev

0.144572356 Sec

6-sigma

0.867434136 Sec

Lab 4 --Vector: insert ()AndDeque: insert ()Comparison of execution features

Purpose

Deque advocates the use of insert () with a constant parameter (). But how can we compare it with vector: insert? The purpose of this experiment is to compare the working characteristics of vector: insert () and deque: insert.

Description

Inserting Data multiple times in the container may not meet your requirements here. Now you can use insert (), and the test code is basically the same as the experiment one, using insert () replace push_back () and use insert () for testing.

Result

When a constant is inserted to deque, we can see the comparison with vector.

Note that the timeline of the two images is different. This is to insert 61810 pieces of data into the container.

Lab 5 -- Read container Performance

Purpose

This experiment will test the performance of vector: At (), vector: operator [], deque: At () and deque: operator. OPERATOR [] is more efficient than at () because it does not perform boundary checks and compares vector and deque.

Description

In this experiment, 1000000 types of containers in the test are STD: string, and each string is 1024 in length, respectively () and operator [] to access the Container data and test the running time. This test is executed 50 times and the result of each execution is counted.

Result

We can see that the use of vector and deque to access the data in the container, their performance difference is very small, the performance difference between using operator [] and at () to access data is almost negligible, the following are the statistical results:

Vector: ()

Mean

1.177088125 Sec

Maximum

1.189580000 Sec

Minimum

1.168340000 Sec

STD. Dev

0.006495193 Sec

6-sigma

0.038971158 Sec

Deque: ()

Mean

1.182364375 Sec

Maximum

1.226860000 Sec

Minimum

1.161270000 Sec

STD. Dev

0.016362148 Sec

6-sigma

0.098172888 Sec

Vector: operator []

Mean

1.164221042 Sec

Maximum

1.192550000 Sec

Minimum

1.155690000 Sec

STD. Dev

0.007698520 Sec

6-sigma

0.046191120 Sec

Deque: operator []

Mean

1.181507292 Sec

Maximum

1.218540000 Sec

Minimum

1.162710000 Sec

STD. Dev

0.010275712 Sec

6-sigma

0.061654272 Sec

Conclusion

In this article, we cover a variety of different situations to choose whether we should use vector or deque. Let's summarize the test results and look at the following conclusions.

When calling large data volumesPush_back ()Remember to callVector: Reserve ().

In experiment 1, we studied how vector and deque insert data. Through these assumptions, we can see that the space allocated by deque is pre-allocated, and deque maintains a fixed growth rate. In the vector experiment, we consider that vecor: Reserve () should be called (). the example below demonstrates our assumption that calling reserve () when using a vector means that we can pre-allocate space, which is a default operation of vector.

When you allocate many memory units, remember to useDequeMemory recovery ratioVectorIt takes a lot of time.

In experiment 3, we discussed the differences between vector and deque in recycling non-adjacent memory blocks, respectively proving that the vector grows linearly when allocating memory, while the deque increases exponentially. Similarly, vector has more memory to recycle than deque. If you call push_back () cyclically, deque will obtain a large amount of memory, which is near. We found that the time consumed by memory allocation units is close to the time consumed by the vector.

If you plan to useInsert (), Or you needPop_front (), Then useDeque.

Since the vector does not provide the pop_front () function, it can be seen from the result of experiment 4 that no insert () is very good, it also tells us why deque should be divided as a separate class in STL class.

For access data,Vector: ()The highest efficiency.

The statistical data in Experiment 5 shows that the efficiency of all data access methods is very close, but the vector: At () is the most efficient. This is because the optimal graph access time is the lowest six sigma value.

Last

I hope this article will show you about deque, And I am interested in or inspired by it. You are welcome to continue to discuss any questions and content about vector and deque.

References

Plauger, P. J. Standard C ++ library reference. February, 2003. msdn.

ISO/IEC 14882: 1998 (e). Programming Languages-C ++. ISO and ansi c ++ standard.

Schildt, Herbert. c ++ from the ground up, second edition. Berkeley: 1998.

Sutter, Herb. More exceptional C ++. indianapois: 2002.

Solemnly declare:
Allows replication, modification, transfer, or other actions
But not for any commercial purposes.
Written in /11/7 masterlee

Author's blog:Http://blog.csdn.net/masterlee/

From: http://dev.csdn.net/htmls/48/48881.html

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.