Saving your strings

Source: Internet
Author: User

 

You are still generating temporary objects for the chain operation code such as string S = str1 + "123" + str2 + str3, and secondary complexity (the minimum complexity is the number of str1 length multiplied by "+?

 

From today on, stay away from these problems.

 

I thought I invented it myself and gave it a name called"Operator proxy"(The English translation has a keyword, sorry). As a result, the talents in the world had a similar idea, calledExpression template (expression-template, my name is ET)(The difference in font is actually the difference between the lady in the main house and the lady in the Eccentric House, the difference between foreign capital and private enterprises), hey. However, I feel that I have extended some of its existing concepts and feel that I am fully qualified to give a new name to this technology.

 

You can check my code first. The Code tests the string for 8 times and the ASCII length of a single string is between 10 and 30. (This is very common. url, SQL, the most common length interval in XML operations ). It is executed for 10000000 consecutive times. For the differences between the two tests, pay attention to the differences between the 115 rows and the 123 rows (see the seed "Seed" in the 115 rows, huh, huh ). * Strb. begin () = '0' is used to prevent some STL implementations from using reference counting and copy on write to reduce the number of copies (this technology is born to confuse you in a dual-core multi-thread program ).

 

# Include <string> <br/> # include <time. h> <br/> # include <stdio. h> <br/> using namespace STD; <br/> # ifdef _ msc_ver <br/> # If _ msc_ver <= 1200 <br/> # ifndef _ intel_compiler <br/> # DEFINE _ msvc_6 <br/> # pragma warning (Disable: 4786) <br/> # endif <br/> template <Class D> <br/> struct et_seed <br/> {<br /> typedef D dest_type; <br/>}; <br/> namespace _ et_private <br/> {<br/> template <Bo Ol n> <br/> struct mpl_bool <br/> {<br/> size_t sizer [size_t (n) + 10]; <br/> }; <br/> template <typename T> <br/> mpl_bool <true> get_result (T *, typename T: dest_type *); <br/> mpl_bool <false> get_result (...); <br/> template <typename T> <br/> struct check <br/> {<br/> Enum {result = (sizeof (get_result (T *) (null), null) = sizeof (mpl_bool <true>) };< br/>}; <br/> template <Class D, class l, class r> <br/> Str UCT binary_op <br/>{< br/> typedef D dest_type; <br/> typedef l left_type; <br/> typedef R right_type; <br/> inline binary_op (const left_type & LHS, const right_type & RHs): <br/> ldata (LHS), RDATA (RHs) {<br/>}< br/> const left_type & ldata; <br/> const right_type & RDATA; <br/> # ifndef _ msvc_6 <br/> template <typename T> <br/> inline static void OP (const T & Arg, dest_type & result) {<br/> result + = ARG; <br/>}</P> <p> template <typename T, typename m> <br/> inline static void OP (const binary_op <dest_type, T, m> & Arg, dest_type & result) {<br/> binary_op <dest_type, T, M >:: OP (Arg. ldata, result); <br/> binary_op <dest_type, T, M >:: OP (Arg. RDATA, result); <br/>}< br/> inline static void OP (const et_seed <dest_type> &/* Arg */, dest_type &/* result */) {}< br/> inline operator dest_type () const {<br/> Dest_type result; <br/> binary_op <dest_type, left_type, right_type >:: OP (ldata, result); <br/> binary_op <dest_type, left_type, right_type> :: OP (RDATA, result); <br/> return result; <br/>}< br/> # else // vc6 cannot choose the correct template function, so the 3rd argument is used to help it! <Br/> template <typename T> <br/> inline static void OP (const T & Arg, dest_type & result, mpl_bool <false> */* dummy */) {<br/> result + = ARG; <br/>}</P> <p> template <typename t, typename m> <br/> inline static void OP (const binary_op <dest_type, T, m> & Arg, dest_type & result, mpl_bool <true> */* dummy */) {<br/> binary_op <dest_type, T, m>: op (Arg. ldata, result, (mpl_bool <check <t>: Result> *) null); <br/> binary_op <dest_type, T, m>: op (Arg. RDATA, result, (mpl_bool <check <m >:: result> *) null ); <br/>}< br/> inline static void OP (const et_seed <dest_type> &/* Arg */, dest_type &/* result */, void */* dummy */) {}< br/> inline operator dest_type () const {<br/> dest_type result; <br/> binary_op <dest_type, left_type, right_type >:: OP (ldata, result, (mpl_bool <check <left_type >:: result> *) null); <br/> binary_op <dest_type, left_type, right_type> :: OP (RDATA, result, (mpl_bool <check <right_type >:: result> *) null); <br/> return result; <br/>}< br/> # endif <br/>}; <br/>}< br/> template <typename D, typename C> <br/> inline const _ et_private: binary_op <D, et_seed <D>, C> <br/> operator + (const et_seed <D> & LHS, const C & RHs) {<br/> return _ et_private: binary_op <D, et_seed <D>, C> (LHS, RHS ); <br/>}< br/> template <typename D, typename C> <br/> inline const _ et_private: binary_op <D, C, et_seed <D >>< br/> operator + (const C & LHS, const et_seed <D> & RHs) {<br/> return _ et_private: binary_op <D, c, et_seed <D> (LHS, RHS); <br/>}< br/> template <typename D, typename L, typename R, typename C> <br/> inline const _ et_private: binary_op <D, _ et_private: binary_op <D, L, r>, c> <br/> operator + (const _ et_private: binary_op <D, L, r> & LHS, const C & RHs) {<br/> return _ et_private :: binary_op <D, _ et_private: binary_op <D, L, r>, C> (LHS, RHS); <br/>}< br/> template <typename D, typename L, typename R, typename C> <br/> inline const _ et_private: binary_op <D, C, _ et_private: binary_op <D, L, r >>< br/> operator + (const C & LHS, const _ et_private: binary_op <D, L, r> & RHs) {<br/> return _ et_private:: binary_op <D, C, _ et_private: binary_op <D, L, r> (LHS, RHS); <br/>}< br/> typedef et_seed <STD:: String> string_helper; <br/> void test () <br/>{< br/> et_seed <STD: String> seed; <br/> string str1 = "1234567890"; <br/> string str2 = "12345678901234567890"; <br/> string str3 = "123456789012345678901234567890"; <br/> string strb; <br/> int current = Time (null); <br/> int I = 0; <br/> for (I = 0; I <10000000; ++ I) <br/> {<br/> strb = seed + str1 + str2 + String ("3") + str1 + "12345678901234567890" + str3 + (seed + str1 + str2) + ''); <br/> * strb. begin () = '0'; <br/>}< br/> printf ("% d/N", time (null)-current ); <br/> string (). swap (strb); <br/> current = Time (null); <br/> for (I = 0; I <10000000; ++ I) <br/> {<br/> strb = str1 + str2 + String ("3") + str1 + "12345678901234567890" + str3 + (str1 + str2) + ''); <br/> * strb. begin () = '0'; <br/>}< br/> printf ("% d/N", time (null)-current ); <br/>}< br/> int main (INT, char **) <br/>{< br/> test (); <br/> return 0; <br/>}

 

Run the test after the release is compiled. The specific time is obviously related to the performance of the respective machines. It doesn't make sense to compare them directly. Some servers are too fast and I even add two zeros to the number of tests. Let's talk about the proportion:

 

Close all other software in the amd dual-core XP system,

1) vc6 compiler + vc6stl, the copy time for "available" versions is about 56% of that for "no" versions,

2) intel Compiler (v10.1.034) + vc6stl results are roughly the same as 1), less than 1% of the fluctuation range;

3) vc6 compiler + stlport4.6.2. The copy time for "available" versions is about 75% of that for "no" versions. This version uses iostream to output the compiler and will crash.

4) intel Compiler (v10.1.034) + stlport4.6.2. The copy time for "available" versions is about 60% of that for "available" versions.

5) for vc2008 compiler + vc2008stl, the copy time for "available" versions is about 70% of that for "no" versions

 

Public servers, due to the use of others, occasionally fluctuating data, but I see that my program occupies almost 99% of the CPU.

(5) Unix-center Ubuntu server dual-core single-thread (ubuntu.unix-center.net), GCC 4.2.4, "available" version copy time is about 89-92% of the "available" version.

 

6) Unix-center Solaris server eight-Core 4-thread (t1000.unix-center.net), GCC 4.0.3, "available" version copy time is about "no" version of 80-85%.

7) Unix-center AIX Server 2-core dual-core single thread (aix.unix-center.net), GCC 4.2.0, actually said the link can not find the string constructor, go, google said that this version of Aix's GCC does have this problem, and I have no idea how to compile it for another visit.

 

Conclusion:

As you can see, the performance improvement between "available" and "NONE" is not small, especially for Windows platforms. GCC seems to be quite powerful, and performance improvement is not as good as Win's BT. I guess it is better to optimize anonymous return values. Another blow to me is that the Intel compiler is not much faster than vc6, and I recommend it if I am lost. In short, if you have performance optimization requirements and the C ++ Code has the custom binary operator chain operation described above, the above technology is worth your consideration, there is almost no charge for one shot. (No! I spent a "Bullet", haha)

 

Usage:

FirstAfter determining the operation result type, define a seed. For example, the first line is et_seed <STD: String> seed; To create a seed of the string type.

 

ThenPlace the seeds on the left end of the operation chain, which can be placed first, such as line 1 of the Code; or the second place. (if you are familiar with the constraint of mixed addition of STD: string and const char *, you can see why it cannot be placed in the third place ). merge it with an existing operator. here is "+ ". generally, it is nice to look at and better to change. We recommend that you.

 

LastIf there are parentheses that change the operation sequence, and there are no parentheses in the brackets, the expressions inside the brackets are treated as an independent operation chain and repeat the previous step.

For example, line 1 of this Code, string ("3") has nothing to do with changing the operation order. However, the next parentheses obviously change the operation order, but there areParentheses, We only need to put the seed again in the parentheses.

Find the most"Deep"It's okay to put more seeds in brackets. If you want to grow vegetables, there is almost no difference between planting vegetables and planting vegetables in the deepest soil, isn't it?

 

Okay, you're done! 10%-40% efficiency improvement is waiting for you.

 

In fact, most operations only need to create a seed and put it on the leftmost end, as long as the User-Defined operators that meet the combination law are removed, we can actually remove the brackets (that is, to meet A + B + C = a + (B + C). The above code is for illustration. in addition, the seed can be reused. If you are interested, you can even make him Singleton. temporary (Anonymous, right value, many) seeds can also be used. You can replace seed with et_seed in Row 3 <STD: String>. it's been so longYou should also note that et_seed is an empty class and there is almost no overhead for creation (depending on your compiler), so there is no loss if there are too many seeds.

 

 

In any case, this trick is still very original and practical:

1. Non-invasive. You only need to "+" A "Seed" when using it ". It is almost impossible to conflict with existing code.

2. It is easy to use. You only need to modify the code by about 10 letters.

3. With excellent portability, I try to use as few advanced C ++ features as possible without affecting efficiency, and carefully let the code be compiled in the antique compilers such as vc6.

4. It has a very wide range of applicability. Compared with the original operators, it can be used only for the types that meet the following requirements. Here we use the "+" Operation and STD: string type to describe it, you can replace + with other 2-element operators in batches, such as *,/, and-. (C ++ generic operators cannot be generic operators or operators ).

Requirements are dividedSyntax requirementsAnd2 types of semantic requirements:

<1> whether there is a constructor (either custom or default ). As long as it is not a reference class (such as STD: auto_ptr_ref),They should all be there. Syntax requirements.

 

<2> supports "+" operations. Nonsense.Syntax requirements.

 

<3> the return type of the "+" operation is fixed to the original type. Have you ever seen this situation in string + String = string & string + const char * = const char? If you see such a class, you should throw it away and don't let it pollute your code. Semantic requirements.


<4> supports "+ =" operations of the same type as "+" (optional ).For example, the string "+" Operation supports the string, const char *, Char, and other operation types. The string "+ =" operation also supports these types through heavy load. If your "+ =" does not support some types,No errors.Semantic requirements.

 

<5> "+ =" Operation and"+" Operation parameters are of constant reference type or value passing.For example, string operator + (const string & LHS, char RHs); the first constant reference, 2nd values. String & operator ++ = (char C); same as above. If you encounter a change in the value of B or C after A = B + C when using a class, we recommend that you cherish your life and stay away from bad class libraries.Syntax requirements.


<6> A = a + B is equivalent to a + = B. A is equivalent to string () + A, and A + B + C is equivalent to a + (B + C ). Semantic requirements. Very important !!

 

Note 1:

If one of the above requirements is violated,If the syntax requirements are not met, the system will encounter errors during compilation.Semantic requirements may cause errors during compilation orIt can be run without an error during compilation and is efficient during runtime.RateThere are two situations: Operation and original efficiency operation. The specific situation is very complicated. You can leave a message to discuss the situation.Violation of requirements<6> the running result is incorrect! The static checking capability of the template is limited after all, and the syntax I can set is limited. Besides, I need to be compatible with the antique compiler, which is too complicated for the compiler to strike directly ...

NOTE 2:

Unless the requirements are violated <6>,Does not existWhen compiling, there is no error while running. An error occurred during running. First, check whether the operation type meets the requirements.<6>.

NOTE 3:

There are also some requirements that will be automatically met when the above requirements are met, such as the same type of copy structure ("+" Operation Return Value required ). Instead, I would like to remind you thatDoes the cognominal copy constructor have the explicit it keyword?

 

The heavy loads of the "+" operator in the Classic C ++ library all meet the above requirements, such as STL, Ace, and QT (boost is too broad and profound, So I dare not say anything, huh, huh ). What kind of database do you write?

 

The principle of Simple Description: The seed will make the result of the "+" operator A binary tree, with the node being a reference of the "+" operator, while the Binary Tree and the binary tree, the result of the Binary Tree and the original calculation object "+" is a new binary tree. therefore, the binary chain "+" operation result is a binary tree, where the leaf node is the original calculation object and the seed, the seed essence is used as the first step as a leaf node to help the original operation object construct the binary tree and avoid the original binary "+" operation. the tree finally attaches (or copies) values to the target type. In this case, the tree uses the non-argument constructor to form a target type object R, and then traverses the entire tree from the beginning to the end, when the sub-tree continues the post-order traversal and encounters the original computing object, it is used to perform the + = operation on the generated target type object R, and the seed node does not perform any operation. in this process, the advantages of using + = to return the reference that does not require the return value are used to construct the result object R. finally, use the generated result object R with a value (or copy ).

 

Note that the binary tree contains two references. The creation overhead is small, and the number of Binary Trees created is the same as the number of +.

 

Keyword: Binary Tree, + = operation.

(Read the latest version ):

Http://blog.csdn.net/zy498420/archive/2010/11/10/6000525.aspx

Some may be difficult to read my code. In the next article, I will explain some of the mysteries, some of my experiences, some detours, and some of my suggestions. in fact, the design of the C ++ library is like this. The database writers are tired and tired, and the library users are eager to die. I have written at least 5000 lines of code here to get the idea of this seed.Not everyone needs to understand STL. You can use it !!

 

You have no requirements on code copyright,RequestIf you copy the code, please leave a message to facilitate the author's statistics. If you have better suggestions, please kindly advise.

 

This is called "Seed" to commemorate an almost unknown national hero.

Shiheng, Shiheng, shishitao, and Shishi

Generations of heroes and heroes have successively fought against Xixia, Liao, and Jin, and contributed more than Yang's, it is a pity that today's people will not be able to read this article, unless they notice that "the old ones are slightly different" and "the small ones are slightly different", and they are willing to go deep into those who want to know about it.

Almost all of the good guys in the Ghost Team were honored to have done things under the big and small managers, and Wang Jin, Lu zhishen, Yang Zhi, and so on all held jobs under the old manager, money leopard Tang Long has made weapons under the old man's manager. I hope you can search for them. These heroes are worth remembering!

 

Stay away from textbooks, "the loss of courtesy lies in the wild", think independently, and take the sword as the spine!

 

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.