9
回答
问下默认情况下STL中std::string被缓冲的情况
注册华为云得mate10,2.9折抢先购!>>>   
连release的汇编代码都几乎一样,但stl的string却比我自己写的string在下面的比较字符串大小的代码上却要快将近20%,而且多次测量,结果一样。问下谁知道这个是由于std::string在cache中命中率比我的string命中率高的原因还是怎么,其他什么原因?如果是cache命中率高造成的,我有什么方法提高我自己写的string的命中率。
STL的string
struct stringcmp_t_std
{
	inline int operator () (const std::string & str1,
const std::string & str2) const
	{
		int ilen1 = str1.length();
		int ilen2 =  str2.length();
		const char* pstrchar1 = str1.data();
		const char* pstrchar2 = str2.data();

		int imin = ilen1;
		if (imin > ilen2)
			imin = ilen2;
		for (int i=0;i<imin;++i)
		{
			int iretn = pecker_value_compare__::compare( *(pstrchar1+i) , *(pstrchar2+i));
			if (0 != iretn)
			{
				return iretn;
			}
		}
		return (ilen1 - ilen2);
	}
};
我自己写的string
struct stringcmp_t_
{
	inline int operator () (const String_base & str1,const String_base & str2) const
	{

		int ilen1 = str1.get_string_length();
		int ilen2 =  str2.get_string_length();
		const char* pstrchar1 = str1.get_data();
		const char* pstrchar2 = str2.get_data();

		int imin = ilen1;
		if (imin > ilen2)
			imin = ilen2;
		for (int i=0;i<imin;++i)
		{
			int iretn = pecker_value_compare__::compare( *(pstrchar1+i) , *(pstrchar2+i));
			if (0 != iretn)
			{
				return iretn;
			}
		}
		return (ilen1 - ilen2);
	}
};
字符比较函数的一样的
struct pecker_value_compare__
{
	inline int operator () (const char &char1,const char &char2)  const
	{
		return (char1 - char2);
	}
	static  inline int compare(const char &char1,const char &char2)
	{
		return (char1 - char2);
	}
};
我的字符串中用到相关的函数	
inline const char_value_t* get_data() const
	{
		return _M_pthis_string_data;
	}
	inline string_size_t get_string_length() const
	{
		return _M_string_length;
	}
<无标签>
举报
cut
发帖于5年前 9回/713阅
共有9个答案 最后回答: 5年前

      我个人觉得不会是cache命中率的问题. 大家都是字节数组,一样的访问, 没理由不一样.       
      0.  代码这么相近.... 会不会是其他外部原因? 
      1.  ps, 如果最后的汇编语句, 人家是4条,而你是5条,自然会慢20%.呵呵.
      2.  指令流水线的原因也可以考虑下.

引用来自“Lunar_Lin”的答案

      我个人觉得不会是cache命中率的问题. 大家都是字节数组,一样的访问, 没理由不一样.       
      0.  代码这么相近.... 会不会是其他外部原因? 
      1.  ps, 如果最后的汇编语句, 人家是4条,而你是5条,自然会慢20%.呵呵.
      2.  指令流水线的原因也可以考虑下.

关键是我输出release汇编的时候我还特意数了下,stl的还要多几条指令,不信自己看

使用STL string代码的汇编
;	COMDAT ??$avl_tree_find@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@Ustringcmp_t_std@@U?$AVL_node_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@pecker_sdk@@@pecker_sdk@@YAPBU?$AVL_node_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@0@PBU10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABUstringcmp_t_std@@@Z
_TEXT	SEGMENT
_ilen2$125000 = -12					; size = 4
tv202 = -8						; size = 4
_ilen1$124999 = -4					; size = 4
_pAvl_root_node$ = 8					; size = 4
_key$ = 12						; size = 4
??$avl_tree_find@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@Ustringcmp_t_std@@U?$AVL_node_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@pecker_sdk@@@pecker_sdk@@YAPBU?$AVL_node_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@0@PBU10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABUstringcmp_t_std@@@Z PROC ; pecker_sdk::avl_tree_find<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,stringcmp_t_std,pecker_sdk::AVL_node_map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,int> >, COMDAT

