论坛首页 编程语言技术论坛

C/C++&Java 字符串拼接效率对比(上部)[内容超过长度被截断完成可以下载文档和源码]

浏览 10903 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-01-09   最后修改:2011-01-10
C++

C/C++&Java 字符串拼接效率对比

    C/C++拼接字符串的方式很多,尤其是所谓的”VC++”语言(不应该称其为语言,但是很多使用VC++的程序员却把它变成了VC++语言即微软血统的C++语言)中这种方式又变多一些。在Windows下的Visual C++中很多的程序员习惯使用微软MFCCString 。虽然使用MFC编程时使用CString来处理字符串的确有着与MFC库配合的便利。但是在开发中如果并没有用到MFC的时候我建议还使用 Standard C++的字符串。好处很多首先它是标准的意味着你使用它(std::string, std::wstring)来处理字符串。并且你的程序没有使用与具体操作系统相关的API (或使用了跨平台的相关类库代替)。 那么意味着你的代码在有对应平台的并且符合C++标准的编译器下可以直接编译通过。也意味着你的程序具备较好的跨平台能力。另外在性能方面也较为出色。下面测试了一下在VC++2008中各种字符串拼接方式的性能对比。当然这里面有有预分配方式的,测试程序中最后会根据每一项的耗时进行排序,当然排序的结果需要看是否采用预分配方式。当然C++ std::string, std::wstring中有一些提高效率的机制(在非预分配方式下)。然后又在Java中测试了一下字符JavaStringBufferStringBuilder字符串拼接效率也很不错。最后测试的结果有助于指导我们使用最高效的方式处理字符处拼接。

字符串拼接测试方式分别是:

1.  C语言在预分配内存上的strcpy函数

2.  C语言在预分配内存上的 memcpy函数

3.  C++std::stringappend函数

4.  C++std::string operator+=

5.  C++std::ostringstreamoperator<<

6.  C++std::string使用事先预分配(调用 reserve函数)

7.  MFCCStringAppend函数

8.  MFCCStringoperator+=

 

以下测试代码:

注:在 const int TEST_TIMES = 9000000;Cmemcpy使用16-32 ms(毫秒) std::string 也在 1000 ms(毫秒)左右。由于其他的方式耗时过长因此将 TEST_TIMES = 90000次 在Java中普通的String也是如此.

#include "stdafx.h"

#include <string>

#include <sstream>

#include <iostream>

#include <cassert>

#include <cstring>

#include <ctime>

#include <vector>

#include <algorithm>

#include <afxwin.h>

 

using namespace std;

 

 

const int      TEST_TIMES              = 90000;

const char   APPEND_CONTENT[]       = "cppmule";

const int      PREALLOCATE_SIZE = strlen(APPEND_CONTENT) * TEST_TIMES + 1;

 

class Statistic {

public:

       string item;

       int used;

       friend inline ostream & operator << (ostream & os, const Statistic &stat) {

              os   << "item: " << stat.item << endl

                            << "used: " << stat.used << " ms." << endl << endl;

              return os;

       }

      

       inline bool operator>(const Statistic& stat) {

              return (used > stat.used);

       }

 

       inline bool operator<(const Statistic& stat) {

              return (used < stat.used);

       }

};

 

vector<Statistic> g_statistics;

 

#define BEGIN_TICK() \

       clock_t start = clock();

 

#define END_AND_PRINT_TICK(info)      \

       clock_t used = clock() - start;            \

       Statistic stat;                                 \

       stat.item.assign(info);                  \

       stat.used = used;                           \

       g_statistics.push_back(stat);             \

       cout << info << " Used: " << used << " ms." << endl;

 

#define PRINT_SORT_TEST_TICKS()                            \

       sort(g_statistics.begin(), g_statistics.end());              \

       struct StatisticPrinter {                             \

              StatisticPrinter() : order(0) {}                 \

              void operator() (const Statistic& stat) {         \

                     ++order;                                  \

                     cout << "sort order: " << order << endl   \

                                    << stat;                    \

              }                                               \

              int order;                                        \

       } printer;                                               \

cout << "---------Statistics informations(sorting ascendent)-------" << endl << endl;     \

       for_each(g_statistics.begin(), g_statistics.end(), printer);\

       cout << "----------------------------------------------------------" << endl;

 

 

void test_stdstring_append()

{

       string str;

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              str.append(APPEND_CONTENT);

       }

       END_AND_PRINT_TICK("std::string append");

       cout << "string length: " << str.length() << endl;

}

 

void test_stdstring_append_operator()

{

       string str;

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              str += APPEND_CONTENT;

       }

       END_AND_PRINT_TICK("std::string += operator");

       cout << "string length: " << str.length() << endl;

}

 

void test_stdostringstream()

{

       ostringstream oss;

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              oss << APPEND_CONTENT;

       }

       END_AND_PRINT_TICK("std::ostringstream <<");

       cout << "string length: " << oss.str().length() << endl;

}

 

void test_stdostringstream_preallocate()

{

       ostringstream oss;

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              oss << APPEND_CONTENT;

       }

       END_AND_PRINT_TICK("std::ostringstream <<");

       cout << "string length: " << oss.str().length() << endl;

}

 

void test_stdstring_append_operator_preallocate()

