巴别塔上的雇工


SBS: 配得上SB的复数
7月 31, 2008, 2:11 上午
Filed under: 八卦杂谈

一大早看到新闻说韩国一个叫SBS的电视台曝光了奥运会开幕式的视频,让我感到很恶心,恶心之后又释然,这种违背行业道德的行为,也只有这种盗用其他民族文化不以为耻反以为荣的人群能够做得出来,对这种SB实在没什么可说的,不对,他们的名字有复数,是SBs,不是一个SB,而是一群SB。



www.cuil.com
7月 30, 2008, 9:22 上午
Filed under: 八卦杂谈

据说几个Google的“判将”搞了一个新的搜索引擎Cuil(发音同Cool),号称可以搜到1200亿个页面,大约是Google的3倍

我试了一下,输入“巴别塔上的雇工”,得到的结果是:

image

连我的Blog都搜不到,还谈什么是Google的三倍呢:-)



异步好…难 (Asynchronous Is Hard)
7月 30, 2008, 3:22 上午
Filed under: 技术体会

以前我写了一些关于异步的东西,异步是好东西,异步的确好,不过也好难,以至于.NET Base Class Library都没法把它弄好。

按照这个KB(http://support.microsoft.com/kb/947862)的说法,使用Socket和NetworkStream的异步API是靠不住的,这是一个很严重的问题!

我们来看看Stream异步读的接口什么样子

public virtual IAsyncResult BeginRead( byte[] buffer, int offset, int count, AsyncCallback callback, Object state )

我们使用这个API的时候,肯定要先分配一个byte array作为buffer参数,调用BeginRead之后,理论上当有数据出现在Stream上或者timeout的时候,callback应该被回调,但是,按照KB的说法,如果对方停止了I/O,可能永远也不会回调这个callback。作为参数buffer传递进去的byte array,.NET为了防止其被Garbage Collected,用一个内部的System.Threading.OverlappedData实例引用它,对每个一部调用都会建立一个OverlappedData实例,在异步操作结束的时候释放,现在,因为callback可能永远不会被调用,异步操作也就永远不会结束,对应的OverlappedData也就永远不会被释放,同样的,我们分配的byte array也就永远不会被GC,这段byte array也就等于leak了。

最近我就发现我的一个程序使用内存特别多,用Windbg一看,内存中有不正常数量的OverlappedData和byte array,原因就是使用了NetworkStream.BeginRead。

这篇KB上提供的解决方法是这样:

The .NET library that allows Asynchronous IO with dot net sockets (Socket.BeginSend / Socket.BeginReceive / NetworkStream.BeginRead / NetworkStream.BeginWrite) must have an upper bound on the amount of buffers outstanding (either send or receive) with their asynchronous IO.

The network application should have an upper bound on the number of *outstanding* asynchronous IO that it posts.

这样的解决方法说了和没说一样,到底这个"Upper Bound"是多少?有没有具体数字,难道要每个使用这个API的程序员来一个数字一个数字来试吗?我觉得根本就没有这样的"Upper Bound"能够避免这种问题。

我试着用一个Timer触发一个操作在timeout的时候强行关闭NetworkStream,结果导致的是Close函数Hang住了,所以,对这个问题,目前是——无解,只好使用同步I/O,这样最保险。

要想推广一项技术,必须要有可靠的支持,像.NET Base Library这样的支持,实在让人难以接受异步技术。这不是.NET第一次让我失望,也肯定不会是最后一次。

参考:

异步(Asynchronous)和可扩展性(Scalability)有关吗?

异步是正道



三亚
7月 27, 2008, 5:28 上午
Filed under: 山河好大

这次部门的Offsite活动出了一次远门,地点在海南三亚,颠簸了四个多小时的飞机后到达,第一个感觉就是——热,不是普通的热,是潮热。然后看到户外的棕榈树,真正感受到这是在热带地区,第一次到北回归线以南,感觉很新奇。

住在亚龙湾,这里酒店众多,依山傍海,环境还是不错。

DSC00010

DSC00038

同样,到处都是棕榈树。

DSC00025

亚龙湾因为价钱高,所以人少,现在又是旅游淡季,沙滩上稀稀拉拉没多少人。

DSC00050

第二天有机会去三亚市区看了看,市区的沙滩就全是人,和下饺子一样。

DSC00042

因为这次行程活动都安排得满满的,没有多少时间去沙滩,所以感觉也不是很过瘾。我比较喜欢逛逛有人问风景的地方,在三亚,基本上只有自然风景可看,也许下次来,可以安下心在沙滩上静静地享受大海的风光。

DSC00022



The Dark Knight: #1 in IMDB
7月 23, 2008, 1:05 上午
Filed under: 电影电视

最近讨论得很火的新片《The Dark Knight》在IMDB兵器谱上的排行短短时间就到了第一位,9.4分,在Godfather之前。

image

这是一个有趣的现象,我还没看过此片,但是各方面对此片反映都不错,估计差不了,但是仅从目前的排名也不能说此片就是最伟大的电影超越《教父》,新作品让观众激动一把,给分自然偏高。记得初中的时候有一个全国调查,青少年评选最喜欢的电视剧,第一是当时刚刚上映的《北京人在纽约》,在当时,这样一个全程美国拍摄主题和包装都新颖的片子的确吸引人,反响很大,现在过了十几年,回头看此片也算不错,但是要再调查一次的话,肯定不会再登榜首。

此片我们是没法在国内电影院看了,审查没过,又是一些不是很正面的中国元素,又是这样一个黑暗的主题,没通过审查也在意料之中,毕竟这是一个“黑暗骑士”,不是“和谐骑士”。



评价关于《赤壁》的评价
7月 20, 2008, 3:00 上午
Filed under: 电影电视

瞄了一下网上关于《赤壁》的评论,骂的还是比赞的多,另一方面票房也在节节攀升。有朋友说在中国看国产大片是“群体活动”,重在参和,至于大片本身怎么样是另外一个问题,我说也是,在中国,由于国产大片每年也就那几个,没多少选择,对票房来说,评论是褒还是贬是次要,评论多不多才是主要的,票房高不高看人气,这是目前中国特色的一种现象,不要说对这个现象定褒贬,这就是目前的现象。

和很多人的意见相左,我是觉得《赤壁》是个不错的电影,但是这里我不是要说这个电影到底是好还是坏。电影作为一种大众艺术形式,每个人的观点都会有主观色彩,一千个人看哈姆莱特就有一千个哈姆莱特,十三亿人看赤壁就有十三亿个赤壁,观点不同很正常。

先说说对赤壁的批评声音,如果上各个论坛一看,大部分都是批评,这能够说明观众中大多数人都是对这个电影持否定意见吗?未必,有意见的人倾向于把意见说出来,没意见的也没什么可多说的。我老婆看赤壁之前也不知道吴宇森不是按照《三国演义》来拍,看到几处笑场的地方也哈哈大笑,看完和我说演员都演得很好,尤其是张丰毅把曹操演活了,情节虽然和想象得不大一样,但是也不影响观看,电影拍的不错,大家高高兴兴地回家了,之后也不多说这个电影了。我老婆没我这么喜欢看电影,应该属于电影观众中的普通人,上电影院就图个乐,既不是满怀期待去电影院,也不是揣着板砖去的,这种人看了电影不会去网上发表评论的,所以网络的评论是不完全的。

看看这些评论的内容,我不禁想问,如果这个《赤壁》不是你喜欢的,那么什么样的《赤壁》是你想要的?我不是说《赤壁》的故事就应该和吴宇森制作的一样,但是既然不同意别人讲故事的方式,那可以想想这个故事应该怎么讲。《赤壁》不是一个完美的电影,世上本来也没多少堪称完美的电影,我这也不是说批评这个电影不应该,不同意见让人进步嘛,但是我想大家都应该想想,如果你觉得一件事情不应该这样,那它应该是怎样?你觉得这件事情不好,是因为你知道它好的样子是怎么样呢,还是因为别人说它不好,所以你也觉得它不好。如果只是有很多人骂,我不骂就显得跟不上遛,有很多人夸,我不夸就显得没有品位,这种想法那就太不应该了,对一件作品你本来有一个自主认识的机会,结果你的认识完全被别人左右了,谁也不会希望发生在自己身上的吧。

说这么多,其实就两点感想,一是对事情的看法需要有点独立思考,二是别带着板砖去电影院,去之前就觉得不好干脆就别去了,享受电影,要是带着挑刺的心态去看电影,就沦落成赵半狄之流了。



路边的字幕
7月 18, 2008, 3:23 上午
Filed under: 城市丛林

晚上在北四环看到“坑”的墙里面有不断变换的电子字幕:“同一个世界,同一个梦想”“树海淀形象”之类。

图像283

图像280



Talking about A Job Interview Quiz
7月 16, 2008, 6:10 上午
Filed under: 技术体会

 前几天说到的这道题,我说到的最后一个解法是空间复杂度最低( O(1) ),但是时间复杂度( O(n*log(n)) )不是最低的。实践复杂度最低的方法是用一个HashSet来储存每个元素x的对应的(M-x)值,遍历这个list的时候,对于每个当前元素x,看M-x是不是在HashSet上,如果在,算法结束返回true,如果不在,就把M-x加入HashSet中,继续下一个元素,所有元素都遍历结束则返回false。因为对HashSet的查找可以认为是O(1)的时间复杂度,所以总共的时间复杂度是O(n),空间复杂度也是O(n)。

Quotes

A Job Interview Quiz

Dev102.com经常有些Job Interview方面的题目,挺有意思,最近的一个问题是:

Given a list of n integers and another integer called m, determine (true / false) if there exist 2 numbers in that list which sum up to m.
Example: 2,6,4,9,1,12,7 and m=14 -> 2 and 12 sum up to 14, so the answer is true.
Provide the best algorithm in both manners: performance and memory to solve this puzzle. Don’t forget to mention the complexity of your solution!

这样的问题,最笨的办法就是把list中的每个数字都和另外所有的数字加一下,看结果是不是m,时间复杂度O(n^2),空间复杂度O(1)。

还有一种办法,时间复杂度为O(n),但是空间复杂度为O(K),其中K为list中最大数和最小数的差值。首先利用O(n)的时间得到list中最大值和最小值,假如分别为Max和Min,K=Max-Min+1,建立一个K大小的数组Array,每个元素初始化为false,这样[Min,Max]中每个数都能够在Array中找到一个位置表示它是否出现。遍历list,对每个数x,看Array[M-(x-Min)]是否为true,如果是,算法返回true;如果否,讲Array[x-Min]设为true,继续。如果所有list中数字都走完,还没有找到匹配的两个数,返回false。这种算法的思想是direct addressing,使用direct addressing的算法比同类型的都要快,代价是空间可能消耗得多。

如果不能忍受可能很巨大的O(K)空间复杂度,可以这样,先对list排序,然后从两头找合适的数字,排序的实践复杂度为O(n*log(n)),寻找数字的过程虽然用了两重循环,但是循环在O(n)时间内会结束,所以时间复杂度还是O(n),加起来时间复杂度O(n*log(n)),空间复杂度O(1),用C#写出来的code:

image



垃圾桶
7月 15, 2008, 1:39 上午
Filed under: 城市丛林

今天上班看到路边一大堆垃圾桶,似乎都是光荣退役的。

图像275

看样子为了Beijing2008,连垃圾桶也要换代了。

图像274

新型上岗的垃圾桶。

图像276



Talking about Should IEnumerable inherits from IEnumerable?
7月 13, 2008, 10:20 上午
Filed under: 技术体会

人的认识是在变化和增进的,你曾经觉得正确的事情,随着你接触的东西的增多,你就会改变观点。

我曾经写过一篇Blog表达了觉得在.NET中不应该让IEnumerable<T>继承IEnumerable的观点,现在回过头来看,这种观点不正确。就像Brad Abrams说的一样“IEnumerable<T> inherits from IEnumerable because it can”。如果没有问题,Generic Interface都应该继承对应的Non-Generic Interface,这是为了达到Contra-variance,假如有某个.NET1.X时代写的函数的输入参数类型为IEnumerable,现在有了IEnumerable<T>,而且假如IEnumerable<T>不继承IEnumerable的话,这个函数就没法接受IEnumerable<T>类型的参数,这可不好,因为IEumerable<T>和IEnumerable应该表现一样的行为。如同Brad Abrams所说,IList<T>不能继承IList,因为如果继承了就会带来别的问题,所做不到,IEnumerable<T>没有这样的问题,为了Contra-variance,就让它继承对应的IEnumerable了。

Quote

Should IEnumerable<T> inherits from IEnumerable?
.Net 2.0引入了Generics(泛型)的概念,原有的在System.Collectionis namespace下的接口几乎都在System.Collections.Generic namesapce下多了一个对应的Generic接口,不过奇怪的是IList<T>不是继承自IList的,而IEnumerable<T>是继承自IEnumerable的。

Brad Abrams有一篇Blog解释了为什么,但是实际上他只解释了为什么IList<T>没有继承IList。以他的观点,理想状况下,所有的新的支持Generic的interface都应该继承以前对应的interface,但是如果让IList<T>继承IList的话,那么是实现IList<int>的类就需要实现两个Insert方法,一个是IList<int>的void Insert(int index, int item),另外一个是IList的void Insert(int index, object item),这样对一个类对象obj,调用obj.Insert(0, 123)和调用obj.Insert(0, "abc")都是合法的,这不是我们想要的,因为我们既然继承IList<int>,就希望编译器能够做好类型检查,不让非int的物体插进来,但是这个继承关系造成了这样局面,所以IList<T>不继承IList。

上面IList<T>不应继承IList的理由很充分,但是并不足以说明IEnumerable<T>就该继承IEnumerable。当然,因为T对IEnumerable而言,只有“输出”作用,不像IList一样既有“输入”作用,也有“输出”作用,所以安全,但是,比较不爽的就是,每个实现IEnumerable<T>的类,不得不实现两个GetEnumerator,MSDN的sample code并没有强调这一点,弄得很多新手(包括我:)一开始只实现了IEnumerable<T>.GetEnumerator,被编译器的出错提示搞得莫名其妙。

我觉得就不应该让IEnumerable<T>继承IEnumerable,虽然这个继承关系似乎不违反LSP,但是我觉得LSP只是一个必要条件,不是充分条件。如果谁想让一个类既能是IEnumerable,又能是IEnumerable<T>,那就同时实现这两个interface好了,就和IList<T>一样:

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable