究竟怎么回事啊?太意外了。

AhBian 2006-08-20 10:02:31
有一段代码,如下:
int i, t, q, r, size;
int[] factors;

...

while ( ... )
{
...
t = factors[size - 1] + factors[size - 2];
q = t / (factors[size - 2] + 1);
r = t % (factors[size - 2] + 1);
t = factors[size - 2] + 1;
i = size - 2;
size = size - 2 + q;
...
}

...

我把它们精简一下,目的是想减少运算表达式,以提高性能:

int i, t, q, r, s, size;
int[] factors;

...

while ( ... )
{
...
i = size - 2;
q = factors[i];
t = factors[size - 1] + q;
s = q + 1;
q = t / s;
r = t % s;
t = s;
size = i + q;
...
}

...

如果不是在循环中,我也不会去精简它们,因为即使有所改善,效果实在太微。
但因为在循环中,所以我才有此想法。
然而实际结果是:精简后,性能反而略微有所下降。

实在不明白是什么道道。

希望熟悉 .NET 编译和底层运行机制的大哥大姐指点一下迷津。
...全文
921 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
daishengs 2006-08-22
  • 打赏
  • 举报
回复
领教
addwing 2006-08-22
  • 打赏
  • 举报
回复
关注,帮你顶!
guyes123 2006-08-21
  • 打赏
  • 举报
回复
mark
myminimouse 2006-08-21
  • 打赏
  • 举报
回复
mark
qzh1119 2006-08-21
  • 打赏
  • 举报
回复
都是高手啊,学习
弘毅致远 2006-08-21
  • 打赏
  • 举报
回复
过手过招。8错8错,领教了。。。。学习ING。
jun_01 2006-08-21
  • 打赏
  • 举报
回复
期待总结,留名学习!
wuhuiITren 2006-08-21
  • 打赏
  • 举报
回复
晕,回答的都是星级用户
jeremychen001181 2006-08-21
  • 打赏
  • 举报
回复
to: 在 .NET 中代码冗余一点,没关系,精简了,反而不好

不敢相信,或者说是不愿意相信, 坐下来再等等。
stephen_liu1980 2006-08-21
  • 打赏
  • 举报
回复
AhBian 2006-08-20
  • 打赏
  • 举报
回复
TO Knight94(愚翁):
我测试了一下你的代码,平均了 10 次的时间,结果的确是有所改善的。

我再研究一下我的代码,看看是否有可改善的地方。
test33 2006-08-20
  • 打赏
  • 举报
回复
寒`
杂的 汇编都来了外`。。。
。。。。。。
肄若芸 2006-08-20
  • 打赏
  • 举报
回复
顶一个~
Knight94 2006-08-20
  • 打赏
  • 举报
回复
所以对代码的性能提升,不单单是对应用类型的访问减少,毕竟对局部变量的访问也是需要通过栈指针访问。
Knight94 2006-08-20
  • 打赏
  • 举报
回复
对于目前的TestOne的性能要比TestTwo差,但是如下进行修改后,TestOne的性能要比TestTwo高
private void TestOne()
{
Debug.WriteLine( DateTime.Now.ToString( "HH:mm:ss" ) );
int i, t;
const int TOTAL_NUM = 100000000;
int[] factors = new int[TOTAL_NUM];
for( int n = 0; n < TOTAL_NUM; n++ )
{
i = factors[n];
i = i + 1;//Forehead this statement
t = i + 1;
}
Debug.WriteLine( DateTime.Now.ToString( "HH:mm:ss" ) );
}

其产生的汇编代码(循环部分):
0000004d mov edx,5F5E100h
00000052 mov ecx,6D610FAh
00000057 call F92B1F10
0000005c mov dword ptr [ebp-10h],eax
for( int n = 0; n < TOTAL_NUM; n++ )
0000005f xor ebx,ebx
00000061 nop
00000062 jmp 00000085
i = factors[n];
00000064 mov eax,dword ptr [ebp-10h]
00000067 cmp ebx,dword ptr [eax+4]
0000006a jb 00000073
0000006c xor ecx,ecx
0000006e call 71A5F79B
00000073 mov eax,dword ptr [eax+ebx*4+8]
00000077 mov dword ptr [ebp-8],eax
i = i + 1;//Forehead this statement
0000007a inc dword ptr [ebp-8]
t = i + 1;
0000007d mov eax,dword ptr [ebp-8]
00000080 inc eax
00000081 mov dword ptr [ebp-0Ch],eax
for( int n = 0; n < TOTAL_NUM; n++ )
00000084 inc ebx
00000085 cmp ebx,5F5E100h
0000008b jl 00000064
Knight94 2006-08-20
  • 打赏
  • 举报