{

       string str;

       str.reserve(PREALLOCATE_SIZE);

       cout << "capacity: " << str.capacity() << endl

              << "size: " << str.size() << endl;

       //assert(str.capacity() == 1024*1024*512);

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              str += APPEND_CONTENT;

       }

       END_AND_PRINT_TICK("hava resize(PREALLOCATE_SIZE) std::string += operator");

       cout << "string length: " << str.length() << endl;

}

 

void test_c_strcat_append()

{

       char* pstr = (char*)malloc(PREALLOCATE_SIZE);

       memset(pstr, 0, sizeof(pstr));

 

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              strcat(pstr, APPEND_CONTENT);

       }

       END_AND_PRINT_TICK("c string function strcat:");

       cout << "string length: " << strlen(pstr) << endl;

 

       free(pstr);

       pstr = NULL;

}

 

void test_c_memcpy_append()

{

       //Allocate memory

       char* pstr = (char*)malloc(PREALLOCATE_SIZE);

       if (NULL == pstr) {

              cerr << "Can't allocate memory." << endl;

              return;

       }

       memset(pstr, 0, PREALLOCATE_SIZE);

 

       BEGIN_TICK();

       int len = 0;

       for (int i=0; i<TEST_TIMES; i++) {

              memcpy(pstr + len, APPEND_CONTENT, strlen(APPEND_CONTENT));

              len += strlen(APPEND_CONTENT);

       }

       END_AND_PRINT_TICK("C language memcpy append");

       cout << "string length: " << strlen(pstr) << endl;

 

       //Cleanup

       free(pstr);

       pstr = NULL;

}

 

void test_mfc_cstring_append()

{

       CString str;

 

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              str.Append(APPEND_CONTENT);

       }

       END_AND_PRINT_TICK("MFC CString append");

       cout << "string length: " << str.GetLength() << endl;

}

 

void test_mfc_cstring_append_operator()

{

       CString str;

      

       BEGIN_TICK();

       for (int i=0; i<TEST_TIMES; i++) {

              str += APPEND_CONTENT;

       }

       END_AND_PRINT_TICK("MFC CString operator append");

       cout << "string length: " << str.GetLength() << endl;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

#ifdef _DEBUG

       cout << "DEBUG version." << endl;

#else

       cout << "Release version." << endl;

#endif

       cout << "TEST_TIME: " << TEST_TIMES << endl;

 

       test_c_memcpy_append();

       test_stdstring_append_operator();

       test_stdstring_append();

       test_stdostringstream();

       test_stdstring_append_operator_preallocate();

       test_mfc_cstring_append();

       test_mfc_cstring_append_operator();

       test_c_strcat_append();

       PRINT_SORT_TEST_TICKS();

      

       return 0;

}

 请接下部。。。

   发表时间:2011-01-09  
1,6,7,8的结果呢。
JAVA的呢。?
0 请登录后投票
   发表时间:2011-01-10  
您好,帖子长度超过了论坛的限制,需要分发不过里面有文档,和源码。你可以下载。
文档时*.docx的
0 请登录后投票
   发表时间:2011-01-10  
您好,帖子长度超过了论坛的限制,需要分发不过里面有文档,和源码。你可以下载。
文档时*.docx的
0 请登录后投票
   发表时间:2011-01-19  
楼主,以后《上传》压缩文件。用ZIP。别用RAR。
什么意思大家多知道的。
0 请登录后投票
   发表时间:2011-01-20  
感觉楼主的Java水平不专业  
0 请登录后投票
   发表时间:2011-01-21  
讲讲区别,我洗耳恭听
0 请登录后投票
   发表时间:2011-02-27  
我的补充,详细的内容在注释中
public static void testJavaStringPerformance2() {
final int TEST_TIMES = 100000;
//String
String str = "";

System.out.println("The testing is running, please wait...");
// 使用纳秒作为时间计量单位,更加精确点
long start = System.nanoTime();
for (int i=0; i<TEST_TIMES; i++){str += "cppmule";}
long strUsed = System.nanoTime() - start;
System.out.println("strUsed: " + strUsed/1000000f + " ms.");
// 这句是为了清楚当前的环境对下面的测试的影响,保留只是为了使测试更加的准确
str=null; System.gc();
//StringBuffer
start = System.nanoTime();
// 构造函数中的参数如果等于整个结果的长度,那么速度将达到最快!
StringBuffer strBuffer = new StringBuffer( TEST_TIMES*7 );
for (int i=0; i<TEST_TIMES; i++){strBuffer.append("cppmule");}
long strBufferUsed = System.nanoTime() - start;
System.out.println("StringBuffer append: " + strBufferUsed/1000000f + " ms.");
// 这句是为了清楚当前的环境对下面的测试的影响,保留只是为了使测试更加的准确
strBuffer.delete(0, strBuffer.length() ); strBuffer = null; System.gc();
//StringBuilder
start = System.nanoTime();
StringBuilder strBuilder = new StringBuilder( TEST_TIMES*7 );
for (int i=0; i<TEST_TIMES; i++){strBuilder.append("cppmule");}
long strBuilderUsed = System.nanoTime() - start;
System.out.println("StringBuilder append: " + strBuilderUsed/1000000f + " ms.");

System.out.println("Times: " + TEST_TIMES);
}

public static void main(String[] args) {
testJavaStringPerformance2();
}
在java中,其实,还有更加快的字符串拼接方法:就是自己靠char[]来组装。StringBuidler的实现原理也就是这样实现的。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics