Hello World
Spiga

.NET程序性能的基本要领

2014-05-14 22:18 by 老赵, 19055 visits

说起Roslyn大家肯定都已经有所耳闻了,这是下一代C#和VB.NET的编译器实现。Roslyn使用纯托管代码开发,但性能超过之前使用C++编写的原生实现。Bill Chiles是Roslyn的PM(程序经理,Program Manager),他最近写了一篇文章叫做《Essential Performance Facts and .NET Framework Tips》,其中总结了几条经验,目前是个CodePlex上的PDF文件,以后可能会发布在MSDN上。

他在文章里谈到以下几点:

  1. 不要进行过早优化。程序员有了一定经验以后,往往会对性能有所直觉,但也要避免盲目优化。
  2. 没有评测,便是猜测。例如,有的时候重复计算都比使用哈希表进行缓存来的快。
  3. 好工具很重要。这里他推荐了PerfView,这是个微软发布的免费工具,将来分析某些案例时我可能也会用到这个工具。
  4. 性能的关键,在于内存分配。凭直觉可能很多人会觉得编译器是一个CPU密集型的场景,但实际上它终究还是个IO密集型的程序。
  5. 其他一些细节。例如,对于字典的内存开销要有一些概念,还有例如我每次面试都会问到的class与struct的区别等等。

第4点值得多说几句。对于托管环境来说,GC对于性能的影响重大。假如一段程序写的不够GC友好,让GC发生的多,尤其是那种Stop-the-World GC,这对性能的影响远胜某些“多花了几条拷贝指令”之类的“探索”。而且很多时候,用户眼中的“性能”在于程序的“响应程度(responsiveness)”,一旦GC暂停了所有的线程,程序便很容易发生卡顿,这甚至不是通过简单评测程序性能能够体现出来的。

相较于Java平台来说,.NET已经是个相对GC友好的运行环境了。其中最重要的方面之一便是自定义值类型,即struct。struct让程序员进行一定程度上可控的内存分配,避免在堆上产生对象。而在Java中,只有几种原生类型是值类型,它们还不能包含成员。要知道在Java里无法使用一个未装箱的int值作为一个字典的键,这对一个.NET程序员来说可能很难想象,但事实便是如此。

当然,Java似乎已经有打算作这方面的改进,但离真正可用还遥遥无期。目前Java只能通过一些如逃逸分析的手段,发现某个对象不会被共享到堆上,于是便将其分配在栈上,避免对GC产生压力。

不过.NET提供再多对GC友好的功能,也抵不过开发人员的误用。Bill的文章里举了一些常见案例,这些其实都是每个.NET开发人员必须了解的基础。最后那个例子颇为有趣,他谈到,对于性能敏感的地方,有时候都要避免LINQ或Lambda。因为使用Lambda构造匿名函数时,编译器会产生闭包,因为所谓闭包,便是一个用来保存上下文的,分配在堆上的对象。此外,如List<T>的迭代器被有意实现为struct,但使用通用的LINQ接口,则会被转化为IEnumerable<T>IEnumerator<T>,进而产生装箱。

无独有偶,不久前@连城404在新浪微博上说到:

按照Michael的建议把HiveTableScan关键路径上的FP风格的代码换成while循环加可复用的mutable对象,扫表性能提升40%。”,这其实也正和这次的话题密切相关。

半夜不清醒,四则运算都算错了…发上条微博的时候实际上是提升了100%多点。之后继续蚊子腿上刮肉,不光是while循环,关键路径上的模式匹配代码也能刮出油水(例如省掉Array.unapplySeq调用开销)。目前使用LazySimpleSerDe的普通CVS表扫表性能提到2.2x,RCFile加上列剪枝可以提到3x。#Spark SQL#

Alan Perlis同样说过:

Lisp programmers know the value of everything but the cost of nothing.

可谓颇为有趣。常用的FP手段的确会带来性能开销,这是事实,不过假如你现在立即得出“不要用FP”或“还好没学FP”这样的结论,那我也只能用怜悯的眼光看着你了。

最后,您有减少内存分配,优化GC这方面的实践吗?不妨联系我吧,有机会我也会谈一下我在这方面的一些技巧和案例的。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

