代码改变世界

随笔分类 - 01. DotNet框架

分清“语言/规范”以及“平台/实现”,以及跨平台.NET开发

2011-01-14 01:52 by Jeffrey Zhao, 25870 阅读, 收藏, 编辑
摘要:在许多年前,“语言”就等同于“平台”,例如C,C++以及最早的Ruby和Python等等。但是随着技术发展,出现了一些通用的平台,例如.NET和Java,逐渐这些平台上的语言也越来越多。再后来,某些语言在不同平台上的实现也越来越多,事情也变得有些复杂。技术在发展,但是从目前社区的讨论中,我发现许多朋友的观念还没有跟上。简单地说,如今的观念,一定要从“语言即平台”切换成“语言及平台”,当分清“语言”和“平台”这两个不同事物之后,许多问题才能讨论地清楚。而且,这点对于.NET程序员来说尤为重要,因为C#语言可以说是目前“平台”、“实现”最为广泛的“语言”之一了。 阅读全文

第三届nBazaar技术交流会开始报名

2010-12-21 00:49 by Jeffrey Zhao, 9184 阅读, 收藏, 编辑
摘要:为了错开年底密集的技术会议,第三届nBazaar技术交流会(即前“盛大创新院赞助的.NET技术交流会”)将于2011年1月15日举行。第三届的交流会将继续以往四场高质量的演讲,这也是确定nBazaar名称之后的第一次活动,希望nBazaar能够真正成为“集市”般热闹的社区活动。从现在开始,nBazaar技术沙龙的相关信息将逐渐集中至独立域名中,欢迎关注。 阅读全文

NDC 2010视频下载:看看其他微软平台程序员们都在做什么

2010-07-13 15:19 by Jeffrey Zhao, 12451 阅读, 收藏, 编辑
摘要:NDC(Norwegian Developers Conference,挪威开发者大会)是一年一度的挪威最大的微软平台开发者大会,内容丰富,讲师阵容强大。NDC与PDC同为高端技术会议,但NDC与PDC的不同之处在于,PDC是微软官方会议,主要是面向微软资深产品的深入探讨。而NDC涉及的内容则广泛的多,包括了我所感兴趣的Java、Mono、IronRuby/Ruby on Rails、NoSQL方面的内容。这也就像我一直强调的那样,微软技术社区非常开放,微软平台上的太多程序员都能够非常热情地拥抱其他平台的技术。那些认为微软技术社区是井底之蛙的兄弟,殊不知你们的嘲笑反而体现了自身的狭隘。 阅读全文

F#与ASP.NET(2):使用F#实现基于事件的异步模式

2010-04-05 20:46 by Jeffrey Zhao, 7274 阅读, 收藏, 编辑
摘要:在上一篇文章中,我们的简单讨论了.NET中两种异步模型以及它们在异常处理上的区别,并且简单观察了ASP.NET MVC 2中异步Action的编写方式。从中我们得知,ASP.NET MVC 2的异步Action并非使用了传统基于Begin/End的异步编程模型,而是另一种基于事件的异步模式。此外,ASP.NET MVC 2对于这种异步模式提供了必要的支持,使此方面的程序设计变得相对简单一些。但是,简单的原因主要还是在于已经由其他组件提供了良好的,基于事件的异步模式。那么现在我们就来看看一般我们应该如何来实现这样的功能,以及F#是如何美化我们的生活的吧。 阅读全文

盛大创新院赞助.NET技术会议意见征询

2010-03-26 15:54 by Jeffrey Zhao, 9743 阅读, 收藏, 编辑
摘要:各位可能大都知道,我于不久前加入了盛大创新院。最近我了解到,创新院这边对于社区开展技术会议的活动也是相当支持的,并且对每个社区的会议会有资金和人员上的支持。这几天我和副院长聊了一下,他表示只要组织得当,创新院也支持把技术交流会办成一个有规律的活动,定期举行。事实上,创新院已经赞助过多次Flash及产品设计方面的技术会议。当然,会议的目的是进行技术交流,对观众自然是完全免费的。因此,我打算在5月或6月份在上海举办一次.NET技术会议,在此征求一下您的意见。 阅读全文

为什么JVM上没有C#语言?浅谈Type Erasure特性

2010-02-22 23:50 by Jeffrey Zhao, 16275 阅读, 收藏, 编辑
摘要:JVM上目前已经有许多语言了:JRuby,Jython,也有一些特定于JVM平台的语言,如Scala和Groovy等。但是,为什么JVM上没有C#语言呢?按理说,这门和Java十分相似,却又强大许多的语言更容易被Java程序员接受才对。有人说,Sun和微软是对头,怎么可能将C#移植到JVM平台上呢?嗯,有道理,但是为什么社区里也没有人这么做呢(要知道JVM上其他语言都是由社区发起的)?其实在我看来,这是受到了技术方面的限制。例如:Type Erasure。 阅读全文

浅谈字节序(Byte Order)及其相关操作

2010-02-10 23:05 by Jeffrey Zhao, 20571 阅读, 收藏, 编辑
摘要:最近在为Tokyo Tyrant写一个.NET客户端类库。Tokyo Tyrant公开了一个基于TCP协议的二进制协议,于是我们的工作其实也只是按照协议发送和读取一些二进制数据流而已,并不麻烦。不过在其中涉及到了“字节序”的概念,这本是计算机体系结构/操作系统等课程的基础,不过我还是打算在这里进行简单说明,并且对.NET中部分类库在此类数据流处理时的注意事项进行些许记录与总结。 阅读全文

李笑来激起千层浪,赵姐夫力拒众强敌

2010-02-03 00:49 by Jeffrey Zhao, 21797 阅读, 收藏, 编辑
摘要:昨天晚上,李笑来(@xiaolai)老师的无心之语却引起了推特上一次前后长达1个多小时的讨论——当时他似乎只是随手发了一句“Apple告诉我们的铁律是:表面功夫一定要做足”便不见了踪影,但是这句话立即引起了众果粉的共鸣。此后,我(@jeffz_cn)的一句评论又引起了众人对微软开发平台的批判之声。在这次讨论中,几乎只有我孤军奋战为.NET平台进行辩解。因此事后有人给出一副对联为此次争论作出总结:李笑来激起千层浪,赵姐夫力拒众强敌。 阅读全文

数组排序方法的性能比较(5):对象大小与排序性能

2010-01-29 00:09 by Jeffrey Zhao, 8198 阅读, 收藏, 编辑
摘要:在我公开测试结果之后,有朋友也进行了其他测试。在测试中我使用的是int数组,经过分析之后我们了解到Array.Sort对于int数组有特殊的优化。于是,某些朋友使用了一些引用类型的数组进行排序,得到Array.Sort方法的性能落后于LINQ排序——虽然由于测试方式的问题,这个结果和结论都不太妥当。不过在讨论的过程中,我们都意识到了一个问题:在其他条件不变的情况下,引用类型的字段越多,Array.Sort方法所需时间就越久。这次我们就来讨论一下这个问题。 阅读全文

数组排序方法的性能比较(4):LINQ方式的Array排序

2010-01-28 00:06 by Jeffrey Zhao, 8612 阅读, 收藏, 编辑
摘要:经过前两篇文章的分析,我们已经了解了Array.Sort与LINQ排序两种实现方式的差别:前者直接比较两个元素的大小,而后者先选出每个元素的“排序依据”再进行比较。因此,虽然后者需要相对较多的“周边工作”,但由于每次比较时都可以仅仅使用高效的基础类型(如int),因此从整体来看,两者的性能高低难以辨别。不过,既然我们已经了解LINQ排序“高效”的原因,又能否将其利用在数组排序上呢?程序是人写的,此类问题大都有肯定的答案。那么我们现在就来实现一下。 阅读全文

数组排序方法的性能比较(3):LINQ排序实现分析

2010-01-27 00:02 by Jeffrey Zhao, 15060 阅读, 收藏, 编辑
摘要:上次我们分析了Array.Sort方法的实现方式,并了解到类库会为一些特例而使用高性能的排序方式——int数组便是这样一例,因此从测试结果上来看其性能特别高。不过从数据上看,即便是在普通的情况下,Array.Sort的性能也比LINQ排序要高。不过也有朋友从测试中得出的结论正好相反,这又是为什么呢?那么现在,我们再来分析一下LINQ排序的实现方式吧,希望这样可以了解到两者性能差别的秘密。 阅读全文