; 451  : {

	push	ebp
	mov	ebp, esp
	sub	esp, 12					; 0000000cH
	push	ebx
	mov	ebx, DWORD PTR _pAvl_root_node$[ebp]
	push	esi
	push	edi

; 452  : 	while (null != pAvl_root_node)

	test	ebx, ebx
	je	SHORT $LN5@avl_tree_f@4

; 453  : 	{
; 454  : 		int cmp_result = _compare(key,pAvl_root_node->key);

	mov	ecx, DWORD PTR _key$[ebp]
	mov	edi, DWORD PTR [ecx+16]
	mov	eax, DWORD PTR [ecx+20]
	mov	DWORD PTR _ilen1$124999[ebp], edi
	mov	DWORD PTR tv202[ebp], eax
	jmp	SHORT $LN6@avl_tree_f@4
$LL42@avl_tree_f@4:
	mov	edi, DWORD PTR _ilen1$124999[ebp]
	mov	ecx, DWORD PTR _key$[ebp]
$LN6@avl_tree_f@4:
	cmp	DWORD PTR tv202[ebp], 16		; 00000010H
	mov	eax, DWORD PTR [ebx+28]
	lea	edx, DWORD PTR [ebx+12]
	mov	DWORD PTR _ilen2$125000[ebp], eax
	jb	SHORT $LN26@avl_tree_f@4
	mov	ecx, DWORD PTR [ecx]
$LN26@avl_tree_f@4:
	cmp	DWORD PTR [edx+20], 16			; 00000010H
	jb	SHORT $LN34@avl_tree_f@4
	mov	edx, DWORD PTR [edx]
$LN34@avl_tree_f@4:
	cmp	edi, eax
	jle	SHORT $LN13@avl_tree_f@4
	mov	edi, eax
$LN13@avl_tree_f@4:
	xor	esi, esi
	test	edi, edi
	jle	SHORT $LN43@avl_tree_f@4
	mov	ebx, edx
	sub	ebx, ecx
$LL12@avl_tree_f@4:
	movsx	eax, BYTE PTR [ebx+ecx]
	movsx	edx, BYTE PTR [ecx]
	sub	edx, eax
	jne	SHORT $LN40@avl_tree_f@4
	inc	esi
	inc	ecx
	cmp	esi, edi
	jl	SHORT $LL12@avl_tree_f@4
	mov	ebx, DWORD PTR _pAvl_root_node$[ebp]
	mov	eax, DWORD PTR _ilen2$125000[ebp]
$LN43@avl_tree_f@4:
	mov	edx, DWORD PTR _ilen1$124999[ebp]
	sub	edx, eax
$LN14@avl_tree_f@4:

; 455  : 		if (cmp_result < 0)

	test	edx, edx
	jns	SHORT $LN44@avl_tree_f@4

; 456  : 		{
; 457  : 			pAvl_root_node = (__AVL_node_t*)(pAvl_root_node->_M_left);

	mov	ebx, DWORD PTR [ebx]
	jmp	SHORT $LN45@avl_tree_f@4
$LN40@avl_tree_f@4:

; 453  : 	{
; 454  : 		int cmp_result = _compare(key,pAvl_root_node->key);

	mov	ebx, DWORD PTR _pAvl_root_node$[ebp]
	jmp	SHORT $LN14@avl_tree_f@4
$LN44@avl_tree_f@4:

; 458  : 		}
; 459  : 		else if (cmp_result > 0)

	jle	SHORT $LN2@avl_tree_f@4

; 460  : 		{
; 461  : 			pAvl_root_node = (__AVL_node_t*)(pAvl_root_node->_M_right);

	mov	ebx, DWORD PTR [ebx+4]
$LN45@avl_tree_f@4:
	mov	DWORD PTR _pAvl_root_node$[ebp], ebx
	test	ebx, ebx
	jne	SHORT $LL42@avl_tree_f@4
$LN5@avl_tree_f@4:
	pop	edi
	pop	esi

; 466  : 		}
; 467  : 	}
; 468  : 	return null;

	xor	eax, eax
	pop	ebx

; 469  : }

	mov	esp, ebp
	pop	ebp
	ret	0
$LN2@avl_tree_f@4:
	pop	edi
	pop	esi

; 462  : 		}
; 463  : 		else
; 464  : 		{
; 465  : 			return pAvl_root_node;

	mov	eax, ebx
	pop	ebx

; 469  : }

	mov	esp, ebp
	pop	ebp
	ret	0
??$avl_tree_find@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@Ustringcmp_t_std@@U?$AVL_node_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@pecker_sdk@@@pecker_sdk@@YAPBU?$AVL_node_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@0@PBU10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABUstringcmp_t_std@@@Z ENDP ; pecker_sdk::avl_tree_find<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,stringcmp_t_std,pecker_sdk::AVL_node_map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,int> >
_TEXT	ENDS
使用自己string代码的汇编
;	COMDAT ??$avl_tree_find@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@Ustringcmp_t_@@U?$AVL_node_map@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@H@2@@pecker_sdk@@YAPBU?$AVL_node_map@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@H@0@PBU10@ABV?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@0@ABUstringcmp_t_@@@Z
_TEXT	SEGMENT
_pstrchar1$119567 = -8					; size = 4
_ilen1$119565 = -4					; size = 4
_pAvl_root_node$ = 8					; size = 4
??$avl_tree_find@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@Ustringcmp_t_@@U?$AVL_node_map@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@H@2@@pecker_sdk@@YAPBU?$AVL_node_map@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@H@0@PBU10@ABV?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@0@ABUstringcmp_t_@@@Z PROC ; pecker_sdk::avl_tree_find<pecker_sdk::pecker_share_string_base_t<char,pecker_sdk::pecker_value_compare<char>,pecker_sdk::pecker_simple_allocator<char> >,stringcmp_t_,pecker_sdk::AVL_node_map<pecker_sdk::pecker_share_string_base_t<char,pecker_sdk::pecker_value_compare<char>,pecker_sdk::pecker_simple_allocator<char> >,int> >, COMDAT
; _key$ = ecx