38 条回复

  1. 昂
    124.127.131.*
    链接

    2014-05-15 10:05:09

    很是期待下文啊,实际开发中对于拆箱装箱还比较注意,但是闭包这类就很随意了,即使有些方法提供了参数可以不用闭包也因为要强转一次而作罢。

    而实际开发中往往一个数据库索引,缓存带来的收益比去研究GC带来的收益大的多,所以上至领导下到小兵谁还会去关注GC呢

    就我的实际经验来讲,我"觉得"序列化(WCF、Memcache)对GC的压力是最大的

  2. 咖啡色
    205.156.160.*
    链接

    咖啡色 2014-05-15 17:26:56

    传说中的沙发?

  3. 咖啡色
    205.156.160.*
    链接

    咖啡色 2014-05-15 17:27:30

    老赵太坏了,不回复就看不见前面的回复吗?

  4. nihao
    219.127.93.*
    链接

    nihao 2014-05-15 17:31:34

    有A,B两个不同的C#程序,A产生了占用大量内存的DataTable对象后,1分钟后这个DataTable对象就可以设置为null,但是CLR并不会立即对这个对象进行GC。那么在未GC的情况下,如果这时B程序也需要使用大量内存,那么CLR会回收A进程DataTable占用的内存吗?

    反之,如果为了保证B进程正常使用,在A进程的DataTable设置为NULL后,使用GC.Collect(),这是个好的做法吗?

    我认为是不需要GC.Collect(),都为但是却无法具体说出理由。真心求详解。

  5. 老赵
    admin
    链接

    老赵 2014-05-15 21:24:04

    @咖啡色

    估计第一次只是没加载出来吧。

  6. 老赵
    admin
    链接

    老赵 2014-05-15 21:26:02

    @nihao

    这东西你自己试验下呗。

  7. 流光小弟
    121.231.163.*
    链接

    流光小弟 2014-05-16 17:34:27

    赵大哥,请教个问题,以前多次留言,您都没能看到,FluentValidation(验证框架),其利用表达式语法链式编程,喜欢表达式,喜欢链式的感觉, 但心中有一个疑问:IIS有个开启多工作进程的功能,一个进程管一块内存,相互独立,用这框架会不会有问题?

    // https://fluentvalidation.codeplex.com/
    public class OrdersValidator:AbstractValidator<Orders> 
    { 
        public  OrdersValidator() 
        { 
            RuleFor(orders => orders.CustomerID).NotEmpty().Length(2, 20).WithName("CustomerID"); 
            RuleFor(orders => orders.DisCount).GreaterThanOrEqualTo(0).LessThan(1).WithMessage("discount must between 0 and 1!"); 
            RuleFor(orders => orders.OrderDate.Date).GreaterThanOrEqualTo(DateTime.Now.Date).WithName("Order Date"); 
        } 
    }
    
  8. 老赵
    admin
    链接

    老赵 2014-05-17 00:24:11

    @流光小弟

    为什么你会觉得有问题,你是指哪方面问题?

  9. 链接

    Haiyang Zhu 2014-05-19 10:50:34

    PM不是project manager 么。。

  10. 流光小弟
    58.241.92.*
    链接

    流光小弟 2014-05-19 21:16:07

    程序的实现用到了委托链,这些东西应该是存在于内存中,IIS有个开启多工作进程,意味着程序有多个进程,每个进程的内存是独立的,那么会不会出现类似多个进程间无法共享状态信息(比如session),丢失找不到情况

  11. 老赵
    admin
    链接

    老赵 2014-05-20 10:45:53

    @流光小弟

    这就看你是怎么做的了,加入你要共享Session里的信息,但没有实现正确的话,那的确就会共享失败了。

  12. laobi
    124.205.175.*
    链接

    laobi 2014-05-20 15:25:43

    我怎么注册用户?

  13. 链接

    wei 2014-05-22 21:49:07

    Roslyn使用纯托管代码开发,但性能超过之前使用C++编写的原生实现。

    请给出证据,我怀疑Roslyn开发团队都不一定有。

  14. 老赵
    admin
    链接

    老赵 2014-05-24 23:37:50

    @wei

    找不到了,至少是内部邮件里说的。性能这么重要的东西,Roslyn团队怎么可能不做性能比较。别急,正式发布了以后各种消息会跟上的……

  15. maomao
    8.35.201.*
    链接

    maomao 2014-05-25 13:12:04

    不知咋滴,我这几天访问老赵的博客还要用goagent代理才行

  16. 老赵
    admin
    链接

    老赵 2014-05-25 21:50:29

    @maomao

    什么网络?

  17. 文少
    14.150.76.*
    链接

    文少 2014-05-26 09:52:46

    Roslyn使用纯托管代码开发,但性能超过之前使用C++编写的原生实现。

    这里说的性能是指编译器本身的性能(编译程序更快),还是编译出来的程序的性能(程序运行得更快)?

  18. 链接

    Ivony 2014-05-26 14:50:48

    http://zrx.zhaojie.me/20140515/ 这个文章下面的阅读原文链接到了这里,请检查一下是否链错了。

  19. 老赵
    admin
    链接

    老赵 2014-05-26 18:56:54

    @文少

    编译器本身执行的效率,不是编译出的代码的效率。

  20. 老赵
    admin
    链接

    老赵 2014-05-26 18:58:05

    @Ivony

    哦也你没看清内容…

  21. 链接

    wen zheng 2014-05-26 20:38:07

    我用的网络是联通的,在家里在公司都需要挂代理,但今天就没用,时好时坏,一阵阵的。

  22. mathgl
    1.36.236.*
    链接

    mathgl 2014-05-27 21:01:04

    java也提供unsafe 方法用来访问raw memory。有不少库用它来管理内存,减少gc heap的使用。

    不过这种用法不是写库的一般用不上。

  23. Kaka
    116.6.88.*
    链接

    Kaka 2014-07-07 13:42:49

    原来11年就开始看老赵的博客,后面没专注.NET就没看了,现在又来捧场了,请原谅我是个潜水族

  24. rxaa
    211.103.237.*
    链接

    rxaa 2014-07-10 09:49:25

    c++有基于模板构造于栈上的静态lambda闭包,性能不但无损,内联后还有提升,而且可以通过raii来代替gc以及所有资源的自动化管理. 可惜c#没有确定性析构功能,无法实现raii,而且gc也只能托管内存,很多情况下反而是个负担. 感觉语言都应该学学c++的基本原则:抽象不应该影响效率

  25. 永远的阿哲
    58.249.96.*
    链接

    永远的阿哲 2014-08-30 16:46:16

    老赵能否翻译《Pro .NET Performance》?我完完整整的听过您在WebCast上讲的Asp.Net Mvc 1.0,那是相当的好。期望您的vNext相关的教程

  26. 链接

    Ho Henry 2014-09-19 19:27:34

    .Net优化这个话题太大了,足够出本书了。感觉.Net开发效率很高,但如果是性能敏感的应用,处处是GC挖的坑。

    举个简单了例子:

    for (int i = 0; i < 1e6; i++)
    {
        foreach (var item in items)
        {
        }
    }
    

    这里面都有一个GC的坑。

  27. 老赵
    admin
    链接

    老赵 2014-09-21 21:28:40

    @Ho Henry

    什么坑?

  28. 黑耗子
    111.207.228.*
    链接

    黑耗子 2014-11-06 16:12:13

    FP手段是什么意思?

  29. linustd
    123.126.85.*
    链接

    linustd 2015-10-07 09:21:41

    要要要,怎么还写上Java了,不是说 Java 是一个 dead language 吗?

    自己闪自己嘴巴子,哈哈哈哈

    人家 UNIX 平台,技术都是沉淀了几十年,公开源代码让你研究学习的,某些贱货反而不学习研究。

    微软那破技术,垃圾一对,藏着掖着怕别人看见,某些贱货反而使出吃奶的劲偷窥。

  30. 老赵
    admin
    链接

    老赵 2015-11-02 06:46:50

    @linustd

    再怎么样也比你都快40了还学不会Java拿到月薪两万的工作还过不了试用期要强啊。

  31. zoroseo2020
    124.156.224.*
    链接

    zoroseo2020 2020-10-16 00:18:21

    PM不是project manager 么 彩票 福彩双色球 幸运飞艇

  32. droggo
    136.158.30.*
    链接

    droggo 2021-01-11 05:01:14

    Hopefully I could find the answers here. Thank you for sharing this. Glad I saw this post. I’ve been searching a lot lately. But I haven’t found the right answers. While I was searching I found this [url=https://among-us.io/]download for computer[/url] And also this [url=https://chrome.google.com/webstore/detail/among-us-online/nhklobelplcndebifbcmideenegaikgm]https://chrome.google.com/webstore/detail/among-us-online/nhklobelplcndebifbcmideenegaikgm[/url]

  33. 招投标
    221.232.104.*
    链接

    招投标 2021-01-27 17:47:49

    文章很棒 支持一下 很喜欢博主的态度

  34. kericnnoe
    111.242.194.*
    链接

    kericnnoe 2022-12-21 04:05:56

    DG百家樂出金都是真實的,公平、公正、公開

  35. zoroseo2020
    35.215.141.*
    链接

    zoroseo2020 2023-05-03 14:27:04

    曾经笃定是正确的东西,其实未必是对的;以为特别重要的事情,也没有想象中那样重要;真心对一个人,可能他们并不在意你的好。人生多是事与愿违,不要随便对谁就掏心掏肺,也不用太固执,没有什么是不会改变的。 幸运时时彩走势图 台湾宾果走势图 SG飞艇走势图

  36. Air Jordan
    147.185.242.*
    链接

    Air Jordan 2025-02-12 13:46:14

  37. Jordan 1
    216.126.233.*
    链接

    Jordan 1 2025-03-27 00:22:49

  38. Yeezy Slides
    104.234.236.*
    链接

    Yeezy Slides 2025-04-26 20:38:39

    Love it or hate it, the Yeezy Foam Runner has become a cultural phenomenon. From its polarizing design to its sky-high resale value, this shoe is more than just footwear—it’s a statement. Whether you’re a hypebeast, a sustainability advocate, or just someone who loves comfy kicks, here’s why the Foam Runner deserves your attention (and maybe a spot in your closet).

    1. The Design: “Ugly” Never Looked This Good When Kanye West first dropped the Foam Runner in 2020, critics called it the “weirdest Yeezy ever” 4. But fast-forward to today, and its chunky, alien-esque silhouette has become a streetwear staple. The shoe’s one-piece EVA foam construction features bold cutouts for breathability and a futuristic aesthetic that screams avant-garde 79.

    Why it works:

    Versatility: Pair it with socks for a cozy fall vibe or go barefoot for summer beach days.

    Bold Aesthetics: The organic curves and “biomorphic” design make it stand out in a sea of basic sneakers 4.

    Unisex Appeal: Available in adult, kid, and infant sizes, it’s a family flex 79.

    1. Sustainability Meets Hype Kanye promised eco-friendly innovation, and the Foam Runner delivers. Made with algae-based foam and recycled materials, each pair helps clean lakes by repurposing harmful algae 79. Even the packaging is minimalist to reduce waste.

    But let’s keep it real: While the eco-credentials are impressive, limited drops and insane resale prices (up to 10x retail!) have left fans frustrated 34. Original retail was 75 – 75–80, but scarcity pushed some colorways to $6,000+ in resale markets 34.

    1. Colorways That Keep Us Obsessed The Foam Runner’s ever-expanding palette is a masterclass in hype. Recent drops include:

    “Ochre” & “MX Cream Clay”: Earthy tones perfect for minimalist outfits (August 2 drop, $80) 210.

    “Mineral Blue”: A moody midnight hue for stealthy flexing 5.

    “Onyx”: Sleek all-black for the “dark mode” enthusiasts (released June 2022) 7.

    “MIST”: A misty brown-gray blend that sold out in seconds 9.

    Styling hacks:

    Socks + Sandals 2.0: Throw on colorful crew socks for a retro vibe.

    Techwear Essential: Match it with cargo pants and a puffer vest.

    Beach-Ready: Water-resistant material means you can rock it poolside 7.

    1. The Hype Train Isn’t Slowing Down From Walmart’s $24 knockoffs (shut down after legal battles 1) to Chinese brands like Peak copying the design 3, the Foam Runner’s influence is undeniable. But nothing beats the OG.

    Why it’s worth the hunt:

    Cultural Impact: It redefined “ugly chic” and inspired a wave of (hole-punched shoes) 6.

    Collector’s Item: Early colorways like the “Marbled” edition are grails for sneakerheads 4.

    Final Word: How to Cop Want to avoid resale scams? Stay alert for restocks! New colorways like “MXT Moon Grey” (2023) and future drops are your best shot at scoring retail 6. Set those app notifications, pray to the Yeezus, and remember: in the world of Foam Runners, patience pays.

    TL;DR: The Yeezy Foam Runner is weird, wonderful, and the shoe of the decade. Grab a pair, wear it with confidence, and join the cult.

    Ready to flex? Drop your Foam Runner stories in the comments!

    Yeezy Slides
    Yeezy Official Website
    Jordan 1
    Jordan 12
    Jordan 11
    Yeezy Slides
    NFL Shop
    NFL Store
    Yeezy Slides
    Yeezy 350
    Jordan 4
    Yeezy Supply
    Jordan 4
    Yeezy Website
    Yeezy Slides
    Jordan 12
    Jordan 11
    Jordan 1
    Air Jodan
    NFL Jerseys
    Yeezy Slides
    Yeezy Supply
    Yeezy Store
    Yeezy Slides
    Louis Vuitton Outlet
    Louis Vuitton Outlet
    Yeezy Shoes
    Yeezy Slides
    Yeezy 350
    Yeezy Slides
    Yeezy Adidas
    Yeezy Official Website
    Adidas Yeezy
    Yeezy Supply
    Yeezy Slides
    Yeezy Official
    Yeezy 350
    Yeezy Slides

    Tags:Yeezy Shoes,Yeezy Slides,Jordan 1,Air Jordan,Jordan

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我