人肉反编译使用yield关键字的方法

2010-01-26 00:06 by Jeffrey Zhao, 11441 阅读, 收藏, 编辑
摘要:我认为这是一个真命题:“没有用.NET Reflector反编译并阅读过代码的程序员不是专业的.NET程序员”。.NET Reflector强大的地方就在于可以把IL代码反编译成可读性颇高的高级语言代码,并且能够支持相当多的“模式”,根据这些模式它可以在一定程度上把某些语法糖给还原,甚至可以支持简单的Lambda表达式和LINQ。只可惜,.NET Reflector还是无法做到极致,某些情况下生成的代码还是无法还原到易于理解——yield关键字便是这样一个典型的情况。不过还行,对于不复杂的逻辑,我们可以通过人肉来“整理”个大概。 阅读全文

数组排序方法的性能比较(2):Array.Sort<T>实现分析

2010-01-22 00:06 by Jeffrey Zhao, 11927 阅读, 收藏, 编辑
摘要:昨天我们比较了Array.Sort方法与LINQ排序的性能,知道了LINQ排序的性能以较大幅度落后于Array.Sort方法。而对于Array.Sort来说,性能最高的是其中使用Comparer.Default作为比较器的重载方法。在前文的末尾我们做出了推测:由于排序算法已经近乎一个标准了(快速排序),因此从算法角度来说,Array.Sort方法和LINQ排序上不应该有那么大的差距,因此造成两者性能差异的原因,应该是具体实现方式上的问题。 阅读全文

数组排序方法的性能比较(1):注意事项及试验

2010-01-21 00:11 by Jeffrey Zhao, 10492 阅读, 收藏, 编辑
摘要:昨天有朋友写了一篇文章,其中比较了List的Sort方法与LINQ中排序方法的性能,而最终得到的结果是“LINQ排序方法性能高于List.Sort方法”。这个结果不禁让我很疑惑。因为List.Sort方法是改变容器内部元素的顺序,而LINQ排序后得到的是一个新的序列。假如两个排序方法的算法完全一致,LINQ排序也比对方多出元素复制的开销,为什么性能反而会高?如果LINQ排序的算法/实现更为优秀,那为什么.NET Fx不将List.Sort也一并优化一下呢?于是今天我也对这个问题进行了简单的试验。 阅读全文

浅谈代码的执行效率(4):汇编优化

2010-01-14 00:08 by Jeffrey Zhao, 11921 阅读, 收藏, 编辑
摘要:终于谈到这个话题了,首先声明我不是汇编优化的高手,甚至于我知道的所有关于汇编优化的内容,仅仅来自于学校的课程、书本及当年做过的一些简单练习。换句话说,我了解的东西只能算是一些原则,甚至也有一些“陈旧”了——不过我想既然是一些原则性的东西,还是能够用它来做一定程度的判断。至少我认为,我在博客园里看到的许多关于“汇编优化”也好,“内嵌汇编”也罢的说法,经常是有些问题的。 阅读全文

浅谈代码的执行效率(3):缓存与局部性

2010-01-12 00:03 by Jeffrey Zhao, 10954 阅读, 收藏, 编辑
摘要:在前两篇文章里,我们讨论了程序性能的两个方面,一是算法(广义的算法,即解决问题的方法),二是编译器。通过这两个方面,我想表达的意思是,一段程序的执行效率,是很难从表面现象得出结论的,至少从一些简单的层面,如代码的长度是几乎难以说明任何问题——因此一定要进行Profiling才能做到有效的优化。而现在,我们假设两段程序算法基本相同,编译器也只是进行简单的“翻译”,那么……我们能从“表面”看出性能高下吗? 阅读全文

按月统计博客园单个用户的发文数量

2010-01-11 00:07 by Jeffrey Zhao, 7601 阅读, 收藏, 编辑
摘要:这几天在家闲着,便试着写一些小程序。之前有朋友问到“F#能不能写Web”,于是我也就打算这么一试。虽然我能肯定,用F#写Web应用程序不会是问题,不过倒真还没有做过这方面的尝试。我想,如果用F#写Web应用程序,那么它很重要的一点,应该是利用其在异步编程方面的强大特性。最后我决定,使用F#编写一个按月统计博客园单个用户发文数量的简单服务。尝试的结果是——还有些问题没有解决。不管怎么样,我先把其主体逻辑描述一下吧。 阅读全文

浅谈代码的执行效率(2):编译器的威力

2010-01-08 00:06 by Jeffrey Zhao, 11100 阅读, 收藏, 编辑
摘要:在上一篇文章中,我主要表达了这样一个观点:影响程序效率的关键之一是算法,而算法的选择与优化,和是否多一个赋值少一个判断的关系不大。关于算法的选择,我谈到其理论上的复杂度,并不直接反映出效率。因为在实际运用时,数据的规模,形式等等都会涉及到算法的实际效用。一个时间复杂度低的算法并不代表任何情况下的效率都高。这是“实际”和“理论”的区别之一。现在我打算来谈一下另一个比较“实际”的东西:编译器对于程序效率的影响。 阅读全文

老赵谈IL(4):什么时候应该学IL,该怎么学IL

2009-12-25 00:08 by Jeffrey Zhao, 11438 阅读, 收藏, 编辑
摘要:又是一个拖了半年的系列,可能是前几篇主要以事实为准,举例子的文章总是比较容易写的,因此十分顺畅。而最后一篇打算做一个总结,以讲道理为主——却发现该将的似乎都已经讲完了。不过做事要有始有终,该完成的也必须要完成。那么现在就来谈谈我的一些个人看法:什么时候应该学IL,以及应该怎么学IL。 阅读全文

重谈字符串连接性能(下):分析优化

2009-12-23 14:03 by Jeffrey Zhao, 7979 阅读, 收藏, 编辑
摘要:经过之间的性能比较,我们得知StringBuilder的性能并非时时最优,再经过实现分析,我们大致了解了StringBuilder的实现方式。虽然在此之前,大家也基本已经了解StringBuilder的实现原理,也有不少朋友指出了它性能缺陷的原因。不过“严谨”起见,寻找性能问题的方式应该是进行Profiling,然后找出性能关键再进行优化——而不是纯粹进行“阅读”这种静态分析方式。 阅读全文

使用Profiler分析程序性能

2009-12-22 11:37 by Jeffrey Zhao, 48884 阅读, 收藏, 编辑
摘要:三个星期之前我向大家求助说,VS的Profiler分析程序性能时无法跟踪框架内部的方法调用。当时我做了不少尝试,例如下载并配置了.NET Framework的symbol文件和源代码,还尝试使用了ANTS Profiler和CLR Profiler等其他工具,最终还是没有成功。Ivony...老大在评论中告诉我说Sampling方式可以获得比Instrumentation更多的信息,不过我觉得Sampling得到的结果并不像我的目标那样干净,因此还是在寻找Instrumentation的方式。不过最终耗费了一个GTSC的支持点数,才被告知——的确应该使用Sampling。 阅读全文

在.NET平台上使用Scala语言(下):分析

2009-12-21 00:30 by Jeffrey Zhao, 7079 阅读, 收藏, 编辑
摘要:上一篇文章里我们简单尝试了在Scala里编写.NET应用程序。这个过程并不困难,因为似乎Scala官方已经对此已经有较好的支持了。我们要做的只是“获取工具”,“编译成IL”,最后再“生成程序集”即可。那么,这些工具究竟做了些什么,Scala究竟又是如何支持.NET平台的,它的可用性究竟如何,我们还需要进一步的分析及尝试。 阅读全文

在.NET平台上使用Scala语言(上):初尝

2009-12-18 12:47 by Jeffrey Zhao, 10497 阅读, 收藏, 编辑
摘要:Scala是Java平台上的一门新兴起的语言,我也不止一次在博客上提到它。我非常希望它可以取代Java这种劣质语言,让Java平台的生产力上一个台阶。事实上,Scala从一开始——或者说“很早”就对生成.NET程序集提供了支持。只可惜,毕竟还是Java平台的东西,.NET方面的资源少之又少,不过我们还是可以进行一番尝试的。 阅读全文

