RSS 2.0 Feed
.NET CF
摘要:前一段时间已经发现CF在载入资源的时候会怪怪的,但是这一段时间都不曾记起要对这个问题研究一下。最近又发现这个问题了,实在是恼火。俗话说择日不如撞日(粤语),唉,就今天啦。这个问题是在VS2k5里面调试的时候才发现的,以前在VS2k3里面一直都不知道有这么一个问题存在。事情是这样的:有一次在VS2k5里面调试运行一个SmartPhone的程序的时候,发现突然在Output窗口里面显示了好几个First Chance Exception,仔细一看发现有两个FileNotFoundException,以及一大堆的UnathorizedException。而这些异常却没有引起中断,也就是说在程序的某一个部分被try...catch截获了。但问题是我的代码里面根本就没有任何的try...catch,不应该呀?后来仔细想想,又想到using也截获异常,所以一下子下不了定论。而我这个程序只有关于画图方面的代码,因此问题应该在画图相关的部分。我立刻想到有两种可能性,第一种是加载资源的时候引起了异常,另外一种可能是画图代码由一些可能引起异常、但是系统能够处理的参数。由于没有时间,开始的时候就没有仔细探索,反正能够正常使用。而昨天呢,我稍微研究了一下,发现问题确实是出在加载资源的部分。当你的SmartDevice程序里面包含了图片资源的话,并且通过资源管理器的GetObject获取这项资源的话,就会在内部引发一系列的异常——第一次引发两个,第二次引发另外两个,后面的就每次引发一个异常。简单的跟踪发现,问题可能出在本地化方面的问题。似乎在GetObject的控制流当中的某一个环节,会检查你指定的“文化(CultureInfo,不知道中文术语是否这么讲)”,然后找到相应的资源文件载入。这个资源文件是干什么的我没有仔细看,这只是一个粗略的分析,估计是用来显示出错信息的。由于没有指定CultureInfo,或者指定CultureInfo的资源文件没有被安装上来,结果就引发了FileNotFoundException了。至于后面的UnaotherizedException,我估计就是一开始引发了FileNotFound之后,某些初始化步骤出现问题的副作用引起的。这个问题也许值得花时间去了解清楚。大家都知道抛出一个Exception,无论代码有没有catch,时间开销都是相当大的。可以说如果你的程序有图片资源,其启动速度就会跟没有图片资源的相差非常大。大家可以试一下建立一个空白的程序,运行一下感受速度。然后在这个项目的Form上面添加3个PictureBox,设置它们的Image属性,分别换上不同的图片。再次运行的时候就会感到速度会有差异了(应该还好,不算很明显。)如果在VS2k5里面做这个实验就再好不过了,因为能够在Output窗口上面看到很明显的First chance exception项目的。这个CF如果跟桌面的.NET Frameword对比,真算不上是精品工程,越用就越多问题。无论如何,在正常使用的情况下抛出一个错误(虽然接住了),都是不正常的设计方式。呵呵,不知道现在VS2k5的beta里面是否有中文的Rom了呢?如果没有的话,下一次来看我的解决方案,今天不在工作机器上面,很多东西没法写,怕不准确害死人。OK,今天就这些。...[阅读全文]

posted @ | Feedback (7) | Filed Under [ .NET CF ]

摘要:1、读一文件2M大,与读144个共200K文件同速;2、快排序远比删除要慢(仅供参考)。...[阅读全文]

posted @ | Feedback (9) | Filed Under [ .NET CF ]

摘要:最近一直在忙于性能优化方面的调试工作,所以一直在研究这方面的问题。其实那些研究都是不着边际的事情,但是作为自己的知识储备,也算是一件有意义的事情。目前的工作算是“OK”了,不过我自己却不是很满意。在整个过程当中发现了不少的问题,首先是XML的速度,后来是FileStream的问题,接下来是Thread的互相影响问题。天啊!我真想喊出来,才解决了数据读取的问题又出现了Thread的问题——Ce里面的背景线程一旦运行,就会严重阻塞前台的线程。有没有谁知道CE里面(包括.NET CF里面)的线程机制是什么样的?是轮换式还是抢占式?优先级有没有作用?.NET CF里面的线程简直就是弱的不堪设想,除了能够让他运行起来,加上调一个优先级,就没有更多的功能了。不能够强制中断,不能够Suspend/Resume,也读不出来他的运行状态……真是要命,如果没有人能够给我答案的话只好自己慢慢找了。还好,目前的性能问题还可以含糊过去,比如让背景线程推迟30分钟之后再运行,但愿这样JGTM不会察觉出来他的存在。很久没有仔细去看看外面周围都发生了些什么了,今天下午真的要好好的看看一些很久没有看到的Blog了。比如Neil Cowburn和Alex Yakhnin的,发现里面又有好多新的东西了,真是很喜欢他们的Blog,虽然更新速度并不快,大师每篇都值得一看。不像我这个Blog,充满了不可阅读的或者不值得阅读的废话。哎,废话少说,还是来看看最近他们都说了些什么吧:(所有内容未经我亲自验证,仅代表原作者观点)Neil Cowburn说:Ultra-Simple Application Logging原来在.NET CF上面开发,如果想要Log一些东西是这么简单的。大概意思就是通过P/Invoke改变标准输入输出流的方向,然后就可以直接用Console里面的方法来输出字符串到一个特定的文件里面了,没错,就那么简单。Pocket PC Magazine Best Software Awards 2004 -- WE WON!opennetcf.org获得了PPC Mag 的2004年度最佳软件大奖。嗯,应该指的是里面的SmartDevice Framework吧?说句老实后,这个东西确实是一件神奇的东西,它能够快速的解决许多你认为非常头疼的事情(也许待会儿我要到那里面找找有没有增强型的Thread类),尽管里面有很多地方有Bug。Bug不是问题,因为这个东西完全免费和开源,只要你自己会调试,水平足够的人都可以自己去截取代码和修改。这个东西最大的问题是:太大了,也还不够大。一方面我希望他能够小巧一点,因为这么大的东西会影响加载速度和占用内存的空间,而我自己又想偷懒,不想老是自己截取代码来避免这个缺点。另外一方面我却希望他能够解决更多更多的问题,比如COM交互,或者DX之类的东西,哈哈,这个就真是勉为其难了。总结一下,SD Framework还是很好D……Craig on .NET Compact Framework 2.0Craig是谁?我不知道,他最近在一个内部培训的时候进行即席演讲,并录了下来。他说了一些他觉得.NET CF 2.0里面最让他喜欢的东西,不听的话你真是错过了很精彩的东西!比如说,.NET CF 2.0 里面将会有Generics,有Iterators,有Com Interop,有Sql CE 3.0,有DX,有SMS Queue,有直接操作Inbox的能力,有Data Encryption,有Location Based API,有Camera API,有……听得我是极度兴奋(还有性能改善忘了列出来了)。不过这个只是内部培训的时候录下来的,估计是为了训练演讲能力,提高培训能力的。(上一次有幸参加了MS给MVP做的类似培训,感觉棒极了。哈达不一定赞同,他水平太高了……)毕竟不是官方的东西,可信程度还是不高,不过也比我自己瞎吹要好多了。嗯,别的东西我不要,就要Generics、Sql ce.NET、DX,还有性能提升,就这些了,我还是不太贪心的。这里还有另外一个录像,我还没有仔细看,大家也可以看看,是关于ASP.NET 2.0的(显著优点的)。这个Post实际上是来自Carter Maslan的。CFNunitBridge GotDotNet Workspace嗯?CF也上NUnit了?嘿嘿……怀疑ingWho would like to fly Virgin Galactic?FT,还有可以飞到室女座星云的方法?Neil想,我可不想。那么大的星云(跟银河系一般大)要找个落脚点可不容易,目前人类在300光年的范围以内都尚未找到和地球环境相近的星球,更何况要在一个直径是万光年的星系里面去找,真是茫茫大海呀……Meet the Visual Studio for Devices Team关于Visual Studio for Devices Team里面的录像Using POOM with .Net Compact Framework Whidbey Beta1 前面说了.NET CF 2.0 可以POOM,这里有一个例子可以去看看。Show me your desktop!看看人家多好,最小的也使17寸的液晶……羡慕有两个显示器,以后有钱了一定要买四个显示器,一个打开VS2kX玩玩,一个运行自己写出来的程序玩玩,一个摆着玩玩,还有一个摔着玩玩……Catch-up Round-up都是一些连接,值得一看。Visual Studio For Devices Team BlogVSD Team的Blog,如果你对如何改进VS有什么想法,可以给他们说说,也许会管用。Alex Yakhnin 说:Accessing Memory Mapped Files from CF这个是关于在CF上面使用FileMapping技术的Post,值得研究。Nota bene...这个……这个……Using cordbg for .NetCF其实也是转自别人的Blog,好像Neil也转了。值得研究,这样我们也许有机会知道.NET CF里面到底搞了些什么小动作。Great info on Managed App Startup and Retargeting有点深度的内容,具体是什么还没有仔细看。好像说的是.NET......[阅读全文]

posted @ | Feedback (16) | Filed Under [ .NET CF ]

摘要:刚才对.NET CF内部的代码的分析得知,FileStream.Position对性能有严重的损耗,那么我们如何去解决的这个问题呢?1、如果你可以自行计算当前位置,那是最好的了。比如for(int i = 0; i < fs.Length; i++),或者有一个count变量自行累加,然后通过while(count < fs.Length)来进行循环。2、如果上面一个条件无法达成,那么可以考虑使用上文所示代码,用MemoryStream来进行间接读取。虽然需要从文件搬到内存,然后再进行读取操作,看起来绕了一圈,但是实际效率还是相当不错的。3、如果文件超出内存能够承受的范围,那么只好自己编写一些更加复杂的代码了。比如一小段一小段的用MemoryStream来读取,或者自己写一个替代FileStream的类。也许大家会困惑,难道还有情况不方便进行当前位置的计算吗?不方便的情况其实还是有的,最简单的比如BinaryReader.ReadString(),这个函数读取了多少个字节取决于编码的方式,以及该字符串的长度。由于它使用了一个7BitEncoding的方式来压缩字符串长度信息,因此整个字符串到底占用了多少文件空间还不是一件特别简单的事情。具体的代码可以自己看一下BinaryReader/BinaryWriter里面的Read/Write7BitEncodedInt函数,简单点讲就是,如果该字符串所占字节数n(注意不是字符串当中字符的个数)小于等于0x7f,则为1+n个字节;小于等于0x3fff,则为2+n;小于等于0x1fffff,则为3+n;小于等于0xfffffff,则为4+n;否则是5+n。另外一种比较罕见的情况是,你需要把这个FileStream交给一个你不认识的模块去处理,因此你无法得知读取了多少字节,也无法保证当前读取位置是否已经被强行修改了。关于如何处理这些问题,相信是见仁见智了。写到这里,我就不断感叹,CE上面的资源是在是少得可怜(相对于桌面来说),尤其是SmartPhone。其实一个项目的开发过程,还是需要考虑到一些技术细节。也许每一个阶段考虑的范围不一样,例如最初的阶段我们首先需要解决领域模型的东西,这个时候我们不能够被技术细节所束缚,不能够因为我们希望使用.NET CF所以我们不解决某个需求等等。但是随着进度的推进,技术细节就开始逐渐地进入了我们的视野,我们绝对不能够视而不见的。举一个例子,如果老板说,我们要进行一个单片机开发,片上内存4-8k,最多的片外内存是64k,那么一切关于OO的东西几乎就是瞎掰。当然,反过来的极端也是不可取的。如果在比较开始的阶段就过分的考虑技术细节也是不正确的,例如Xml可以为我们的开发工作提供方便,它的强大的描述能力和简单明了的格式,使得我们希望产生某些数据变得相对简单,那么为什么我们要舍去不用呢?一开始就专门开发一种工具,也许就会限制你的思路,因为可能你会觉得有效率问题,所以所有扩展性都是奢侈的部分。最后其实一个依赖于扩展性的项目却因为一开始设计的文件格式不支持,而无法完成开发,那这个代价就太大了。其实目前我遇到的情况是使用了Xml之后发现性能上面有非常严重的问题,但是相对来说还是比较庆幸当初使用XML作为数据的载体。因为开发过程确实比较轻松快捷,而且也拓宽了我们的思路,发现原来有些东西确实考虑的不周到,也搞清楚了一些原来毫无概念的东西。那么现在怎么办呢?技术问题相对于设计问题还是比较好解决的,比如说我们可以做一个简单的XML->特殊二进制格式的转化工具,就能够极大地提升性能。目前对于6000项数据的完整遍历,大概在19秒的级别,再加上一些其他的优化手段,目前能够达到3秒左右的级别,基本上属于可以接受的范围。(从197秒到3秒,提升幅度还是比较夸张的。)写着写着就回忆起以前写自己的文件格式,现在还是念念不忘,后来逐渐认识到随着主流软硬件系统的性能提升,一些比较简单但是相对低效的文件格式比如Xml(不过我用Xml的机会非常少,几乎就是没有用过),其效率也慢慢变得可以接受,就不再愿意去做这种费时费力的事情了。没想到今天还是要开发一种特殊的二进制格式,感觉又回到了过去386之前的时代了……640k的物理限制,40MHz的CPU……其实现在在手机上用.NET CF开发也好不到哪里去,还是要不断的优化优化再优化。幸好以前在这些方面还是有一定的基础,不然真是手忙脚乱了。p.s.: 会不会有人说,你的197秒怎么来的,在我这里才20秒不到的样子。呵呵,那我估计你是在P4 2.8(HT) 1G内存或者以上的机器上跑的模拟器吧?模拟器在大吞吐量方面的操作要比真实手机要快10倍左右,比如这种大量的文件读写操作。但是如果是普通的密集运算,两者就几乎不相上下了,甚至有可能手机还要快一点(比如启动的时候)。今天就到这里吧,下次再写。(唉,明知道周末人看的人少,还那么努力不知道为什么……)...[阅读全文]

posted @ | Feedback (11) | Filed Under [ .NET CF ]

摘要:不知道大家有没有对我上面写的那个程序在.NET CF上面跑一遍?怎么样?感觉如何?大家肯定完全没有耐心完成整个过程,大概看到第一个输出之后,就基本上“死机”了。等了五六分钟时在不耐烦了,断点调试一看,fs.Position才到xxKB到xxxKB之间,基本上绝望了,这就是我当时的感觉。但是千万不要放弃,请把while语句直接读FileStream的那一段去掉,重新来一遍。这一次怎么样呢?奇怪吧,绕了一个大弯,申请了一块巨大的内存,然后再用MemoryStream来读,速度远比FileStream快很多。我猜大家刚才还在注意那个BinaryReader,觉得那是一个累赘,一个可能的效率瓶颈。其实问题不在那个BinaryReader身上,相信大家已经知道问题在FileStream的Position属性上面了。用Reflector一看,果然问题多多:FileStream上面的Position计算非常麻烦,尤其是如果你一遍写一遍读的话问题会更加严重(不过本来问题已经够严重了,估计你不会觉得会有什么差别,麻木了)。 public override long get_Position(){      if (this._handle == HostNative.INVALID_HANDLE_VALUE)      {            __Error.FileNotOpen();      }      if (!this.CanSeek)      {            __Error.SeekNotSupported();      }      this.VerifyOSHandlePosition();      return (this._pos + ((this._readPos - this._readLen) + this._writePos));}首先需要经过两个判断,虽然没有多大的性能损失,但是我还是觉得不雅观。要命的就在那个VerifyOSHandlePosition里面: private void VerifyOSHandlePosition(){      if (this.CanSe