; 451  : {

	push	ebp
	mov	ebp, esp
	mov	eax, DWORD PTR _pAvl_root_node$[ebp]
	sub	esp, 8
	push	ebx
	push	esi
	push	edi

; 452  : 	while (null != pAvl_root_node)

	test	eax, eax
	je	SHORT $LN5@avl_tree_f@2

; 453  : 	{
; 454  : 		int cmp_result = _compare(key,pAvl_root_node->key);

	mov	ebx, DWORD PTR [ecx+12]
	mov	ecx, DWORD PTR [ecx+4]
	mov	DWORD PTR _ilen1$119565[ebp], ebx
	mov	DWORD PTR _pstrchar1$119567[ebp], ecx
	npad	4
$LL6@avl_tree_f@2:
	mov	ecx, DWORD PTR [eax+24]
	mov	edx, DWORD PTR [eax+16]
	mov	edi, ebx
	cmp	ebx, ecx
	jle	SHORT $LN13@avl_tree_f@2
	mov	edi, ecx
$LN13@avl_tree_f@2:
	xor	esi, esi
	test	edi, edi
	jle	SHORT $LN10@avl_tree_f@2
	mov	ecx, DWORD PTR _pstrchar1$119567[ebp]
	mov	ebx, edx
	sub	ebx, ecx
	npad	5
$LL12@avl_tree_f@2:
	movsx	eax, BYTE PTR [ebx+ecx]
	movsx	edx, BYTE PTR [ecx]
	sub	edx, eax
	jne	SHORT $LN28@avl_tree_f@2
	inc	esi
	inc	ecx
	cmp	esi, edi
	jl	SHORT $LL12@avl_tree_f@2
	mov	eax, DWORD PTR _pAvl_root_node$[ebp]
	mov	ebx, DWORD PTR _ilen1$119565[ebp]
$LN10@avl_tree_f@2:
	mov	edx, ebx
	sub	edx, DWORD PTR [eax+24]
$LN14@avl_tree_f@2:

; 455  : 		if (cmp_result < 0)

	test	edx, edx
	jns	SHORT $LN31@avl_tree_f@2

; 456  : 		{
; 457  : 			pAvl_root_node = (__AVL_node_t*)(pAvl_root_node->_M_left);

	mov	eax, DWORD PTR [eax]
	jmp	SHORT $LN32@avl_tree_f@2
$LN28@avl_tree_f@2:

; 453  : 	{
; 454  : 		int cmp_result = _compare(key,pAvl_root_node->key);

	mov	eax, DWORD PTR _pAvl_root_node$[ebp]
	mov	ebx, DWORD PTR _ilen1$119565[ebp]
	jmp	SHORT $LN14@avl_tree_f@2
$LN31@avl_tree_f@2:

; 458  : 		}
; 459  : 		else if (cmp_result > 0)

	jle	SHORT $LN7@avl_tree_f@2

; 460  : 		{
; 461  : 			pAvl_root_node = (__AVL_node_t*)(pAvl_root_node->_M_right);

	mov	eax, DWORD PTR [eax+4]
$LN32@avl_tree_f@2:
	mov	DWORD PTR _pAvl_root_node$[ebp], eax
	test	eax, eax
	jne	SHORT $LL6@avl_tree_f@2
$LN5@avl_tree_f@2:

; 462  : 		}
; 463  : 		else
; 464  : 		{
; 465  : 			return pAvl_root_node;
; 466  : 		}
; 467  : 	}
; 468  : 	return null;

	xor	eax, eax
$LN7@avl_tree_f@2:
	pop	edi
	pop	esi
	pop	ebx

; 469  : }

	mov	esp, ebp
	pop	ebp
	ret	0
??$avl_tree_find@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@Ustringcmp_t_@@U?$AVL_node_map@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@H@2@@pecker_sdk@@YAPBU?$AVL_node_map@V?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@pecker_sdk@@H@0@PBU10@ABV?$pecker_share_string_base_t@DU?$pecker_value_compare@D@pecker_sdk@@V?$pecker_simple_allocator@D@2@@0@ABUstringcmp_t_@@@Z ENDP ; pecker_sdk::avl_tree_find<pecker_sdk::pecker_share_string_base_t<char,pecker_sdk::pecker_value_compare<char>,pecker_sdk::pecker_simple_allocator<char> >,stringcmp_t_,pecker_sdk::AVL_node_map<pecker_sdk::pecker_share_string_base_t<char,pecker_sdk::pecker_value_compare<char>,pecker_sdk::pecker_simple_allocator<char> >,int> >
_TEXT	ENDS

 

--- 共有 2 条评论 ---
cut回复 @Lunar_Lin : 如果是流水线的问题应该多次测试出来的结果不一样才对吧,有的快有的慢,如果程序使用流水线优化应该会在汇编上有所体现,但那汇编中看不出来 5年前 回复
Lunar_Lin呵呵. 那就可能是实际执行时候的流水线差异? 写标准库真不容易. 我对这方面没经验, 也没热情. 嘿嘿. 5年前 回复

STL 那些模板替换之后, 实际上最后就变成了 memcpy.

绕了很大一个圈子, 先写一大堆代码, 用最复杂的编译器, 继续模板替换之后, 

最后生成了 memcpy 的代码

我的疑问就是为什么不直接用memcpy

和STL去比性能, 意义不大.

如果真想和STL比性能, 就直接调用strncpy或者memcpy.  代码更干净, 性能更佳, 更容易调试.

不要模仿它, 如果你模仿它, 永远超越不了它

但是, 如果你如果不打算模仿它, 超越它很容易, 只要不引人bloats就直接超越它了.


--- 共有 2 条评论 ---
宏哥回复 @cut : 这个我倒没有注意到. 5年前 回复
cut我那汇编代码并没有发现memcpy的替换,而且比较里也没用stl string的比较,比较全是自己写的,std::string只提供字符首地址,跟字符长度,其他的都是自己写,用string里面的compare没任何比较的价值。 5年前 回复

引用来自“永远在一起”的答案

能给出完整的测试程序来么?我帮你用多个编译器测试一下

http://www.oschina.net/code/snippet_253717_15597

用VC2010打开,btst_tree_test.cpp里面的是测试代码,看int _2_avl_key_map_cmp(int itime = 1)那个函数,里面是这里相关的测试代码

  avl_stress_find_time(array,avl_tree_strings_map);是使用我自己的string作为key的avl树
  avl_std_string_stress_find_time(arraystd,avl_tree_stdstrings_map);是使用stl的string作为key的avl树

目前代码只有在gcc 4.6安卓版的上面试过,其他编译器不保证能通过编译。

在使用8W词库的时候,avl_stress_find_time执行一次大约40~46毫秒,avl_std_string_stress_find_time是31~36毫秒。使用其他两个词库还是stl的string快。

 建议release编译好后,在文件夹里运行,不要使用vc直接打开,因为vc会给程序挂钩,导致运行结果不准确。

引用来自“cut”的答案

引用来自“永远在一起”的答案

能给出完整的测试程序来么?我帮你用多个编译器测试一下

http://www.oschina.net/code/snippet_253717_15597

用VC2010打开,btst_tree_test.cpp里面的是测试代码,看int _2_avl_key_map_cmp(int itime = 1)那个函数,里面是这里相关的测试代码

  avl_stress_find_time(array,avl_tree_strings_map);是使用我自己的string作为key的avl树
  avl_std_string_stress_find_time(arraystd,avl_tree_stdstrings_map);是使用stl的string作为key的avl树

目前代码只有在gcc 4.6安卓版的上面试过,其他编译器不保证能通过编译。

在使用8W词库的时候,avl_stress_find_time执行一次大约40~46毫秒,avl_std_string_stress_find_time是31~36毫秒。使用其他两个词库还是stl的string快。

 建议release编译好后,在文件夹里运行,不要使用vc直接打开,因为vc会给程序挂钩,导致运行结果不准确。

测试了,在gcc 4.6.2中没有出现stl比手写的要快的情况(有几次stl更快,有几次stl更慢)。不过有几个编译错误,可变宏参数的支持:在g++4.6.2中,PECKER_LOG_INFO("tst_stress_insert_time",".......");会出错,它被扩展为printf (".....",/*这里的参数没有了*/ );。第二个错误是模板的>>中间的空格的问题。还有就是data/pekcer_string.h这个是不是拼错了。不过VS2010确实出现了楼主说的情况,今天先弄到这里。明天在看看看看VS2010中的怎么会这样子。

引用来自“永远在一起”的答案

引用来自“cut”的答案

引用来自“永远在一起”的答案

能给出完整的测试程序来么?我帮你用多个编译器测试一下

http://www.oschina.net/code/snippet_253717_15597

用VC2010打开,btst_tree_test.cpp里面的是测试代码,看int _2_avl_key_map_cmp(int itime = 1)那个函数,里面是这里相关的测试代码

  avl_stress_find_time(array,avl_tree_strings_map);是使用我自己的string作为key的avl树
  avl_std_string_stress_find_time(arraystd,avl_tree_stdstrings_map);是使用stl的string作为key的avl树

目前代码只有在gcc 4.6安卓版的上面试过,其他编译器不保证能通过编译。

在使用8W词库的时候,avl_stress_find_time执行一次大约40~46毫秒,avl_std_string_stress_find_time是31~36毫秒。使用其他两个词库还是stl的string快。

 建议release编译好后,在文件夹里运行,不要使用vc直接打开,因为vc会给程序挂钩,导致运行结果不准确。

测试了,在gcc 4.6.2中没有出现stl比手写的要快的情况(有几次stl更快,有几次stl更慢)。不过有几个编译错误,可变宏参数的支持:在g++4.6.2中,PECKER_LOG_INFO("tst_stress_insert_time",".......");会出错,它被扩展为printf (".....",/*这里的参数没有了*/ );。第二个错误是模板的>>中间的空格的问题。还有就是data/pekcer_string.h这个是不是拼错了。不过VS2010确实出现了楼主说的情况,今天先弄到这里。明天在看看看看VS2010中的怎么会这样子。
确实是拼错了,LOG输出那个我没在桌面版的GCC编过,ANDROID跑的是LOGCAT的那路输出,模板的一些>>空格问题确实蛋疼,每个编译器要求都不一样
--- 共有 2 条评论 ---
cut回复 @永远在一起 : 究竟GCC编译出来的程序测试显示的时间跟VC2010编译的程序测试显示的时间,同一个测试项哪个快哪个慢,还是一样,是VC2010下STL的STRING特别快还是跟GCC的一样。 5年前 回复
永远在一起模板的>>一开始C++是不支持的,要求所有的都要加上空格,合在一起会被认为是右移操作符,C++11发现这个限制又是不必要的,所以又允许了。不过为了完整的兼容所有情况,还是请加上空格。VS2010的测试结果确实稀奇。不知道是什么原因。 5年前 回复

g++4.6.2运行的结果

msvc10.0的运行结果

--- 共有 7 条评论 ---
cut回复 @永远在一起 : 应该不会,都是只取指针和字符长度的操作,其他的都一样。 5年前 回复
永远在一起回复 @cut : 现在不想看源代码,不过我怀疑是不是其他地方污染了测试结果 5年前 回复
cut回复 @永远在一起 : 编译release的时候我将ASM输出选型勾上了,从输出的汇编上看并没有类似的替换 5年前 回复
永远在一起回复 @cut : 上次2010居然能使用memcpy之类的函数替换整个代码段,但是GCC不会。看来2010在优化方面做得比较激进。开挂的可能还是挺大的 5年前 回复
cut回复 @永远在一起 : 这个值快得不正常,当初调三叉树的时候,按原理来说平衡三叉树字符串搜索应该要比AVL树速度更快,我调了大半天,用VS2010舰旗版的性能分析工具发现在字符比较那性能老有问题,后来改成AVL比AVL的,结果就比出那么坑爹的结果。 5年前 回复

引用来自“永远在一起”的答案

g++4.6.2运行的结果

msvc10.0的运行结果

昨天花了2G的流量,下了个Intel Parallel Studio XE2011用ICC编译了下,也没发现很大的区别,然后我切换成VC的编译编译了下,也没有发现原来那么大的区别,但我这次是用XP SP3的系统编译的,一会晚上回去用我自己的WIN7机再试试,搞不好跟操作系统有关,这个差异应该确实是跟内存的位置很有关。

顶部