定制Paste from Visual Studio插件(下)

2009-12-16 14:27 by Jeffrey Zhao, 5292 阅读, 收藏, 编辑
摘要:上一篇文章里我们进行了简单的实验,验证了通过修改IL生成新插件的可行性,不过我们要做的事情还有很多,因为我们实际要做的事情其实是……插入行号。这需要我们补充新的逻辑,并且对CreateContent进行修改。那么我们又该如何写这大段大段的IL呢?没关系,其实这些事情不懂IL也可以做。 阅读全文

定制Paste from Visual Studio插件(上)

2009-12-16 10:56 by Jeffrey Zhao, 5922 阅读, 收藏, 编辑
摘要:我在上一篇文章里谈了我常用Paste from Visual Studio(下文称VSPaste)的插件,这大大方便了我写博客时贴代码的工作。不过今天早上有朋友在我博客后面留言说:“VSPaste没法显示行号,不知大家有没有办法解决?”其实这点很容易,写个小程序,把VSPaste生成的HTML再进行一番处理不就可以了嘛。不过最方便的做法还是让VSPaste直接生成带行号的代码块,不是吗?那么,我们就来自己动手丰衣足食解决这个问题吧。 阅读全文

使用值类型LazyString分析字符串

2009-12-07 10:09 by Jeffrey Zhao, 6443 阅读, 收藏, 编辑
摘要:.NET里提供了值类型与引用类型可谓是一个非常关键的特性,例如开发人员使用值类型时,可以充分控制内存的布局方式,这对于Interop等操作非常重要。不过,其实值类型最重要,最基本的特性还是内存分配上。现在基本上是个.NET开发人员就会叨念说“值类型”分配在栈上,“引用类型”分配在堆上。但是什么是栈什么堆?分配在栈上和堆上的区别是什么?如果说这两个问题太“理论”,那么来个实际的:您在平时什么情况下会使用,或者说,定义一个值类型呢?其实这才是重要的,否则背再多概念也没有用。只可惜从我面试的经验上来看,基本没有多少兄弟能把这些.NET基础完整说清楚。 阅读全文

求助:如何使用VS的Profiler跟踪框架内部的方法调用?

2009-12-05 19:16 by Jeffrey Zhao, 6486 阅读, 收藏, 编辑
摘要:解决性能问题必须使用Profiler,无论是自己写的实验代码还是一些高级工具,没有数据,而是凭感觉来解决性能问题在绝大部分情况是不靠谱的。VSTS包含了Profiler,也经常见一些博客上用Profiler得到的数据进行性能分析,其中最著名的莫过于Rico Mariani的Performance Quiz系列了。使用VSTS的Profiler可以收集程序运行过程中每个方法的调用次数,所消耗的总时间等等,一目了然,但是我在使用过程中却出现了问题。 阅读全文

做个游戏:设计代码生成特定的调用堆栈

2009-12-04 00:30 by Jeffrey Zhao, 4806 阅读, 收藏, 编辑
摘要:前篇文章里我谈了谈String.Concat与StringBuilder的实现,于是后来有个朋友回复到:“我发现StringBuilder里好像也用了String.Concat。在一次异常中,Exception的StackTrace显示是先发生了String.Concat异常,然后再StringBuilder.Append。”不过经过一些简单的分析,我们会发现StringBuilder.Append方法的各个重载都没有依赖(即调用)String.Concat方法,那么这样的调用堆栈又是如何形成的呢? 阅读全文

重谈字符串连接性能(中):细节实现

2009-12-03 10:10 by Jeffrey Zhao, 9814 阅读, 收藏, 编辑
摘要:根据上次的评测结果,我们了解了几种字符串拼接方式的性能高低。从中可以看出,广受追捧的StringBuilder性能似乎并不是最好的,String.Concat方法有时候有时候更适合使用。那么为什么String.Concat方法性能那么高,StringBuilder又为什么落败,而我们又有没有什么可以改进的做法呢?为此,我们不妨动用.NET Reflector这一利器,看一下两者是怎么实现的。 阅读全文

各种数组元素复制方式的性能比较

2009-12-02 10:27 by Jeffrey Zhao, 8734 阅读, 收藏, 编辑
摘要:原本这只是“字符串”话题的一个分支,不过后来我发现这个问题单独来看也有一定参考价值,也有一些问题值得讨论的地方,其中也有一些问题希望得到高手指点,最终打算把这个话题独立处理。话不多说,现在就来看看。 阅读全文

使用WinDBG + SOS谈对象大小及字符串的结构

2009-12-01 14:57 by Jeffrey Zhao, 5704 阅读, 收藏, 编辑
摘要:昨天我们使用了一个最最简单的小实验,来检查相同类型的不同对象大小是否相同。当然,我们很轻易地“验证”得出,不同长度的字符串大小是不一样的。不过这种表面现象其实很难说明问题,因此我现在还是用WinDBG + SOS来进行一些检查,希望可以得到一些表面上看不出来的信息。 阅读全文

相同类型的每个对象大小都是一样的吗?

2009-11-30 14:09 by Jeffrey Zhao, 5084 阅读, 收藏, 编辑
摘要:快速回答:“相同(引用)类型的每个对象大小都是一样的吗?”其实个问题对于大多数情况下来说应该正确的,不过的确也有些类型受到CLR的特殊照顾,因而有那么些例外。我现在尝试使用一些简单的小实验来进行验证,当然它是不严谨的,只能算是一个简单尝试而已。 阅读全文

验证fixed关键字效果的小实验

2009-11-29 21:11 by Jeffrey Zhao, 5423 阅读, 收藏, 编辑
摘要:之前谈到String连接操作的性能,其中会涉及到unsafe操作,而unsafe操作必然会涉及到指针,于是fixed关键字也应运而生。fixed关键字是用来pin住一个引用地址的,因为我们知道CLR的垃圾收集器会改变某些对象的地址,因此在改变地址之后指向那些对象的引用就要随之改变。这种改变是对于程序员来说是无意识的,因此在指针操作中是不允许的。否则,我们之前已经保留下的地址,在GC后就无法找到我们所需要的对象。现在就来我们就来做一个小实验,验证fixed关键字的效果。 阅读全文

视频:Microsoft PDC 09,算法及数据结构内容及其他

2009-11-27 13:57 by Jeffrey Zhao, 5719 阅读, 收藏, 编辑
摘要:这里又有一些新整理好的视频。Microsoft PDC 09是最近的重头,只要您是搞微软技术的,无论关注哪个技术方面,都可以找到许多有用的内容。我也经常从此类大会中了解许多平时不太关注的内容,也算是保持知识的新鲜度。此外,还有算法和数据结构相关的内容,以及有趣的Visual Studio纪录片。 阅读全文

重谈字符串连接性能(上):性能评测

2009-11-26 01:12 by Jeffrey Zhao, 16167 阅读, 收藏, 编辑
摘要:看到这个标题是不是觉得很奇怪呢?字符串连接的性能,这个话题已经被谈了一遍又一遍,一次又一次,似乎已成定论,这又有什么好谈的呢?不过说来奇怪,根据我的实验结果在网上进行搜索,却找不到答案。因此,我现在和大家一起重新再作一次实验并观察结果。在文章最后我也会给出完整的代码,您可以自由地运行,修改,尝试,我们再一起进行交流。 阅读全文

关于浮点数计算时的精度问题

2009-11-24 14:21 by Jeffrey Zhao, 11905 阅读, 收藏, 编辑
摘要:那个有问题的缩略图生成的方法发布之后,短短半天就有很多朋友响应,其中指出了不少方法中的不少问题,有些也是我没有意识到的。果然集体的智慧是无穷的,一段代码在许多人的眼皮底下经过,想留有bug也不容易。不过,我在这里只能谈一下我写那篇文章的本意了,我认为那篇文章中最主要的问题是,在计算图片尺寸时没有处理好浮点数计算的精度问题。 阅读全文

您能看出这个生成缩略图的方法有什么问题吗?

2009-11-24 00:32 by Jeffrey Zhao, 9594 阅读, 收藏, 编辑
摘要:昨天又使用了某个多年以前写的,或者说是“收集”而来的方法。这个方法的作用是根据一幅图片(一般是幅大图)生成它的缩略图。这个方法用了许多年了,一直没有去怀疑过它的正确性,但是昨天忽然发现它一直以来都存在一个问题,虽然可能不是那么明显,而且也不会造成太大问题(否则早就发现了)——但是,这的确是个不妥的地方。这个问题在我看来也有一定借鉴意义,因此我打算把它展示出来。那么,您能否看出它究竟是错在什么地方了呢? 阅读全文

再谈Attribute性能优化方式:使用CCI Metadata

2009-11-20 10:47 by Jeffrey Zhao, 6269 阅读, 收藏, 编辑
摘要:Attribute使用了反射,密集调用时会带来较大开销,因此我们上次提出了一些优化方式,这样就不会产生性能方面的问题了。这个优化方式的关键,主要是使用直接获得构造Attribute的元数据,然后自定义它们的生成方式并缓存,这样就避免了每次获取元数据及反射构造Attribute的开销。我从一开始就抱有这个优化的“思路”,但是上篇文章中最终的做法是受到了heros同学的提示才得出的,因为我一开始还根本不知道CustomAttributeData这个已然内置的类库。我当时在探索的方向是使用CCI Metadata读取程序集中与Attribute相关的元数据。 阅读全文

Attribute操作的性能优化方式

2009-11-18 10:09 by Jeffrey Zhao, 23430 阅读, 收藏, 编辑
摘要:Attribute是.NET平台上提供的一种元编程能力,可以通过标记的方式来修饰各种成员。无论是组件设计,语言之间互通,还是最普通的框架使用,现在已经都离不开Attribute了。迫于Attribute的功能的重要性(Kent Beck认为NUnit比早期JUnit设计的好,一个主要方面便是利用了Attribute),Java语言也在5.0版本中引入了与Attribute类似的Annotation概念。不过Attribute说到底也是一种反射操作,平时正常使用不会带来问题,但是密集的调用还是对性能有一定影响的。这次我们就来总结看看我们究竟可以如何回避Attribute操作的一些性能问题。 阅读全文

《链接、装载与库》里的一个错误:关于调用栈

2009-11-17 00:29 by Jeffrey Zhao, 20408 阅读, 收藏, 编辑
摘要:周六老同学聚会,出门前随手从桌上抓起了《程序员的自我修养——链接、装载与库》在路上翻。自从武汉博文出版社的周筠老师送给我这本书后,我基本上还没怎么看过。对这本书第一感觉是“标题党”,主标题起大了,虽然经过解释之后并非无法理解,但还是不太喜欢。但书还是好书,已经看完大半,而且基本上会在近期找个方式推荐一把。不过现在我想细说的并不是推荐相关话题(如适合谁看,该怎么看,结合什么一起看等等),而是想指出书中还未被《勘误》收录的一个错误:P288讲调用栈时,文字描述和配图上的问题。 阅读全文

并发环境下的缓存容器性能优化(下):性能测试

2009-11-16 00:29 by Jeffrey Zhao, 19481 阅读, 收藏, 编辑
摘要:上一篇文章里,我谈到对于某些场景中的缓存容器,其写操作非常少,到了程序后期甚至为零,而对它的读操作却几乎是密集连续且无穷无尽的。对于这样的容器,如果使用ReaderWriterLockSlim去进行保护每个“读”操作,这开销是在有些多余。因此我提出了“不可变”的哈希表,目的是在保持读操作的时间复杂度为O(1)的情况下,尽可能避免多余的开销。现在我们便将它和其他几种时间进行一个性能的对比。 阅读全文

“表达式树”配合“泛型参数字典”定义通用操作

2009-11-13 13:53 by Jeffrey Zhao, 18108 阅读, 收藏, 编辑
摘要:上午有朋友提出了这么一个问题:如何定义一个通用的相加操作。其实这可以利用“泛型参数字典”和“表达式树”配合完成,也有着非常优秀的性能。于是,我们便可以定义一个比.NET框架自带的Enumerable.Sum强大许多的扩展方法了。 阅读全文

并发环境下的缓存容器性能优化(上):不可变的哈希表

2009-11-12 00:03 by Jeffrey Zhao, 22401 阅读, 收藏, 编辑
摘要:我们在项目中经常会遇到这样的场景:一些信息读取开销较大,但只需要生成一次便可反复使用,因此我们会将其永久地缓存起来。例如在ASP.NET MVC中,系统会根据Controller的名称来缓存对应的元数据。这些缓存容器都有一些共同的特点,便是存储的对象数量有限(少则几十,多不过数千),但都需要在并发环境下被大量地读取,因此必须是线程安全的。那么,我们该如何设计这样的容器呢? 阅读全文

缓存方式与对象创建的性能比较

2009-11-11 14:28 by Jeffrey Zhao, 19589 阅读, 收藏, 编辑
摘要:由于Lambda表达式构造URL的速度不佳,我最近对于性能上的细节问题进行了一些探索和尝试。对于很多问题,以前由于不会形成性能瓶颈,因此并没有进行太多关注。还有一些问题可以“推断”出大致的结论,也趁这个机会进行更详细的试验,希望可以得到更为确切的结论和理性的认识。这次我打算做的实验,是关于对象的缓存与创建的性能比较。在某些情况下,我们会将创建好的对象缓存起来,以便今后进行复用。但是不同的缓存方式会有不同的性能,因此……我们现在便来试试看。 阅读全文

一次失败的尝试(下):无法使用泛型的Attribute

2009-11-11 00:07 by Jeffrey Zhao, 18858 阅读, 收藏, 编辑
摘要:原本打算两篇写在一起,但是我认为这两个话题本身并没有太大关联,因此分开,便于查询。其实在构建Attribute的时候,我们经常会从构造函数中传入一个Type类型,然后在Attribute中使用Activator.CreateInstance或其他的“反射”方法来构造对象。那么,我忽然想,为什么不能使用泛型的Attribute呢?有了泛型便可以利用静态检查,也可以获得其他有用的特性。只可惜,C#并不支持在Attribute中使用泛型……而且这点在C# 4中也基本不会有所改变了。 阅读全文

一次失败的尝试(上):原来GetCustomAttributes方法每次都返回新的实例

2009-11-10 00:08 by Jeffrey Zhao, 21304 阅读, 收藏, 编辑
摘要:前一段时间我在比较各种URL生成方式性能的时候,其实已经为利用Lambda表达式的做法进行了优化。在优化之前,使用Lambda构建URL的性能比现在的结果还要慢上50%。性能低下的原因,在于每次都使用GetCustomAttributes来获取参数(或其他一些地方)标记的Custom Attribute。这里应该用到了反射,在这种密集调用情形中性能急转直下。 阅读全文

统计一个表达式树拥有的节点数量

2009-10-31 21:05 by Jeffrey Zhao, 16748 阅读, 收藏, 编辑
摘要:如果要统计表达式树的节点数量,我们可以编写一个Expression Visitor来完成这个任务。值得注意的是,由于ExpressionVisitor只负责“遍历”,因此在进行“统计”、“收集信息”等任务的时候,都需要在子类内部保存临时信息。因此,许多ExpressionVisitor的实现其实都不是线程安全的。一般说来,由于自动生成闭包等机制,一个Lambda表达式实际构造出的节点总比我们“看出”的要多一些。 阅读全文

浅谈线程池(下):相关试验及注意事项

2009-10-20 00:06 by Jeffrey Zhao, 27275 阅读, 收藏, 编辑
摘要:三个月,整整三个月了,我忽然发现我还有三个月前的一个小系列的文章没有结束,我还欠一个试验!线程池是.NET中的重要组件,几乎所有的异步功能依赖于线程池。之前我们讨论了线程池的作用、独立线程池的存在意义,以及对CLR线程池和IO线程池进行了一定说明。不过这些说明可能有些“抽象”,于是我们还是要通过试验来“验证”这些说明。此外,我认为针对某个“猜想”来设计一些试验进行验证是非常重要的能力,如果您这方面的能力略有不足的话,还是尽量加以锻炼并提高吧。 阅读全文

谈吉日嘎拉的《白话反射技术》及其他(技术篇)

2009-10-16 19:16 by Jeffrey Zhao, 25252 阅读, 收藏, 编辑
摘要:社区又掀起了腥风血雨,这次又是吉日嘎拉这一博客园的众矢之的所引发的惨案。他的一篇《白话反射技术》发表之后,被包同学一篇文章狠狠地踩在脚底下,言辞之激烈令人罕见。从两片文章的内容与评论来看,大家的眼光似乎都没有集中在技术本身,而是针对个人在你来我往。有评论称这是“门派之争”,虽然看不出到底哪门哪派,但看上去也还真像那么一回事情。不过这真是技术社区该有的讨论氛围和方式?如果觉得吉日嘎拉在技术上有问题,难道不应该条条指出吗?既然没有人做这件事情,那么就还是我来吧,反正我写博客也成习惯了。 阅读全文

尝试使用IKVM运行Lucene 2.9.0版

2009-10-09 15:26 by Jeffrey Zhao, 13430 阅读, 收藏, 编辑
摘要:上月末Lucene发布了2.9.0版,这个版本的改进比较明显,主要是各方面性能的增强,以及对数字字段范围查询的直接支持。这个版本还有个重要的意义,就是它标记了Lucene 3在API上的改变,及早跟进的话对Lucene 3的未来接受程度会比较好。Lucene的更新很慢,而移植到.NET平台上的Lucene.NET的二进制发布则更是一直停留在07年三月的2.0版本。虽然我们可以通过svn获取到Lucene.Net 2.3.2的源代码自行编译,但这次我还是想直接使用最新的2.9.0版本。最终我决定趁这个机会尝试一下IKVM.NET。 阅读全文

幻灯片:LINQ Inside, Part 1

2009-09-26 13:06 by Jeffrey Zhao, 11745 阅读, 收藏, 编辑
摘要:整理电脑时整理发现一个幻灯片,修改日期是去年年底,当时不知道为了什么,对方是谁讲一次LINQ。这次讲座是入门型的,主要讲了讲什么是LINQ,什么是表达式,表达式树等等。不过这第一部分似乎……还没有提到LINQ,更那个什么的是,我已经找不到第二部分了……因此,大家可以随意看看。目前脑袋写了几篇相当不错的,可作为入门的LINQ相关文章。以后我再提到这部分内容时终于也有东西可以引用了…… 阅读全文

基于DelegateEvent创建第一个IEvent对象

2009-09-11 13:47 by Jeffrey Zhao, 11603 阅读, 收藏, 编辑
摘要:继续和“事件即对象”打交道。我们之前提到过两个“趣味编程”:DelegateEvent与Functional Reactive Programming,现在我们在它们两者之间架起一座桥梁。也就是说,我们要从一个DelegateEvent对象创建一个IEvent对象出来。这样,您就可以把它作为第一个IEvent对象,继续尝试Functional Reactive Programming了。 阅读全文

如何创建TextWriter的子类

2009-09-11 00:42 by Jeffrey Zhao, 14021 阅读, 收藏, 编辑
摘要:如果您需要继承TextWriter实现自己的类型,您会怎么做?继承TextWriter不难,不过接下来,您打算覆盖(override)掉哪些方法?从Reflector的观察结果发现,其中所有的方法最终都会委托给Write(char)方法。但是只覆盖Write(char)方法只能保证最终成果“可以运行”,却无法保证是最优秀的结果。但是又有谁可以告诉我,究竟该怎么做呢? 阅读全文

监视程序中的死锁及其他

2009-09-10 00:08 by Jeffrey Zhao, 14130 阅读, 收藏, 编辑
摘要:每天回家路上总有一段比较长的路一片漆黑无法看书。这种时候,如果我有兴致则会用手机上上网,但是大部分情况下还是用来想问题的。今天我回忆起今天园子首页的一篇文章谈到死锁,想到了一种可行的解决方案,只可惜到家一搜索……别人已经实现过了。于是,又没我什么事情了…… 阅读全文

我犯了一个错误,您能指出吗?(结论)

2009-09-08 15:55 by Jeffrey Zhao, 13389 阅读, 收藏, 编辑
摘要:其实许多朋友已经在回复中发现问题所在了。泛型类中的静态变量会因为T的不同而产生不同的值,也就是说每个T所访问的静态变量都是独立的。因此,看似共享的静态ConnectionKey实际上是两个不同的Guid。 阅读全文

我犯了一个错误,您能指出吗?

2009-09-08 10:01 by Jeffrey Zhao, 15008 阅读, 收藏, 编辑
摘要:这是我最近在项目中犯的一个错误,您能指出吗? 阅读全文

再谈ASP.NET Routing中的ParsedRoute

2009-08-24 14:10 by Jeffrey Zhao, 4915 阅读, 收藏, 编辑
摘要:ParsedRoute是ASP.NET Routing中的内部类,作用是根据既定模式将一段URL解析为一个RouteValueDictionary。上次的文章中我主要谈了如何利用反射使用类库的内部成员,而这次则想分享一些使用ParsedRoute时产生的一些想法。 阅读全文

为什么是HttpContextBase而不是IHttpContext

2009-08-21 15:15 by Jeffrey Zhao, 9500 阅读, 收藏, 编辑
摘要:由于HttpContext很难进行Mock,因此为了提高可测试性,微软随ASP.NET MVC发布了一个“抽象包”,专门用于对HttpContext及其相关组件进行抽象。不过在Preview 1版本中,这些抽象都是一个个接口,如IHttpContext,IHttpRequest等等。而在下一个版本中,立即就成为了一个个抽象类,如HttpContextBase,HttpRequestBase。现在我打算从“使用”角度来谈一下,为什么这里的确应该用抽象类而不是接口。 阅读全文

复用类库内部已有功能

2009-08-19 18:59 by Jeffrey Zhao, 7805 阅读, 收藏, 编辑
摘要:经常看我博客的人可能会知道,我是一个喜欢搞点小技巧来实现某个功能的人。例如博客的皮肤,自己花了不少时间定义,也是为了效果丰富一些。当然,搞得最多的是从框架或类库内部取出一点小功能来用用,节省自己开发的时间。 阅读全文

再谈抽象类和接口

2009-08-19 12:15 by Jeffrey Zhao, 8882 阅读, 收藏, 编辑
摘要:昨天我质疑了为什么定义RouteBase抽象类,而不是IRoute接口,我谈到对于一个“没有任何实现”的抽象类来说,开发人员应该使用接口。不过在后面的评论中,有朋友给了我启发,让我忽然想到更多的事情。晚上又再次翻了翻《Framework Design Guidelines》之后,打算再谈一些东西,把这个问题讨论地更加清楚一些。 阅读全文

从.NET中委托写法的演变谈开去(下):性能相关

2009-08-10 00:44 by Jeffrey Zhao, 11324 阅读, 收藏, 编辑
摘要:在上一篇文章中,我们详细讲述了C# 3.0中Lambda表达式(构造委托)的使用方式,它在语义上的优势及对编程的简化——这些内容已经属于委托的“扩展内容”。不如这次谈得更远一些,就来讨论一下上文中“编程方式”的性能相关话题。 阅读全文

从.NET中委托写法的演变谈开去(中):Lambda表达式及其优势

2009-08-07 08:24 by Jeffrey Zhao, 20151 阅读, 收藏, 编辑
摘要:在上一篇文章中我们简单探讨了.NET 1.x和.NET 2.0中委托表现形式的变化,以及.NET 2.0中匿名方法的优势、目的及注意事项。那么现在我们来谈一下.NET 3.5(C# 3.0)中,委托的表现形式又演变成了什么样子,还有什么特点和作用。 阅读全文

从.NET中委托写法的演变谈开去(上):委托与匿名方法

2009-08-05 12:50 by Jeffrey Zhao, 22858 阅读, 收藏, 编辑
摘要:在《关于最近面试的一点感想》一文中,Michael同学谈到他在面试时询问对方“delegate在.net framework1.1,2.0,3.5各可以怎么写”这个问题。我也问过,那么我就先单独针对这个问题进行解释,然后谈谈自己为什么会提出这个问题吧。 阅读全文

快速计算表达式树

2009-07-29 09:25 by Jeffrey Zhao, 11852 阅读, 收藏, 编辑
摘要:.NET 3.5中新增的表达式树(Expression Tree)特性,第一次在.NET平台中引入了“逻辑即数据”的概念,它是LINQ to Everything在技术实现上的重要基石之一。对表达式树进行计算,是处理表达式树时中最常见的工作了。根据我的本地测试结果,在一台P4 2.0 GHz的服务器上,单线程连续计算一万个简单的四则运算表达式便要花费超过1秒钟时间。这并非是一个可以忽略的性能开销,引入一种性能更好的表达式树计算方法势在必行。 阅读全文

浅谈线程池(中):独立线程池的作用及IO线程池

2009-07-24 09:21 by Jeffrey Zhao, 22040 阅读, 收藏, 编辑
摘要:在上一篇文章中,我们简单讨论了线程池的作用,以及CLR线程池的一些特性。不过关于线程池的基本概念还没有结束,这次我们再来补充一些必要的信息,这样有助于我们在程序中选择合适的使用方式。例如,为什么要有独立的线程池,CLR线程池到底有什么不足,IO线程池又是什么呢?有了这些准备之后,最后的试验也就非常自然了。 阅读全文

浅谈线程池(上):线程池的作用及CLR线程池

2009-07-22 09:01 by Jeffrey Zhao, 36846 阅读, 收藏, 编辑
摘要:线程池是一个重要的概念。不过我发现,关于这个话题的讨论似乎还缺少了点什么。作为资料的补充,以及今后文章所需要的引用,我在这里再完整而又简单地谈一下有关线程池,还有.NET中各种线程池的基础。更详细的内容就不多作展开了,有机会我们再详细讨论这方面的细节。这次,还是一个“概述”性质的,希望可以说明白这方面问题的一些概念。文章分两段,我们先来谈谈线程池的作用,及CLR自带的线程池。 阅读全文

老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

2009-06-06 00:04 by Jeffrey Zhao, 25903 阅读, 收藏, 编辑
摘要:IL的确比C#等高级语言来的所谓“底层”,但是很明显,IL本身也是一种高级抽象。而即使是机器码,它也可以说是基于CPU的抽象,CPU上如流水线,并行,内存模型,Cache Lock等东西对于汇编/机器码来说也可以说是一种“封装”。从不同层次可以获得不同信息,我们追求“底层”的目的肯定也不是“底层”这两个字,而是一种收获。了解自身需要什么,然后能够选择一个合理的层次进入,并得到更好的收益,这本身也是一种能力。追求IL的做法,本身并没有错,只是追求IL一定是当前情况下的最优选择吗?这是一个值得不断讨论的问题,我的这篇文章也只是表达了我个人对某些问题的看法。 阅读全文

老赵谈IL(2):CLR内部有太多太多IL看不到的东西,包括您平时必须了解的那些

2009-06-03 14:34 by Jeffrey Zhao, 29911 阅读, 收藏, 编辑
摘要:CLR作为承载IL的平台,就像一个溺爱孩子的父母,操办了孩子生活所需要的一切。这个孩子一嚷嚷“我要吃苹果”,则父母就会拿过来一个苹果。您咋看这个孩子,都还是无法了解父母是如何获得苹果的(new一个Apple对象),怎么为孩子收拾残局的(GC)。虽然这些经常是所谓的“成年人(.NET程序员)必知必会”。而您如果盯着孩子看了半天,耐心分析他吃苹果的过程(使用IL编写的逻辑),最后终于看懂了,可惜发现——tmd老子自己也会吃苹果啊(从C#等高级语言中也能看出端倪来)! 阅读全文

驳文不看文,实在可怕

2009-06-02 09:17 by Jeffrey Zhao, 22047 阅读, 收藏, 编辑
摘要:一早看到包同学的驳文《批驳小赵之IL无用论(1)》,甚是期待,但看了第一个回复,却让我大失所望。包同学能否看清了老赵以前说过的,自己以前说过的,以及老赵昨天说的东西以后再进行反驳呢?我们很多明明是同样的观点,为什么变成相互驳斥了呢? 阅读全文

老赵谈IL(1):IL是什么,它又不是什么?那么汇编呢?

2009-06-01 21:00 by Jeffrey Zhao, 30876 阅读, 收藏, 编辑
摘要:我们.NET开发人员必定离不开IL,就算您没有学习,也一定可以在各处看到它的身影。最近在博客园上活跃的IL文章译者包建强同学的一些看法让老赵大为震惊,决定独立开篇,希望可以让大家看到不同的声音。真理越辩越明,也欢迎大家来一起讨论,发表自己意见。老赵也会尽量把朋友们留在老赵博客上的看法汇总起来,并加以回应。《老赵谈IL》也是系列文章,目前的计划有4篇,您现在看到的便是本系列的第1篇:IL是什么,它又不是什么。 阅读全文

谈表达式树的缓存(7):五种缓存方式的总体分析及改进方案

2009-05-31 22:47 by Jeffrey Zhao, 22474 阅读, 收藏, 编辑
摘要:终于到了这个系列的最后一篇文章了,这个系列的文章本是许多话题的基础,却拖了那么长时间还没有完结。这篇文章主要讨论五种缓存方式各自的优劣,以及他们的性能关键在什么地方,如果要进行改进又有什么可选方案。在这个问题上,老赵的思考可能会有遗漏,如果您有任何补充,也请不吝指出。 阅读全文

谈表达式树的缓存(6):五种缓存方式的性能比较

2009-05-26 21:06 by Jeffrey Zhao, 25878 阅读, 收藏, 编辑
摘要:目前我们已经涉及了五种不同的缓存实现(SimpleKeyCache、PrefixTreeCache、SortedListCache、HashedListCache和DictionaryCache),如果要从一个已经包含n个表达式树的存储中,查找一个有m个节点的表达式树,根据几篇文章的分析,从理论上说除了HashedListCache的时间复杂度是O(m * log(n))之外,其它几种实现的时间复杂度都是O(m)。不过,理论上的结果和实际使用中的效果完全符合吗?那么我们就写一个程序,让数据说话。这是一个控制台应用程序,接受用户参数,并由此生成试验数据,或进行性能比较。 阅读全文

使用WinDbg获得托管方法的汇编代码

2009-04-01 22:42 by Jeffrey Zhao, 27076 阅读, 收藏, 编辑
摘要:有时候,我们需要查看一个.NET方法的汇编指令是怎么样的。记得在大学的时候,我们使用gcc -s和objdump来获得一个c程序代码的汇编指令。但是对于.NET程序来说,我们肯定无法轻松地获得这些内容。因为所有的.NET程序都是编译成IL代码的,而只有在运行时才会被JIT编译成本机代码。老赵这里演示一下如何使用WinDbg来做到这一点。 阅读全文

浅谈尾递归的优化方式

2009-04-01 01:00 by Jeffrey Zhao, 53789 阅读, 收藏, 编辑
摘要:在上文《尾递归与Continuation》里,我们谈到了尾递归的概念和示例,不过有些朋友对于尾递归的功效依然有所怀疑。因此现在,老赵再简单讲解一下尾递归的优化原理,希望能给大家以一定理性认识。 阅读全文

谈表达式树的缓存(5):引入散列值

2009-03-20 01:40 by Jeffrey Zhao, 13153 阅读, 收藏, 编辑
摘要:到目前为止,我们已经实现了三种缓存方式:首先我们设法构建唯一字符串,但是由于它的代价较高,于是我们使用了前缀树进行存储;又由于前缀树在实际操作中所花的时间和空间都有不令人满意之处,我们又引入了二叉搜索树。那么二叉搜索树又有什么缺点呢? 阅读全文

谈表达式树的缓存(4):使用二叉搜索树(AVL树)

2009-03-19 09:05 by Jeffrey Zhao, 11376 阅读, 收藏, 编辑
摘要:上一篇文章中谈到的前缀树实现方式,时间复杂度从理论上来讲已经达到了最优,而空间复杂度理论上也可以做到较优。但是理论和实际是有差别的,而对于上文前缀树的实现来说,这两方面并不是非常理想。因此,虽然事实上前缀树是老赵第一个真正实现的缓存方法,但是对此并不满意,也想着有什么办法可以进行优化。不如尝试一下使用二叉搜索树? 阅读全文

谈表达式树的缓存(3):使用前缀树

2009-03-18 01:24 by Jeffrey Zhao, 13629 阅读, 收藏, 编辑
摘要:在上一篇文章里我们设法将前缀树构造为一个唯一的字符串,然后使用字符串作为key缓存在字典中。这个想法非常直接,做法也不困难(在遍历时记录详细信息便可)。不过事实上,老赵在思考表达式树的缓存问题时,这种字符串拼接的方式只存在于脑海当中,而上文的实现是为了这一系列文章的完整性而特地编写的。这是因为它的缺点较为明显,正如上文所述,字符串拼接操作较为耗时耗资源,且很容易生成一个长度可观的字符串(并非不能优化,不过实现就复杂了)。于是我们现在设法选择另一个解决方案来处理这个问题。 阅读全文

谈表达式树的缓存(2):由表达式树生成字符串

2009-03-17 00:58 by Jeffrey Zhao, 11871 阅读, 收藏, 编辑
摘要:谈到使用表达式树作为key进行缓存,您脑海中最早浮现出来的解决方案是什么?老赵看来,大部分朋友的第一反应自然就是将作为key的表达式树,使用一定规则生成一个字符串。那么我们就先使用这个办法来解决问题。 阅读全文

谈表达式树的缓存(1):引言

2009-03-16 09:29 by Jeffrey Zhao, 16303 阅读, 收藏, 编辑
摘要:表达式树(Expression Tree)是.NET 3.5中引入的一种表达方式。表达式树的运用十分广泛,可以直观地表现出各种“数据”,甚至“逻辑”和“行为”。老赵现在希望可以找到一种较为通用的,能够根据表达式树进行缓存的解决方案。在这一系列文章中,老赵希望可以重现自己在思考这个问题的时候所形成的完整思考路径。相比最终解决方案,这可能才是更有价值的东西。至少我觉得讨论一下这个问题也是非常有意思的事情。而且从一定程度上说,这些思考能够在一定程度上体现出算法设计与数据结构的美妙之处。 阅读全文

警惕匿名方法造成的变量共享

2009-03-13 09:03 by Jeffrey Zhao, 30952 阅读, 收藏, 编辑
摘要:匿名方法是强大的,但是也会造成一些令人难以察觉的陷阱。 阅读全文

一个简单的性能计数器:CodeTimer

2009-03-10 09:03 by Jeffrey Zhao, 45557 阅读, 收藏, 编辑
摘要:有数据,有真相,相信大家在平时的工作或学习过程中,都需要比较几种不同方法或实现之间的性能差距。在这些时候,往往就需要我们不断地创建Stopwatch,打开,关闭,然后打印时间。这种一遍又一遍的重复终有一天会让人忍无可忍,因此如果能有一个“标准”的性能计数器,那应该可以让生活轻松许多。这个性能计数器不用复杂,够用就好;也不需要考虑扩展性,要扩展时直接修改代码就够了;同样不需要考虑输出格式,直接打印在Console就行。 阅读全文

简化异步操作(下):构建AsyncTaskDispatcher简化多个异步操作之间的协作调用

2009-02-24 09:27 by Jeffrey Zhao, 9250 阅读, 收藏, 编辑
摘要:由于CCR和AsyncEnumerator难以“并行”地执行异步代码,因此我们需要提出新的解决方案来满足这方面的需求。本文将构建一个AsyncTaskDispatcher组件,使多个异步操作之间的协作调用得以大大简化。 阅读全文

简化异步操作(上):使用CCR和AsyncEnumerator简化异步操作

2009-02-20 11:25 by Jeffrey Zhao, 10536 阅读, 收藏, 编辑
摘要:在以前的文章中,我曾多次强调应用程序中异步化的重要性。尤其对于IO密集型操作来说,异步执行对于应用程序的响应能力和伸缩性有非常关键的影响。正确使用异步编程能够使用尽可能少的线程来执行大量的IO密集型操作。可惜的是,即使异步编程有避免线程阻塞等诸多好处,但是这种编程方式至今没有被大量采用。其原因有很多,其中最主要的一点可能就是异步模型在编程上较为困难,导致许多开发人员不愿意去做。因此,无论是微软官方还是社区中都出现了一些简化异步编程方式的组件,例如微软的CCR和Wintellect's .NET Power Threading Library中的AsyncEnumerator。但是它们都有同样的局限性,例如操作之间存在依赖,则很难让它们并行执行。对于这样的场景,我们还需要构建额外的解决方案,使多个有依赖关系的异步操作之间的协作调用得以尽可能的简化。 阅读全文

Fast Reflection Library

2009-02-01 09:25 by Jeffrey Zhao, 17836 阅读, 收藏, 编辑
摘要:这是我在CodePlex上创建的一个项目,它的网址是http://www.codeplex.com/FastReflectionLib,使用Microsoft Public License (Ms-PL),您可以随意在自己的产品中使用它的全部或部分代码。这个项目用到了我在《方法的直接调用,反射调用与Lambda表达式调用》和《这下没理由嫌Eval的性能差了吧?》两篇文章里用到的做法,并加以提炼和扩展发布的项目——随便搞搞,留个印记,也供以后参考。 阅读全文

计算机体系结构与程序性能

2009-01-22 08:28 by Jeffrey Zhao, 15071 阅读, 收藏, 编辑
摘要:老赵现在不谈“数据结构与算法如何有助于改善编程思维有什么改善”,或是“操作系统中线程调度、内存分页机制对于开发大型应用程序的参考价值”等“虚无缥缈”之物。在这篇文章里,我想通过两个直接的例子,来说明了解计算机体系结构对于提高程序性能有什么样的作用。 阅读全文

这下没理由嫌Eval的性能差了吧?

2009-01-09 02:32 by Jeffrey Zhao, 18115 阅读, 收藏, 编辑
摘要:写ASP.NET中使用Eval是再常见不过的手段了,好像任何一本ASP.NET书里都会描述如何把一个DataTable绑定到一个控件里去,并且通过Eval来取值的用法。什么,您觉得Eval性能差不堪大用?那么就来看看这篇文章吧。(Updated:提供思考题解答) 阅读全文

方法的直接调用,反射调用与……Lambda表达式调用

2008-11-24 09:59 by Jeffrey Zhao, 39441 阅读, 收藏, 编辑
摘要:想调用一个方法很容易,直接代码调用就行,这人人都会。其次呢,还可以使用反射。不过通过反射调用的性能会远远低于直接调用——至少从绝对时间上来看的确是这样。因此,很多框架在必须利用到反射的场景中,都会设法使用一些较高级的替代方案来改善性能。例如,使用CodeDom生成代码并动态编译,或者使用Emit来直接编写IL。不过自从.NET 3.5发布了Expression相关的新特性,我们在以上的情况下又有了更方便并直观的解决方案。 阅读全文

概念,依旧是概念……csproj文件是做什么用的?

2008-08-04 08:57 by Jeffrey Zhao, 43732 阅读, 收藏, 编辑
摘要:本来今天是在写一篇关于LINQ的文章,不过写着写着忽然觉得有些找不着北的感觉,似乎有点过于发散了?于是来博客园逛了一下,正好发现有朋友发了一篇文章《.NET面试题,看看你的水平》,于是就在这篇文章里和目前正红火的小包子同学为某个问题进行了一番争论。而在吵吵闹闹的过程中看到这么一句话“pdb文件需要放在Debug目录下才有效果”,忽然觉得有个话题值得一说:“开发环境与运行环境”。回想起平时被问到的问题,发现有不少朋友对于开发环境和运行环境并不是分的非常清楚。那么就让我们从标题中的问题开始:“csproj文件究竟是做什么用的”。 阅读全文

觉得有必要来澄清几组重要概念

2008-06-04 01:51 by Jeffrey Zhao, 35838 阅读, 收藏, 编辑
摘要:在阅读很多朋友问题的过程中,以及平时和别人讨论中,亦或是园子里的文章中经常发现一些误用概念的情况。如果在概念上没有形成共识,那么在工作和交流上就会造成许多问题。因此,老赵已觉得有必要特地来澄清一些概念,解释一下这些概念之间的区别和联系。希望在明确这些概念之后,大家能够把注意力集中在对于具体问题的分析解决上,而不要让沟通成为瓶颈。 在这篇文章中,我希望澄清三组概念,它们是: AJAX / AJAX框架 / AJAX.NET (Professional) / ASP.NET AJAX LINQ / LINQ to SQL / LINQ to XXX Lambda Expression / Expression Tree / 匿名方法 阅读全文

您善于使用匿名函数吗?

2008-04-04 00:10 by Jeffrey Zhao, 29214 阅读, 收藏, 编辑
摘要:合理使用匿名方法能够大大简化开发,提高代码质量。您善于使用匿名方法吗? 阅读全文

扩展LINQ to SQL:使用Lambda Expression批量删除数据

2008-03-05 13:01 by Jeffrey Zhao, 40936 阅读, 收藏, 编辑
摘要:ORM框架在删除数据方面一直有个尴尬,那就是无法通过指定条件批量删除数据。于是对于一些删除操作,我们不得不写SQL语句或者执行存储过程。幸运的是C# 3.0所拥有的强大特性足以让我们对LINQ to SQL的功能进行扩展。为了更好地进行项目开发,以及周五的一次技术交流,我为LINQ to SQL扩展了批量删除功能。 阅读全文

LINQ to SQL异步查询

2008-03-01 01:51 by Jeffrey Zhao, 28941 阅读, 收藏, 编辑
摘要:异步操作是提高Web应用程序吞吐量的重要手段,关于这方面的话题已经在前文《正确使用异步操作》中解释过了。对于大多数互联网应用来说,性能瓶颈数据库访问。换句话说,一个请求在数据库操作上所花的时间往往是最多的——并且占总时间的90%以上。因此,当Web应用程序的吞吐量因为数据库操作的阻塞而受到影响的话,我们可是尝试使用异步数据库操作来进行优化。那么我们又该如何使用LINQ to SQL进行异步查询呢? 阅读全文

正确使用异步操作

2008-02-24 22:03 by Jeffrey Zhao, 41981 阅读, 收藏, 编辑
摘要:本想写一点有关LINQ to SQL异步调用的话题,但是在这之前我想还是先写一篇文章来阐述一下使用异步操作的一些原则,避免有些朋友误用导致程序性能反而降低。这篇文章会讨论一下在.NET中有关异步操作话题,从理论出发结合实际,以澄清概念及避免误用为目标,并且最后提出常见的异步操作场景和使用案例。这样我们就可以知道什么时候该使用异步操作,什么时候会得不偿失。 阅读全文

在LINQ to SQL中使用Translate方法以及修改查询用SQL

2008-02-19 03:02 by Jeffrey Zhao, 29378 阅读, 收藏, 编辑
摘要:目前LINQ to SQL的资料不多——老赵的意思是,目前能找到的资料都难以摆脱“官方用法”的“阴影”。LINQ to SQL最权威的资料自然是MSDN,但是MSDN中的文档说明和实例总是显得“大开大阖”,依旧有清晰的“官方”烙印——这简直是一定的。不过从按照过往的经验,在某些时候如果不按照微软划定的道道来走,可能就会发现别样的风景。老赵在最近的项目中使用了LINQ to SQL作为数据层的基础,在LINQ to SQL开发方面积累了一定经验,也总结出了一些官方文档上并未提及的有用做法,特此和大家分享。 阅读全文

WCF的Web编程模型资源

2008-01-24 02:11 by Jeffrey Zhao, 10533 阅读, 收藏, 编辑
摘要:.NET 3.5中增强了WCF的功能,为它提供了发布RESTful服务和Syndication(即常见的RSS或Atom)的能力。现在我们开发RESTful的服务或API就非常简单了。同样,无论是分析还是发布RSS也都有了现成的类库(开源产品中原本也有RSS.NET和Atom.NET,不过好像现在都商业化了?)。 MSDN上这方面资源很多,看完类库参考和示例代码(其实并不很多)一般已经足够了。不过... 阅读全文

在Linq to Sql中管理并发更新时的冲突(3):使用记录的时间戳进行检测

2007-11-23 09:21 by Jeffrey Zhao, 5488 阅读, 收藏, 编辑
摘要:在《在Linq to Sql中管理并发更新时的冲突(2):引发更新冲突》一文中,我们描述了Linq to Sql检测在更新时是否产生了冲突的基本方法:将该记录每个字段原来的值和更新时的值进行对比,如果稍有不同则意味着记录被修改过,因此产生了更新冲突。不过您是否有这样的感觉,这种方法实在累赘了一些?因此Linq to Sql提供了另外一种检测并发更新冲突的方式:使用记录的时间戳。这并不是Linq to Sql特有的功能,如果您了解其他的ORM框架的话,就会发现诸如Hibernate也提供了类似的机制——自然,在使用上不会像Linq to Sql那样方便。 阅读全文

是否会成为问题——Linq to Sql的执行可能无法复用查询计划

2007-11-21 08:43 by Jeffrey Zhao, 4629 阅读, 收藏, 编辑
摘要:复用查询计划是Sql Server降低CPU开销,提高性能的一个重要手段。但是Linq to Sql可能无法复用查询计划,这是怎么回事儿呢? 阅读全文

在Linq to Sql中管理并发更新时的冲突(2):引发更新冲突

2007-11-20 19:30 by Jeffrey Zhao, 3642 阅读, 收藏, 编辑
摘要:在上一讲中,我们提到了一些诸如“乐观并发控制”、“悲观并发控制”的概念,以及察看Linq to Sql自动生成sql语句的方法。从这篇文章起我们将继续来查看Linq to Sql在管理并发更新时是如何发现冲突问题的。 阅读全文

在Linq to Sql中管理并发更新时的冲突(1):预备知识

2007-10-30 23:49 by Jeffrey Zhao, 5325 阅读, 收藏, 编辑
摘要:无论与目前的ORM框架相比有没有优势,Linq to Sql在语言和平台的级别上为我们提供了一种新的操作对象和数据的方式,在一定程度上为我们解决了Object != Data的问题。在实际应用中,对于数据库的操作往往有着天生的并发性,因此在更新数据时可能会产生冲突。有些时候,如果没有合理的解决冲突问题,轻则让用户摸不着头脑,重则让系统数据处于一种不一致的状态。Linq to Sql自然考虑到了这一点,本系列讨论的内容,就是在使用Linq to Sql时,如何管理并发更新时产生的冲突。   本文为这个系列的第一篇,将讨论一些预备知识,它们是进行后续研究的基础。 阅读全文

WCF在安全性方面的支持(1):一些概念

2007-07-25 02:32 by Jeffrey Zhao, 8724 阅读, 收藏, 编辑
摘要:对于一个应用程序来说,最重要的特性之一就是安全性。安全性是如此的重要,自然WCF也会为它提供了良好的支持,否则也无法称之为一个成熟的模型了。 阅读全文

Enterprise Library 2.0 Test Guide下载

2007-02-12 02:43 by Jeffrey Zhao, 2022 阅读, 收藏, 编辑
摘要:在PnP小组推出Enterprise Library 3.0之前,他们又发布了一个“Enterprise Library Test Guide”。这是PnP小组测试Enterprise Library的构思过程和实际使用方法的整理,应该是份相当重要的参考。http://www.microsoft.com/downloads/details.aspx?familyid=9ad254e9-e1f8-4... 阅读全文

似乎离新的.NET Framework还很远

2007-02-09 03:15 by Jeffrey Zhao, 3958 阅读, 收藏, 编辑
摘要:http://blogs.msdn.com/ericnel/archive/2007/02/08/visual-studio-orcas-will-work-with-net-framework-2-0.aspxJust come off the phone chatting to Richard Costall, who besides his real job, runs the rather... 阅读全文