回复
而对于TestOne产生的汇编代码如下(循环部分):
0000004d mov edx,5F5E100h
00000052 mov ecx,6D610FAh
00000057 call F92B1F10
0000005c mov dword ptr [ebp-10h],eax
for( int n = 0; n < TOTAL_NUM; n++ )
0000005f xor ebx,ebx
00000061 nop
00000062 jmp 00000086
i = factors[n];
00000064 mov eax,dword ptr [ebp-10h]
00000067 cmp ebx,dword ptr [eax+4]
0000006a jb 00000073
0000006c xor ecx,ecx
0000006e call 71A5F79B
00000073 mov eax,dword ptr [eax+ebx*4+8]
00000077 mov dword ptr [ebp-8],eax
t = i + 2;
0000007a mov eax,dword ptr [ebp-8]
0000007d inc eax
0000007e inc eax
0000007f mov dword ptr [ebp-0Ch],eax
i = i + 1;
00000082 inc dword ptr [ebp-8]
for( int n = 0; n < TOTAL_NUM; n++ )
00000085 inc ebx
00000086 cmp ebx,5F5E100h
0000008c jl 00000064


对于TestTwo产生的汇编代码(循环部分):
0000004d mov edx,5F5E100h
00000052 mov ecx,6D610FAh
00000057 call F92B1F18
0000005c mov dword ptr [ebp-10h],eax
for( int n = 0; n < TOTAL_NUM; n++ )
0000005f xor ebx,ebx
00000061 nop
00000062 jmp 00000094
i = factors[n] + 1;
00000064 mov eax,dword ptr [ebp-10h]
00000067 cmp ebx,dword ptr [eax+4]
0000006a jb 00000073
0000006c xor ecx,ecx
0000006e call 71A5F7A3
00000073 mov eax,dword ptr [eax+ebx*4+8]
00000077 inc eax
00000078 mov dword ptr [ebp-8],eax
t = factors[n] + 2;
0000007b mov eax,dword ptr [ebp-10h]
0000007e cmp ebx,dword ptr [eax+4]
00000081 jb 0000008A
00000083 xor ecx,ecx
00000085 call 71A5F7A3
0000008a mov eax,dword ptr [eax+ebx*4+8]
0000008e inc eax
0000008f inc eax
00000090 mov dword ptr [ebp-0Ch],eax
for( int n = 0; n < TOTAL_NUM; n++ )
00000093 inc ebx
00000094 cmp ebx,5F5E100h
0000009a jl 00000064
Knight94 2006-08-20
  • 打赏
  • 举报
回复
我也写了一段程序来进行测试,除了减少对引用类型数据的访问外,同时要对局部变量的访问也要有很好的顺序,换句话说对于局部变量的访问连续性有利于性能的提升。

对比方法如下:
private void TestOne()
{
Debug.WriteLine( DateTime.Now.ToString( "HH:mm:ss" ) );
int i, t;
const int TOTAL_NUM = 100000000;
int[] factors = new int[TOTAL_NUM];
for( int n = 0; n < TOTAL_NUM; n++ )
{
i = factors[n];
t = i + 2;
i = i + 1;
}
Debug.WriteLine( DateTime.Now.ToString( "HH:mm:ss" ) );
}

private void TestTwo()
{
Debug.WriteLine( DateTime.Now.ToString( "HH:mm:ss" ) );
int i, t;
const int TOTAL_NUM = 100000000;
int[] factors = new int[TOTAL_NUM];
for( int n = 0; n < TOTAL_NUM; n++ )
{
i = factors[n] + 1;
t = factors[n] + 2;
}
Debug.WriteLine( DateTime.Now.ToString( "HH:mm:ss" ) );
}
AhBian 2006-08-20
  • 打赏
  • 举报
回复
一个程序就主要就这一个方法,测试的时间也仅是这个方法执行所需的时间,不包含其他时间。
应该不会有分别执行或者顺序执行的问题吧。
AhBian 2006-08-20
  • 打赏
  • 举报
回复
源代码中有一句:
factors[size - 1] += r;

这一句会导致 IL 代码多分配一个 int[] 变量。
相应地反编译后的 C# 代码为:
(numArray2 = numArray1)[(int) (ptr1 = (IntPtr) (num5 - 1))] = numArray2[(int) ptr1] + num4;

而把该句源代码改为:
factors[size - 1] = factors[size - 1] + r;
就不会这种情况的发生。

C# 代码究竟怎样写?写了四年 C#,我还懵哪。
Knight94 2006-08-20
  • 打赏
  • 举报
回复
你是分别执行还是先后执行

如果是后者的话,调换一下顺序看看
加载更多回复(25)

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