提高程序运行效率

*************************参考文章***************************************************************************

(1)提高程序效率的 10 种简单方法(转)提高程序运行速度 - 开发者博客

(2)改善C#程序,提高程序运行效率的50种方法 - 一杯清酒邀明月 - 博客园

(3)

(4)

(5)

(6)

**************************************************************************************************************

(1)通过Stopwatch来监视到底是哪个地方耗时比较长。

(2)优化代码的最佳方法是使用分析器来确定代码的哪些部分很慢.有许多可用于.NET代码的优秀分析器,它们可以帮助确定程序中的瓶颈.

一个好的分析器会告诉你统计数据,例如函数执行了多少次,函数的平均运行时间,函数的峰值运行时间,函数的总运行时间等等.一些分析器甚至会为你绘制图形,这样你就可以直观地看到程序的哪些部分是最大的瓶颈,你可以深入研究子函数调用.

如果没有分析,你很可能会错误地认为程序的哪一部分很慢.

用于.NET的优秀和免费分析器的一个例子是EQATEC Profiler.程序员在猜测代码热点的位置方面是出了名的不好.在测量之前不要费心去尝试优化.通常会浪费时间.专注于良好的架构.

(3)关于这个问题,最重要的一点是:不要过早优化!

只有一个优化时间,即存在当前工作实施无法满足的性能限制时.然后你应该拿出一个分析器,检查代码的哪些部分很慢,以及如何解决它们.

在编写第一个版本时考虑优化主要是浪费时间和精力.

  • 相反,在设计阶段,大多数实质性的优化都会发生. (3认同)
  • "在编写第一个版本时考虑优化主要是浪费时间和精力." 是的,不是.如果你的意思是"++ i"和"i ++"这样的东西,我同意.另一方面,如果你做了很多优化,你就会学会避免导致性能不佳的模式,即过度的数据结构设计,过度依赖通知,过度抽象,导致西兰花式调用树. (

一、尽量多用using

using的使用会减少对象图的复杂。

二、使用线程

使用线程(多核的话可以加快速度,单核的话不会。反而影响了效率,提高响应而已)提高CPU利用率,从这个角度看,也可以说一定程度提高运行的速度。

对于耗时的操作,需要另开线程处理,并能让用户看到处理过程,用户可以干预,例如取消操作等
不让主界面停滞。

三、对大文件或大量数据,能分段处理分段处理。

对于不会变量的值尽量多用const 。

对象不用时的及时释放

  将一个成员方法注册到某个对象的事件会造成后者持有前者的引用。在事件注销之前,前者不会被垃圾回收。

//关闭窗体时及时释放事件
private void Form1_FromClosed()
{
……
//关闭窗体时及时释放事件
CommandRemotingContext.CmdChanged -= new ReciverCmdStateChangedEventHandler(this.CommandRemotingContext_CmdChanged);
……
}

提高应用程序运行效率,主要还是从你的逻辑入手,把复杂任务拆分开来,能够利用IOCP的地方就用IOCP,在多CPU或多核机器上,按照核心数把任务分解到每个单独的核心上去执行

三、循环引发的讨论1(循环内定义,还是循环外定义对象)

请看下面的两段代码:

代码1:

ClassTest CT;
for(int i = 0; i < 100  ibr     />{
CT = a;
//do something
}
代码2:
for(int i = 0; i < 100  ibr     />{
ClassTest CT = a;
//do something
}

你会觉得哪段代码的运行效率较高呢?代码1科学家是代码2?其实这种情况下,哪段代码的效率更高是不确定的,或者说是由这个类ClassTest本向决定的,分析如下:

对于代码1:需要调用ClassTest的构造函数1次,赋值操作函数(operator=)100次;对于代码2:需要高用(复制)构造函数100次,析构函数100次。

如果调用赋值操作函数的开销比调用构造函数和析构函数的总开销小,则第一种效率高,否则第二种的效率高。

四、循环引发的讨论2(避免过大的循环)

现在请看下面的两段代码,

代码1:

for(int i = 0; i < n  ibr     />{
fun1();
fun2();
}

代码2:

for(int i = 0; i < n  ibr     />{
fun1();
}
for(int i = 0; i < n  ibr     />{
fun2();
}

注:这里的fun1()和fun2()是没有关联的,即两段代码所产生的结果是一样的。

以代码的层面上来看,似乎是代码1的效率更高,因为毕竟代码1少了n次的自加运算和判断,毕竟自加运算和判断也是需要时间的。但是现实真的是这样吗?

这就要看fun1和fun2这两个函数的规模(或复杂性)了,如果这多个函数的代码语句很少,则代码1的运行效率高一些,但是若fun1和fun2的语句有很多,规模较大,则代码2的运行效率会比代码1显著高得多。可能你不明白这是为什么,要说是为什么这要由计算机的硬件说起。

由于CPU只能从内存在读取数据,而CPU的运算速度远远大于内存,所以为了提高程序的运行速度有效地利用CPU的能力,在内存与CPU之间有一个叫Cache的存储器,它的速度接近CPU。而Cache中的数据是从内存中加载而来的,这个过程需要访问内存,速度较慢。

这里先说说Cache的设计原理,就是时间局部性和空间局部性时间局部性是指如果一个存储单元被访问,则可能该单元会很快被再次访问,这是因为程序存在着循环。空间局部性是指如果一个储存单元被访问,则该单元邻近的单元也可能很快被访问,这是因为程序中大部分指令是顺序存储、顺序执行的,数据也一般也是以向量、数组、树、表等形式簇聚在一起的。

看到这里你可能已经明白其中的原因了。没错,就是这样!如果fun1和fun2的代码量很大,例如都大于Cache的容量,则在代码1中,就不能充分利用Cache了(由时间局部性和空间局部性可知),因为每循环一次,都要把Cache中的内容踢出,重新从内存中加载另一个函数的代码指令和数据,而代码2则更很好地利用了Cache,利用两个循环语句,每个循环所用到的数据几乎都已加载到Cache中,每次循环都可从Cache中读写数据,访问内存较少,速度较快,理论上来说只需要完全踢出fun1的数据1次即可。

五、局部变量VS静态变量

尽量用临时变量和局部变量,不用全局变量和静态变量。

很多人认为局部变量在使用到时才会在内存中分配储存单元,而静态变量在程序的一开始便存在于内存中,所以使用静态变量的效率应该比局部变量高,其实这是一个误区,使用局部变量的效率比使用静态变量要高。

这是因为局部变量是存在于堆栈中的,对其空间的分配仅仅是修改一次esp寄存器的内容即可(即使定义一组局部变量也是修改一次)。而局部变量存在于堆栈中最大的好处是,函数能重复使用内存,当一个函数调用完毕时,退出程序堆栈,内存空间被回收,当新的函数被调用时,局部变量又可以重新使用相同的地址。当一块数据被反复读写,其数据会留在CPU的一级缓存(Cache)中,访问速度非常快。而静态变量却不存在于堆栈中。

可以说静态变量是低效的。

六、避免使用多重继承

在C++中,支持多继承,即一个子类可以有多个父类。书上都会跟我们说,多重继承的复杂性和使用的困难,并告诫我们不要轻易使用多重继承。其实多重继承并不仅仅使程序和代码变得更加复杂,还会影响程序的运行效率。

这是因为在C++中每个对象都有一个this指针指向对象本身,而C++中类对成员变量的使用是通过this的地址加偏移量来计算的,而在多重继承的情况下,这个计算会变量更加复杂,从而降低程序的运行效率。而为了解决二义性,而使用虚基类的多重继承对效率的影响更为严重,因为其继承关系更加复杂和成员变量所属的父类关系更加复杂。

八、减少除法运算的使用

无论是整数还是浮点数运算,除法都是一件运算速度很慢的指令,在计算机中实现除法是比较复杂的。所以要减少除法运算的次数,下面介绍一些简单方法来提高效率:

1、通过数学的方法,把除法变为乘法运算,如if(a < b/c),如果a、b、c都是正数,则可写成if(a*c < b);

2、让编译器有优化的余地,如里你要做的运算是int型的n/8的话,写成(unsigned)n/8有利于编译器的优化。而要让编译器有优化的余地,则除数必须为常数,而这也可以用const修饰一个变量来达到目的。

九、将小粒度函数声明为内联函数(inline)

正如我们所知,调用函数是需要保护现场,为局部变量分配内存,函数结束后还要恢复现场等开销,而内联函数则是把它的代码直接写到调用函数处,所以不需要这些开销,但会使程序的源代码长度变大。

所以若是小粒度的函数,如下面的Max函数,由于不需要调用普通函数的开销,所以可以提高程序的效率。

int Max(int a, int b)
{
return a<b?a:b;
}

十、多用直接初始化

与直接初始化对应的是复制初始化,什么是直接初始化?什么又是复制初始化?举个简单的例子,

ClassTest ct1;
ClassTest ct2(ct1);    //直接初始化
ClassTest ct3 = ct1;    //复制初始化

那么直接初始化与复制初始化又有什么不同呢?直接初始化是直接以一个对象来构造另一个对象,如用ct1来构造ct2,复制初始化是先构造一个对象,再把另一个对象值复制给这个对象,如先构造一个对象ct3,再把ct1中的成员变量的值复制给ct3,从这里,可以看出直接初始化的效率更高一点,而且使用直接初始化还是一个好处,就是对于不能进行复制操作的对象,如流对象,是不能使用赋值初始化的,只能进行直接初始化。

*************************************************************************************************************

我也谈 C# 的执行效率到底有多高

*************************************************************************************************************

最近大家都在讨论C#的执行效率问题。由于采用的测试方法不同,测试结果差异很大。有些人得到结论,C#的速度竟然比 C++ 慢 20 倍!但是这样的测试是没有准确性的。

为什么这么说呢?语言的执行效率是要考虑编译到机器码后用户代码执行的紧凑性和高效性,而不是代码本身的执行速度。因为代码可以优化,.NET framework 也在升级,但编译的机器码却是死的。编译机制才是影响执行效率的最重要的原因。其它原因都不是根本原因

单从计算和执行的角度来说,C#应该还是比较快的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值