新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Dot NET,C#,ASP,VB 』 → 也谈.Net中的效率问题 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 2315 个阅读者  浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 也谈.Net中的效率问题 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     admin 帅哥哟,离线,有人找我吗?
      
      
      
      威望:9
      头衔:W3China站长
      等级:计算机硕士学位(管理员)
      文章:5255
      积分:18407
      门派:W3CHINA.ORG
      注册:2003/10/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给admin发送一个短消息 把admin加入好友 查看admin的个人资料 搜索admin在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给admin  访问admin的主页 引用回复这个贴子 回复这个贴子 查看admin的博客楼主
    发贴心情 也谈.Net中的效率问题


    发信人: flier (小海->找啊找工作 :)), 信区: DotNET        
    标  题: 也谈.Net中的效率问题
    发信站: BBS 水木清华站 (Mon Apr  8 02:26:01 2002)

    也谈.Net中的效率问题(草稿)

    Flier Lu

    前面有朋友提到.Net中的效率问题,
    我这里就我的一些了解结合他的关注点做一些介绍,
    希望对大家提高对.Net的认识有帮助 :)

    首先是.Net代码的执行效率。如果单单只是代码运行的话,
    因为.Net是通过JIT编译成本地代码后执行,因此执行效率
    并不比普通的VC/Delphi程序慢多少,比如MS做评测
    C#的XML库实现效率比VC还要高,当然这是特殊情况。

    而实际上很多朋友反映.Net程序运行很慢,的确如此,
    为什么呢?如何避免呢?

    因为.Net程序与普通程序不同,他首要的任务是保证代码的
    稳定性,因此将类型检查、缓冲区溢出检查、数组越界检查、
    数学运算溢出检查,加上GC、安全认证等等,效率不低才怪。
    这些新特性在提高代码质量的同时是以运行时效率作为代价的。

    如果你不需要这些特性,强烈建议你使用Unmanaged C++
    将核心代码以传统形式开发编译执行,只是在对效率不敏感的
    部分使用.Net来实现。这种方式更多的是需要了解两种C++
    之间的不同与交互,我们以后有时间再详谈。

    这里我关注的是如何提高必须使用.Net架构程序的运行时效率。
    这方面需要关注的几点前面那位朋友其实基本上都提到了

    1.自动内存管理,也就是GC
    2.配件Assembly的装载
    3.JIT编译的效率
    4.各种运行时的检测
    5.安全权限验证
    6.各种小细节

    因为这里不是写书,我只能各个点大概提一下,有兴趣的朋友
    可以自行查阅相关资料了解详情。

    1.自动内存管理,也就是GC

    现代编程语言发展的一个重要趋势是使用自动内存管理,也就是GC

    来摆脱依赖程序员人的因素的手工内存管理机制,从最开始的
    智能指针,到基于缓冲池的内存管理,到GC,一步一步在发展。

    GC的好处与坏处我这里就不多说了,大概介绍一下GC在.Net中的实现机制,
    以及带来的对效率方面的影响好了,说不清的可以re此文和我讨论。

    在.Net中,MS实际上是为GC做了相对多的效率上的优化的。

    首先,在GC中,分配内存无需象传统C++/Delphi那样遍历一个可用内存链表,
    而是有一个指针执行Managed Heap的使用到的末尾,直接通过指针+Size
    来分配内存,效率达到最高。当然如果没有足够内存要引发强制性GC就ft了,
    因此在进行注重效率部分之前,最好提前分配好需要用的对象、数组等等。
    或者在之前使用GC.GetTotalMemory估算内存是否足够使用。
    如果实在不够可以事先强制性GC.Collect()回收内存
    总之,尽量避免在分配堆内存时引发GC。

    注意:只有引用类型如类、数组才在堆里分配内存,值类型如结构、int等是
    直接在堆栈里面分配空间。

    其次,在GC中,所有实现了Object.Finalize()方法的类,在析构时需要
    进行特殊处理。在C#里面使用类似C++析构函数的诸如 ~MyClass() 实现。
    普通的对象GC一旦发现其不可到达,马上释放其内存;实现了Object.Finalize()
    方法的对象,则被丢入一个列表,在第一遍GC完成之后逐个调用Finalize函数
    再放回GC的队列中,在第三次时才被真正释放。

    因此如果没有必要,绝对不要使用Object.Finalize()图方便,如果实在要
    释放unmanaged resource,加一个Close或者Dispose方法好了,手工处理

    此外如果频繁使用或者创建麻烦的对象,可以采用对象池的方法大大提高效率,
    在其析构时放回对象池,使用时直接从池里拿,也可以大大提高效率。
    过两天有时间我给个例子再说……

    再就是GC的分代机制,把所有对象分为若干代Generation,
    用GC.MaxGeneration可以取得最大代数,一般为3代,0-2
    .Net的GC的实现思路是越晚建立的对象越可能被先释放
    因此他将堆分为三代,每次缺省只处理第0代,所有不可访问对象回收,
    可访问对象代数加一。这样就大大优化了GC时的工作量
    我们也可以使用此机制,避免强制性的GC.Collect()回收全部堆
    而一次只操作一代如GC.Collect(0);

    再就是比较高级的优化手段弱引用,Weak References,
    这里就不多说了,以后有时间再详谈

    2.配件Assembly的装载

    配件Assembly的装载也是影响效率的一大问题,特别是动态装载,
    对效率影响更大。因为在装载配件时,CLR要分析配件的Metadata
    要对不同配件之间进行关联,要检查配件的类型安全性,加上后面
    要提到的进行静态安全验证等等,速度还是很慢的。

    因此要减少动态的配件使用,尽量用静态连接,在程序开始时完成这些
    麻烦事情。对实在要动态装载的配件,尽量把公共部分提取出来等等。
    当然就算是静态连接,在载入配件时还是要花费相当时间,一个简单
    的解决办法就是在程序开始对效率没有要求时,写一些无用的代码
    去调用配件中等会要在注重效率代码中用到的类,强制CLR载入。
    比如获取配件中类的类型信息等等

    3.JIT编译的效率

    JIT编译来说,是用到哪里编译到哪里,编译后代码在内存中缓存起来
    因为一次编译代码不多,每次效率较高;同时也因为编译次数较多,
    外加的负荷也较重。

    不过解决办法也很简单,用ngen工具强制JIT预编译.Net程序的本地
    代码镜像,并以文件形式缓存起来,这样既可以享受.Net程序的诸多优势,
    又可以享受本地代码直接运行的高效率。

    实际上.Net框架里面很多类都是被ngen预处理过的,保证其效率。
    可以用ngen /show命令查看已经被预编译的配件。

    4.各种运行时的检测

    就JIT编译后代码来说,很大的影响效率的问题是各种运行时检测。
    有些是不可避免的,如类型安全、数组越界;有些是可以选择的,
    如数学运算溢出检查、缓冲区溢出检测等等,可以根据需要关闭之。
    这种检测对计算密集型的程序打击最大,往往一个很简单的算法
    里面被加进了一堆乱七八糟的东东。最简单的解决办法就是用
    unmanaged c++来写,避开这些检测。

    5.安全权限验证

    安全权限验证对企业级应用来说至关重要,但其对效率的影响与其
    功能强大成反比。比如你要检测一个方法调用者的权限,可能就需要
    遍历整个stack list,检测每个调用者是否有相应权限,
    整个过程耗时巨大。

    解决办法一是尽量少用,只在必要的地方用。二是权限尽量限制窄。
    三是尽量以静态验证(以attribute方式声明)代替动态验证
    (以普通类形式使用),将大部分工作放到载入配件时

    此外还可以使用一些高级的优化手段,如指定验证的范围,
    缺省是堆栈列表中所有调用者,可以指定到一层,大大减少
    消耗时间,但代价是安全性降低,可能出现安全漏洞
    (程序A使用有权限的程序B来调用程序A没有权限访问的程序C)

    6.各种小细节

    算了,懒得写了,睡觉了…… :)

    上面大概从较高的层面对.Net中效率问题进行了一些介绍,
    以后有时间再写一篇从较低的代码层面的解决思路。

    --
    .  生命的意义在于   /\   ____\ /\_ \   /\_\                             .  
    .      希望         \ \  \___/_\/\ \   \/_/__     __    _ _★           .  
    .      工作          \ \   ____\\ \ \    /\  \  /'__`\ /\`'_\           .  
    .    爱你的人         \ \  \___/ \ \ \___\ \  \/\  __//\ \ \/           .  
    .   和你爱的人         \ \___\    \ \_____\ \__\ \____\ \ \_\           .  
    .      ……             \/___/     \/_____/\/__/\/____/  \/_/ @126.com.  


    ※ 来源:·BBS 水木清华站 smth.org·[FROM: 61.183.136.8]
    返回上一页
    回到目录
    回到页首
    下一篇


       收藏   分享  
    顶(0)
      





    关闭广告显示

    ----------------------------------------------

    -----------------------------------------------

    第十二章第一节《用ROR创建面向资源的服务》
    第十二章第二节《用Restlet创建面向资源的服务》
    第三章《REST式服务有什么不同》
    InfoQ SOA首席编辑胡键评《RESTful Web Services中文版》
    [InfoQ文章]解答有关REST的十点疑惑

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/9 2:26:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/6/21 20:12:45

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms