瞎折腾


Down with GFW

by yurii

In a place no one can tell,
dwells gfw, the great firewall,
like a demon from the hell,
valuable information, it blocks them all.


Bureaucrats said, internet opens a door,
meanwhile, they shut out sites for fun,
day by day, the wall grows tall,
one by one, bypass software fall down.


People told me, the wall’s father is  Fang,
something of, a so-called scientist,
for his idea, netizen’s nightmare begun,
due to his wall, websites became “connection reset”


GFW, down with you!
Sooner or later, we will get back our own view!

Comment: In 1987, China sent out its first email declaring “Across the Great Wall we can reach every corner in the world!”

GFW, go hell!

beta技术沙龙越办越有意思了,上次错过了阙宏宇的mod_cache(还有关于线程进程的讨论)就很可惜,这次关于Lucene的演讲,是无论如何不应该错过了。

到目前为止,全文检索已经完全不算高技术门槛了,记得以前看过一本书里面写:“今天,任何程序员,都可以很容易地构造一个全文检索应用”。是的,全文检索的基本原理大家都知道差不多了,剩下的只是实践。我见过纯粹自己开发的,具有AS(Advanced Search)、BS(Basic Search)、DI(Digest)等结构,“像模像样”的全文检索架构,不过应用更多的,却是在开源项目上完善、定制而来的,Apache的Lucene就是众多开源全文检索项目中,名气最大、资格最老、应用也最广泛的一个。本期beta技术沙龙,讲的就是大型网站中lucene的应用,主讲人是手机之家团队的唐福林(“手机之家”总是有些东东来共享,比如上次的DAL,这真是不错)。

众所周知,用Lucene构造一个“索引-查询”的应用是非常简单的,搭好环境,参照(修改)示范代码,很容易就可以成功。但是,要构造一个真正大规模、稳定、可靠的应用,就不说这么简单。程序的编写、模块的分布、架构的设计,都有许多费心思的讲究。按照PPT提供的数据,手机之家目前的Lucene应用,采用的是Lucene 2.4.1 + JDK 1.6(64 bit)的组合,运行在8 CPU, 32G内存的机器上,数据量超过3300万条,原始数据文件超过14G,每天需要支持超过35万次的查询,高峰时期QPS超过20。单看这些数据可能并没有大的亮点,但它的重建和更新都是自动化完成,而且两项任务可以同时运行,另一方面,在不影响服务可靠性的前提下,尽可能快地更新数据(如果两者发生冲突,则优先保证可用性,延迟更新),其中的工作量还是非常大的。

演讲的主要内容都PPT里,非常丰富,我就不再赘述了。要补充的是,这份PPT做得非常清楚,需求-目标-进度-设计-上线-测试-上线,整个流程非常清楚,给出的数据同样非常精当,我想,这也反映了手机之家团队的开发规范。

因为对Lucene的使用稍微有些经验,我在这里补充几句,权当狗尾续貂:

  1. 在大规模的应用中,Lucene更适合用于狭义的“搜索”,而不应当负责数据的存储。我们看看Lucene的源代码也可以知道,Document和Field的存储效率是不够好看的。手机之家的团队也发现了这一点,他们的办法是,用Lucene存放索引,用Memcache + Berkeley DB(Java Edition)负责存储。这样有两个好处,一是减小了Lucene的数据规模,提高了程序的效率;另一方面,这套系统也可以提供某些类似SQL的查询功能。实际上,Lucene Project自己似乎也注意到了这个问题,在Store中新增了一个db选项,其实也是利用的Berkeley DB。如果仅仅用Lucene存放索引,而不存放Document,并且合理配置,一台机器可以支持几十G甚至上百G的索引;如果需要用Lucene存放索引,最好在读取时使用FieldSelector,只读取需要的Field,如果使用恰当,性能会有10%左右的提升。
  2. 在大规模应用中,Cache是非常重要的。PPT中也提到,可以在程序提供服务之前,进行几次”预热“搜索,填充Searcher的Cache。据我们(银杏搜索)的经验,也可以在应用程序中,再提供针对Document的Cache,这样对性能有较大的改善(同一个JVM内部的Cache,速度更快一些)。Lucene自己似乎也注意到了这个问题,在2.4版本中提供了Cache,并提供了一个LRU Cache实现。不过据我们测试,在极端情况下,这个Cache可能会突破大小限制,一路膨胀最后吃光内存,甚至从网络上找的许多LRU Cache实现在极端条件下都有可能出现这样的问题(这也是我们百思不得其解的地方:反复检查程序的逻辑都没有问题),最终自己写了一个LRU Cache,并修改多次,目前来看是稳定的。
  3. 在编写Java服务程序的时候,记得设置退出的钩子函数(RunTime.getRunTime.addShutdownHook)是一个非常好的习惯。许多Java程序员都没有这种意识,或者有,也只是写一个finalize函数,结果程序非正常退出时,可能造成某些外部资源的状态不稳定。拿Lucene来说,之前的IndexWriter是默认autoCommit的,这样每添加一条记录,就提交一次,好处是如果中断,则之前添加的记录都是可用的,坏处则是,索引的速度非常低。在新版本中autoCommit默认为False,速度提升明显(我们测试的结果是,提高了大约8倍),但如果中途异常退出,则前功尽弃。如果我们添加了退出的钩子函数,捕获到退出信号则自动调用writer.close()方法,就可以避免这个问题。
  4. 目前的Lucene是兼容JDK 1.4的,它的binary版本也是JDK1.4编译的,如果对性能要求比较高,可以自行下载Lucene Source Code,用更新版本的JDK编译出.jar文件,据我测试,速度大约有30%的提升。
  5. 如果对并发的要求较高,可以考虑采用多IndexSearcher的技术,也就是在一个应用服务中,开启多个IndexReader(可以对同样的索引开启多个),每个IndexReader再生成一个IndexSearcher,将这些Searcher放在一个“池”里头,给搜索请求调用。这样可以大幅度提高并发的性能,代价是在写程序的时候就要考虑到这一点,进行相应的调整。

P.S. 据我观察,国内公司内部的项目,一般取的名字都中规中矩,以’er’结尾的比较多,多是Indexer, Crawler, Layer之类。好像很少有外国那种“天马行空”的奇特名字,譬如Hadoop(这是一个“没来由”的名字)、Lucene(这是个少见的姓)。国内我接触过不多,以前抓虾有个重要的DB叫tudui(“土堆”),目前银杏有个项目叫LaserTank,都是跟实际用途毫不相关的,印象反而深刻。

虽然医生嘱咐要静养,可谁让“小姬看片会”那么好玩呢?周六下午两点钟,我顶着大太阳来到微软亚洲研究院地下一层的会议厅,加入了第9期小姬看片会。

本次看片会的主题是“人工智能如何改变世界”,选的影片是BBC的VISIONS OF THE FUTURE。这样“科技含量高”(用松鼠的行话说,就是“高级”),又比较偏IT的主题,放在这里举办(尤其还有免费饮料提供),真是再合适也没有了。
参加的人很多,看来大家热情都比较高,我首先找了个僻静地方“潜伏”下来,过会儿居然有人来打招呼,一看居然是刘未鹏,不久又遇到图灵的刘江老师。寒暄一阵,眼看影片要开始了,我提议搬三把椅子坐到中间的过道里,这样比较靠前,大家一致同意,于是搬了三把椅子,在过道里前后排成一列,影片正好开始。

影片分好几个方面,介绍了广义上的“人工智能”:模拟人类行为、虚拟现实、机器与生物的结合等等。关于狭义的“人工智能”,也就是与“智慧”相关的内容,并没有占太多的比重。我觉得,作为科普影片,这样的安排,是没有错的。
影片结束之后,照例是嘉宾与观众的互动环节,这次的嘉宾都很“高级”,几乎都是IT专业人士,即便有研究科幻非IT人士,来头也相当大。难能可贵的是,他们回答起问题来,丝毫没有普通人想象中的“死板”,而是妙趣横生,许多时候台上台下笑成一片,这正好应了松鼠会的口号:让科学变得有趣。另一方面,它也说明,活动办得非常成功。

我不是研究人工智能的,只是以前稍微看过一点点资料,参加完这次活动,也有两点想法,可惜小姬没给我当场提问的机会(观众实在是太热情了),写在自己blog上吧。
关于“人工智能”,我想大概可以分为好几个方面,之一就是“仿真”(也就是模拟生物体的机能),在片中我们可以看到,现在已经有机器人可以惟妙惟肖地模仿人类的许多行为,譬如会走路的机器人Asimo;换句话说,神秘而简单的生物行为,可以通过物理模型、数学公式来分解,加以实现。人类“潜意识”里的某些“感性”动作,譬如“向前走五步”,可以转化为一系列精妙的指令,以另一种方式来“理性”实现。当然,这个方面也存在困难,譬如王启宁博士所说,用电气元件模拟生物行为,总是存在若干困难,因而有时候,“电气元件–生物”混合的方式,反而效率更高。这一点在影片中也有提及,研究人员记录了小白鼠脑内的海马区(与短期记忆相关的区域)在不同情况下的电流脉冲,再照这些规则制造出芯片,植入小白鼠体内,据称“反应速度提高了40%左右”。我对这个例子很有兴趣,可惜,它在影片中只是一带而过。
另一个方面,也是大家非常感兴趣的方面,就是“机器能否具有智慧”,或者说“机器能否像人一样思维”。这个问题,关于这个问题,前面有过著名的图灵检验,后来塞尔教授又提出过“中文屋子”问题,于是产生了“强人工智能/弱人工智能”的分野。按照程序的逻辑,我们关心的是“接口”,而不是“实现”。也就是说,不管我们面对的“其实”是机器,还是人,只要我们无法做出区分,就可以认定,对方“就是”人,虽然就其“本质”上来说仍然是机器。我之所以对那个小白鼠的例子感兴趣,原因也在这里:如果我们不去关心这些脉冲所“承载”的意义,而只是在“黑屋子”外,模拟我们观察到的一切,能产生完全相同的结果,那么或许可以说,电脑模拟的这些信号,本身也“承载”了同样的意义?
关于这个问题,现场的毛老师也提到,关于“什么是人(智慧)”,我们目前可能很难给出一个确定的定义,而只能通过多个特征加以描述和归纳,如果机器实现了这些特征,我们仍然“愿意”觉得,这还是与人有区别的,或者说,大家心中,其实多少还有一点对“人类本质”的偏执。在我看来,这有点类似波普尔所说的“本质论”和“标签论”的关系,通过“贴标签”而不是“追求本质”的方式(譬如把某种现象定义为“重力”而不是研究“重力的本质是什么”),科学已经取得了长足的进展,未来有一天,如果我们彻底无法区分面对的是人还是机器,我们是认定“这就是人”,还是心智紊乱,或者苦心积虑地找到另一种“定义”,把对方排除出“人”的范畴?这是个有意思的问题。
另说一点,在看片的时候,我忽然想到象棋与围棋,机器“深蓝”已经可以在国际象棋上打败人类世界冠军,但是对于围棋,目前人工智能却束手无策,最好的围棋程序,也敌不过一般的围棋爱好者。大家认为,主要原因是围棋的可能性太多,决策树太过复杂,超过了目前计算机的计算能力。如果人类的大脑能够处理这样两类计算量迥然不同的任务,这到底说明,我们理解棋类游戏的算法思路有问题(也就是说,大脑的运算能力是一定的,只是我们还没找到围棋的高效算法),还是人类大脑的运算(思维)能力,其实是不能以单一维度衡量的(从某个维度上来说,在解决围棋的问题上,大脑可以展现出远远高于象棋的计算能力)?

