精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-01-09
最后修改:2011-01-10
C/C++&Java 字符串拼接效率对比 C/C++拼接字符串的方式很多,尤其是所谓的”VC++”语言(不应该称其为语言,但是很多使用VC++的程序员却把它变成了VC++语言即微软血统的C++语言)中这种方式又变多一些。在Windows下的Visual C++中很多的程序员习惯使用微软MFC中CString 。虽然使用MFC编程时使用CString来处理字符串的确有着与MFC库配合的便利。但是在开发中如果并没有用到MFC的时候我建议还使用 Standard C++的字符串。好处很多首先它是标准的意味着你使用它(std::string, std::wstring)来处理字符串。并且你的程序没有使用与具体操作系统相关的API (或使用了跨平台的相关类库代替)。 那么意味着你的代码在有对应平台的并且符合C++标准的编译器下可以直接编译通过。也意味着你的程序具备较好的跨平台能力。另外在性能方面也较为出色。下面测试了一下在VC++2008中各种字符串拼接方式的性能对比。当然这里面有有预分配方式的,测试程序中最后会根据每一项的耗时进行排序,当然排序的结果需要看是否采用预分配方式。当然C++ std::string, std::wstring中有一些提高效率的机制(在非预分配方式下)。然后又在Java中测试了一下字符Java的StringBuffer及StringBuilder字符串拼接效率也很不错。最后测试的结果有助于指导我们使用最高效的方式处理字符处拼接。 字符串拼接测试方式分别是: 1. C语言在预分配内存上的strcpy函数 2. C语言在预分配内存上的 memcpy函数 3. C++中std::string的 append函数 4. C++中std::string 的 operator+= 5. C++中std::ostringstream的 operator<< 6. C++中std::string使用事先预分配(调用 reserve函数) 7. MFC中CString的Append函数 8. MFC中CString的operator+=
以下测试代码: 注:在 const int TEST_TIMES = 9000000;时C的memcpy使用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; } 请接下部。。。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-01-09
1,6,7,8的结果呢。
JAVA的呢。? |
|
返回顶楼 | |
发表时间:2011-01-10
您好,帖子长度超过了论坛的限制,需要分发不过里面有文档,和源码。你可以下载。
文档时*.docx的 |
|
返回顶楼 | |
发表时间:2011-01-10
您好,帖子长度超过了论坛的限制,需要分发不过里面有文档,和源码。你可以下载。
文档时*.docx的 |
|
返回顶楼 | |
发表时间:2011-01-19
楼主,以后《上传》压缩文件。用ZIP。别用RAR。
什么意思大家多知道的。 |
|
返回顶楼 | |
发表时间:2011-01-20
感觉楼主的Java水平不专业
|
|
返回顶楼 | |
发表时间:2011-01-21
讲讲区别,我洗耳恭听
|
|
返回顶楼 | |
发表时间: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的实现原理也就是这样实现的。 |
|
返回顶楼 | |
浏览 10903 次