好了,闲话这么多,就此打住。最后给松鼠会提两点意见:
1.我看片的时候,听讲解的同时看了看字幕,发现字幕有一些翻译错误,所幸不是很严重。因为字幕是合成在影片一起的,所以,这样的问题也不能怪罪松鼠会。不过以后准备材料时,多注意一些这样的细节(如果同一部片子有多个字幕,不妨选择质量最好的那个版本),另外互动环节如果出现问题应该当时纠正(比如有人说“吃转基因食品,我们的基因就会随之变化”,应当有人马上澄清),可能更好点。
2.如果能够在影片结束后,做一些入门性的背景介绍(譬如这一次的,可以介绍图灵检验,中文屋,图灵完备性等概念),这样可以真正“以科普为中心”,而不会“以影片为中心”,对主题起到辅助和补充的作用(而不限于影片所介绍的知识),在专业的嘉宾和热情的观众之间夯实基础的沟通桥梁,效果可能更好。

杭州的事情,一路看下来,已经没什么好说的了。我委实很难想象,也更难以理解,要怎样的教养,才能在撞死人之后能够无动于衷,漠然地坐在车里,遮住脸孔;

我也难以理解,要经历怎样的阵仗,才能面对这样的境况,依然谈笑风生,镇静若素……


再看接下来的表演,我只想到蒲松龄的那句话:“禽兽之变诈几何哉?只增笑尔”。古人尚且知道,扬汤止沸,莫如釜底抽薪。“担心引起群体事件”之类拙劣的借口,哪谈得上什么“尊重传统”,纯粹就是对传统的彻底倒退和背叛。

在这样的现实面前,你再去看去年那句著名的口号,只会想到两个字:荒谬!或者,我们不妨把它改得更确切些:

One City, Two Worlds!

现实的世界这么复杂,上帝到底起了什么作用?
有人说,上帝就是创生世界的第一因,他是这个因果链条的第一环,然后世界就“自顾自”地出现了;
也有人说,其实因果链条上的每一环,表面看来是逻辑联系,其实都是上帝的意志;

这个问题我们不回答,我们能确定的是,在这个高科技的社会,生活中的各种事务,背后都是技术的“意志”;正因为如此,温伯格在《技术领导之路》中说,在这个时代,技术人员拥有强大的力量,只是需要发掘自己技术(技术知识)的价值,所以他还会花专门篇幅讲到力量转换。

今天写上面的话,是因为今天又看到有朋友在不厌其烦地详细介绍wordpress的维护。我想说的是,作为技术人员,不妨多动些脑筋,想想如何依靠技术解决更广泛的问题。譬如Wordpress的维护,我之前也饱受折磨,某天终于发现,PHP可以直接调shell,shell里面又可以直接调mysqldump——这样,只要简单几个Web页面,就可以完成wordpress的升级、文件备份、数据库备份和恢复,再通过Cron,就实现了blog的定期备份和日常维护,从此高枕无忧。

技术的力量,其实无所不在。

俗话说“无巧不成书”,还真是这样。上周末的“巧”,就是RSS:周六跟抓虾的朋友们聚餐,周日下午Beta技术沙龙的主题就是“网易有道RSS阅读器”。

Beta技术沙龙在詹膑老师的“奇遇花园咖啡馆”举行。在车水马龙的西直门,能找到这样一个安静的地方,实属不易(当然也很难找,我们开玩笑说还应该开一家“齐秦菜园餐馆”)。装修也别有味道:明亮的落地窗,颀长的红色窗帘,极高的天花板……第一次去的时候,我瞥见高架上堆放着一排白色的书:“看那样子,应该是川端康成的《雪国》和《伊豆的舞女》吧?”,詹老师微笑颔首。

“有道”这个品牌,最早应该是作为博客搜索引擎出现的,07年末又诞生了有道阅读器。如今RSS在线阅读器日趋流行,有道赶上了好时候,又可借助网易的资源,相对其它一些阅读器,条件好得有点让人嫉妒,但是能在一年多的时间里做到今天这样的程度,也确实下了不少工夫。此次来的三位嘉宾,胡琛、王焱和刘懿,分别从运营、技术和产品三方面介绍了有道阅读器,包括遇到的问题,解决的办法,对未来的思考……看得出来,他们的准备非常认真仔细。
当然,既然名为“技术沙龙”,参与者最关心的,还是技术的方面:系统的架构是怎样的、采取了怎样的策略、出现问题如何解决……看他们的PPT,我最深刻的感觉是“天下大同”:各家的技术,或许细节上有所差异,但总的思路和方向,大抵不会相差太远。当然,最让我羡慕的还是他们可以使用网易的存储系统,轻松备份超过20T的数据,高枕无忧,这太让人嫉妒了(曾经有天晚上,我因为太困误删了极为重要的用户数据。当时已经十一点半,就准备休息了,结果惊出一身冷汗。而且之前没有及时备份,所以只能想法从四处导出数据“拼”回来,折腾到四点才算写完恢复程序,让它正常运行,第二天总算没让用户发现,那次事故印象太深刻了)。

整个沙龙的气氛轻松而随意。主题演讲结束之后,主持人说:“下面大家自由开小会吧”,于是会场瞬间热闹起来。坊间传言:“沙龙的成功程度,取决于小会的热闹程度”,这样看来,沙龙是很成功了。

这次活动还有点小意外——有位素不相识的朋友(原来是Robin)很意外“没想到《精通正则表达式》的译者也在场”。是的,我们都没想到,这倒正合咖啡馆的名字:奇遇花园。

现场图片(如果这是一张世界地图,我就在新西兰的位置:))

认知心理学中有这么个实验:被试面对一红一蓝两盏灯,要求预测每次实验时哪一盏会亮起来;实验要进行许多次,并按照准确率给予一定的报酬。实际上,每轮实验,红灯亮的概率都是70%,蓝灯是30%,但是两种灯的点亮顺序是完全随机的。
在实验中,大多数被试很快就发现了,红灯亮起的频率要远高于蓝灯。尽管如此,大多数人都希望找到一个模式,能够准确地“预测”下一次亮起的是什么颜色的灯。极少有人认识到,如果“两眼一抓瞎”,全部猜红色命中,反而能有70%的准确率——只是这样选择必须克服“明知道会错”的心理障碍。而追求“100%”的准确,即便能够在红灯亮起的70%中命中70%,蓝灯亮起的30%中命中30%,仍然只有(70% * 70%) + (30% * 30%) = 58%的命中率。
这个实验说明,即便需要面对不确定性,人还是偏好“完全准确”的预测,哪怕依据毫无道理,哪怕“愚蠢”的做法本来能够带来更高的收益。

生活中,我们经常可以看到的“赌徒心态”,就是这种心理偏好的表现:赌徒往往希望获得100%的准确率,因此尽管大多数赌博属于“独立事件”(也就是说,前一次赌博和后一次赌博之间是互不影响的),赌徒仍然希望构建出一个模式,实现“更准确”的预测。卖彩票的地方通常会挂一张大图,显示“中奖趋势”,“预测”将来走势,这也是“赌徒心态”的常见形式(这里需要补充一点,有人潜心“分析趋势”,结果“中了大奖”,但“分析趋势”与“中大奖”两个事件之间,其实只有时间上的先后关系,不存在逻辑上的因果关系,这道理就好像“春天在夏天之前,但春天不是夏天的原因”一样)。
别理解错了,我并不是说,赌博的时候不必动脑筋,应该纯粹碰运气。我的意思只是,在不可能有什么“准确”规律的地方,去追求100%的命中率,无异于缘木求鱼,是完全徒劳的。有头脑的赌徒不会做这样的事情,他们能获得较大的胜率,借助的往往是上面红蓝灯测试中“接受错误来减少错误”的原理。有兴趣的读者,不妨去翻翻费曼写的《别闹了,费曼先生》,看看这个通晓统计原理的家伙,是怎样下注的。

我们深入思考就会发现,不信任统计学,否认或者逃避客观存在的偶然性,其实是“赌徒心态”的根源。在现实中,这种“力求百发百中”的心态还有另一种表现:对于没有100%——或者说,非常大——把握的事情,就不愿投入精力。常见的情景就是,不少人既想学(干)这个,又想学(干)那个……但仔细想想,这个也“不一定”会有好结果,那个也“没把握”会有大的收获……。最后的结果往往就是,迟迟不敢选择(借口是“还没想好”、“还没把握”、“要谨慎”),时间就这样白白浪费了。
有人会开脱说:凡事要“想明白”再动手。然而,他们希望的“想明白”,其实还是希望知道一个准确的结果,“这个有50%的成功率,那个有60%的成功率”,是他们不愿意见到也不愿意接受的,“现实那么复杂,这类‘没定数’的事情还是不要白费气力了”——于是就要继续“想明白”,甚至用终生来“想明白”了。
的确,我们的生活由无数的因素构成,充满了偶然性。许多事情的规律,只能用统计概率来描述,尽管我们更偏爱“准确”的结果,但充满“偶然”的客观现实,我们应该有勇气接受。其实我们也能够接受。说明这个道理,我常举的例子就是:动手术,有两种方案,一种的成功率是50%,另一种是70%,尽管这两个数字都是大量采样之后的结果,尽管手术失败对于个体来说就是0%的成功率,但是,大多数人无疑都会选择70%的方案。也就是说,即便面对充满偶然性的概率问题,大家其实是能够接受统计规律,也懂得如何选择的。

这些年来,我见过许多人否定学习的理由就是:“学那玩意干嘛?将来又‘不一定’会用到(或者是,谁知道将来怎么样呢)”。其实它的潜台词是,“不如再等等看看,看明白了、有把握了再说,至于现在,还是放松放松好了”。
是的,许多事情有点“撞大运”的色彩:天上掉下的馅饼,不太可能正好掉到你手上。但是,你手里的盘子越大,一旦馅饼掉下来,还是“更有可能”掉在里头的。所以老话说,“机遇只偏爱有准备的头脑”,而不是“有准备就能遇到机遇”,也不是“没看到机遇之前,别做准备”——所以又有句老话说“所谓幸运,就是你做好了准备之后,机会恰巧来了。”

做翻译的人,往往有种怨念:自己花了无数心血,费尽周折,在译文中熔铸了各种精巧,一般读者却难以体会,视而不见,或者仅仅觉得“通顺”、“流畅”;另一方面,一点点的错误,或是纰漏,往往为人诟病,斤斤计较。一句话,翻译是个苦差事,读者太难伺候,对译者不公平

不可否认,这种困境的确存在,然而,它真的“不公平”吗?我看未必,理由有两点:

  1. 社会分工必然造成这种“困境”。亚当·斯密在《国富论》的开头就说,“分工带来效率”,虽然当时他是单就生产而言,但“分工带来效率”的理论,也可适用于其它问题,尤其是在当今社会,体现的更明显:非专业人士无需了解专业知识和技巧,就可以享受专业知识带来的好处(这就是哈耶克说的“知识的分工”)。用户觉得软件“更快”了,而无需知道其中进行了多少优化;驾驶员觉得汽车“更好开”了,而无需知道汽车的各个部件采用了多少新技术……反过来看,仅仅为了提供这种抽象直观的“更快”、“更好开”的感觉,软件制造商和汽车制造商,必须在专业上不断精进,绞尽脑汁,这算是一种“不公平”吗?好像不算。
  2. 沟通中效率损失必然会造成这种“困境”。沟通的过程,粗略描述起来就是:从意念形成文字(话语),传播出去,再由文字(话语)还原为意念。其中每一个环节,都有信息的遗漏和变形。人人都喜欢的“沟通顺畅”,无非是尽力减少这些遗漏和变形——注意,是尽力减少,而不是杜绝。普通文字如此,译文也是如此,要求读者细密上溯整个沟通过程,“体谅”译者的良苦用心,未免缘木求鱼。

综合起来看,每一种专业的信息(积累),在传播中都面临不断被稀释的问题。我们能做的,一方面是改善沟通,尽力减少“稀释”的程度;一方面是努力提高自己的专业积累,保证被“稀释”以后仍然有相当的浓度(实际上我以为,这一点更重要)。仅仅抱怨自己被稀释的“不公平”,实在不是什么好办法——须知道,我们所见、所羡的那些“深刻”,其实也是经过稀释之后的深刻。

一方说已经确定了双方的称呼:会长你好,马前主席你好;一方说,“我是以总统身份来会见他”,“最希望對岸稱呼我們總統、院長”;没几天了,大家等着看到时候怎么办吧。

相逢一笑泯恩仇

Next Page »