Monthly Archives: 一月 2008

你搜我搜

Song同学利用空余时间和复旦某位神秘牛人搞了个关于汽车的垂直搜索引擎——你搜我搜: 你搜我搜是一款以汽车相关信息为检索对象的专业搜索引擎,是涵盖新车报价、二手车信息、汽车评论、汽车新闻、汽车图片等汽车相关信息的搜索平台。你搜我搜融合了信息检索、自然语言处理等多项关键技术,为用户提供汽车领域的一站式搜索门户。 2007年5月公司在上海创立,并于当月获得第一笔风险投资,开始快速发展。公司专注于垂直搜索平台的开发,拥有的深厚自然语言处理和搜索引擎技术背景,你搜我搜具有智能识别、即时索引、海量信息处理等技术特色。我们以用户需求为中心,努力提供准确、迅速的信息。 其中最具有技术含量的关于汽车的“评论”搜索,可以对被搜索的汽车,分别显示正面和负面的评论,便于用户进行比较。 希望Song同学能继续把这个网站做好!

PHP的二进制位移操作

PHP主要是设计于文本操作的,其实PHP不适合做数学运算,效率也不高,不过因为这次的项目中有个东西必须使用到二进制位移操作,在PHP上面遇到了一些麻烦。 因为PHP只有32位有符号整数,没有64位长整型,也没有无符号整数。其整型的范围是-231-1~231,超出这个范围的,将被解释为浮点数。因此,0xFFFFFFFF,直接打印,显示的是4294967295,及232: >> 0xFFFFFFFFF 4294967295 >> gettype(0xFFFFFFFF) ‘double’ 而在32位有符号整型中,0xFFFFFFFF应表示-1: >> (int)0xFFFFFFFFF -1 而PHP不支持浮点数的二进制位移操作,如果要进行,会先转换为整型,最后的结果,也将按照整型来返回: >> 1 << 31 -2147483648 >> 1 << 30 1073741824 >> 1 << 32 1 >> 0xFFFFFFFF >> 1 -1 同时PHP的向右位移操作,高位会填充符号位,而且PHP没有提供类似Java的>>>来强制填充0: >> 1 << 32 1 >> 0xFFFFFFFF >> 1 -1 >> 0xFFFFFFFF >> 2 -1 >> 0xFFFFFFFF >> 3 -1 >> [...]

硬盘损坏+高可用性有感

最近一直觉得笔记本的硬盘有些问题,因为有时候系统会莫名奇妙地停止响应,硬盘灯则长亮,只听见硬盘在有规律的间隔发出声音。果然,先是本周周一的时候,我的个人用户配置文件损坏,导致无法登录Windows,接下来就是前天windows\system32\config\system系统配置文件损坏,导致无法启动系统。 估计是硬盘出现了坏道。为什么会这样,我本身在使用上也有很大责任,估计是这些原因: 一直只有一个分区:因为笔记本硬盘本来就小,如果分成若干区,虽然划分地清楚,但难免有某个区总是闲置,另一个区却被塞满了,只有用一个分区才能最大化利用硬盘容量 硬盘一直很满:硬盘上总是塞了很多乱七八糟的文档,以及一些电影、游戏等。比如WoW就占了7G 从不检查清理:因为NTFS号称可以不用整理磁盘、又是日志文件系统,又号称可以自动修复,所以我也从来没有整理过,也没有检查过磁盘,甚至包括各种临时文档,也很少去清理 从不备份:因为备份很消耗时间和空间,虽然IBM提供了Thinkadvantage全套的工具,但是我很少用,因为本身硬盘空间就不足。另外也就是根本不知道Windows里面哪些东西是关键,比如system32\config\system文件,如果这次没有出现这个事情,我估计这辈子不会了解Windows还用了这个文件存放系统配置 长时间连续运行:我经常拿笔记本当服务器,会连续几天不关,用来下东西或者是挂机 幸好只是出现了坏道,我找了个移动硬盘盒就把东西备份出来了。那么接下来是恢复单个文件还是全部恢复整个硬盘的,但这都不是我想搞的,因为仅仅恢复单个文件,我不知道其他文件还有没有问题,还有没有可能出现其他坏道,而且很可能硬盘需要低级格式化。恢复整个硬盘也是很麻烦的,因为我需要重装很多东西。 最后我的选择是换一块硬盘,装个Ubuntu,虽然还是放不下预装Windows XP,因为那毕竟是唯一一份正版,而且Linux毕竟在桌面系统的硬件支持上还是较为落后的,比如不支持指纹识别等等。不过所幸现在Ubuntu做得已经够好了,而且我更相信Linux的文件系统。 高可用性 公司正好也要搞高可用性,因为公司网站需要对客户提供24小时不间断的服务。高可用性就是让系统在出现问题(宕机、维护等)的时候不至于全部瘫痪,用户依然可以使用系统。高可用性的特点是事先进行可以控制的投入,来防止出现事后不可控制的损失。高可用性的核心是冗余,也就是什么东西都有备份,多出来一个以备不测。这就意味着必须要付出很多成本来维持高可用性。 比如我这次的事故,如果我没有能成功备份出硬盘上的数据,那么我记录的一些关键信息、银行证书、过去搜集的很多资料和在做的一些东西都付诸东流,对我个人的损失不可估计。 但我可以有很多方案达到备份的目的: Windows自带的系统还原,从来没用这个功能 IBM ThinkVantage 的快速备份和恢复(RRU)软件,功能十分强大,可以放在隐藏分区中,也可以放在单独的移动硬盘中,问题是备份消耗很多空间以及时间,这都是针对个人用户而言。可以完整备份、增量备份,但消耗巨大空间,以前我有一台IBM R50,硬盘只有30G,隐藏空间5G,如果备份一下就只有20G了,出厂设置的Windows基本上需要10G,所以对于硬盘的消耗是惊人的。如果要选择性备份,则无法了解Windows需要备份什么——看来移动硬盘非买不可了 使用Norton的Ghost,以及世面上流行的一键恢复加上单独备份数据——还是要移动硬盘吧? 另外买台机器……,可以做到使用上连续,如果数据不重要的——你得有钱买另外一台机器 基本上可以发现,要想冗余,想备份,必须有实打实的投入,物质上的人力上的。如果仅仅是物质上的投入,还能令人接受,但目前功能还都十分繁琐,备份过程相当长,而且备份介质的安全性也不是十分可靠。服务器的高可用性是需要大量人力物力投入的、做集群、做双机热备份等等。 无论是个人电脑,还是公司服务器,越是偷懒,就越可能出现大问题,这印证了墨菲定律: “如果一件事情有可能向坏的方向发展,就一定会向最坏的方向发展”。 只有把工作做在前面,才能防止事后的损失,这其实是一个管理层面上的问题了。 总结 其实我总期待更好的备份方案,我希望等将来网络速度更快、存储器更廉价的时候,可以适当推出网络备份,那时候应该我们基本上每人有一台电脑,甚至多数白领会有多台机器(自己的、公司的)。这种网络备份其实就是类似于如今Google Browser Sync的功能,结合另一种版本控制软件类似于Subversion,无须消耗本地的存储器容量,本地崩溃了还有主机上的备份,那么我们重装系统或者迁移到另一台机器,或者几台机器之间同步,就会变得非常方便。

Redmine

Redmine是基于Ruby/Rails的一个项目管理软件。比较类似的则是基于Python的Trac,相比之下,Redmine有很多优势: 简单的安装、配置和部署Redmine利用rake、rails的db migration安装很方便,Trac则要用到命令行的trac-admin进行配置,以及每个项目有单独的ini配置文件 方便的用户和权限管理Redmine支持多LDAP认证、还支持用户自己注册,然后通过邮件激活。Trac依然需要使用trac-admin来配置,而且默认的用户登录方式是HTTP验证,基于cookie的还需通过插件实现 基于Web的多项目管理Trac创建和配置新项目需要使用trac-admin AjaxRedmine通过Ajax在某些方面提供了更好的用户体验,如代码仓库的浏览 多语言包括简体中文 多种SCM包括SVN、CVS、Darcs、Mercurial、Bazaar,是通过调用它们的可执行文件来实现的。 trac的很多功能都需要通过trac-admin在命令行方式下进行配置,不易上手,这方面Redmine则十分方便。 其实功能方面,Redmine更多地是模仿Sourceforge的功能,比如新闻、文档、下载等,目的是建立这种适合团队协作的平台。我估计以后Rubyforge可能会迁移到Redmine上去。

回想高中时的一次被采访经历

我家在常州,念高中的时候,有一次常州电视台为了做一档关于中学生上网情况的节目,采访了几个不同学校的学生,采访到我们学校的时候,老师就找到了我。 除了采访同学外,还要采访同学家长,于是我去把我父亲找来了。记者问了一些问题,其他的问题都不记得了,我只记得问过一个关于网上色情信息的问题,我父亲对此表态,说相信我能自己抵制和控制,保持好的心态,所以对这个问题不是非常担心。 过了几天,听说上电视了,一家人就一起看这个节目。最后当主持人说到家长是如何看待网络上的色情信息的时候,几个家长的画面迅速的切换过去,最后一个画面是我父亲,说了四个字“非常担心”。

升级到RubyGems 1.0

虽然前一段时间Ruby社区推出了很多重大的更新,如RubyGems发布了1.0,Rails发布了2.0,Ruby发布了1.9测试版。但是却潜藏了很多危险。比如在Windows平台下,升级了RubyGems之后,会导致我现有的Mongrel无法启动,原因在于RubyGems1.0修改了系统的识别,将mswin32改成了x86-mswin32,从而导致gem_plugin无法正确定位相应gem。 修复的方法也很简单,只需要先删除Mongrel再重新安装: ::先升级RubyGems到1.0 gem update –system ::卸载再重装Mongrel gem uninstall mongrel gem i mongrel 另外还在一些人的BLOG中发现Rails2.0刚发布时,是要求使用RubyGems0.9.5,也会出现一些问题。幸而我暂时没有迁移到Rails2.0上,也还没有遇到问题。 从这一个事件上也可以看出Ruby社区相对于Python/Perl的社区来说,还不是十分的成熟。

函数式JavaScript编程指南

JavaScript Programming 原文地址:http://www.pfeiffer-mediation.de/remast/javascript.php 翻译:ShiningRay 函数式JavaScript编程指南 简介 你是否知道JavaScript其实也是一个函数式编程语言呢?本指南将教你如何利用JavaScript的函数式特性。 要求:你应当已经对JavaScript和DOM有了一个基本的了解。 写这篇指南的目的是因为关于JavaScript编程的资料太多了但是极少的资料提到了JavaScript的函数式特性。在本指南中,我只会讲解这些基本知识而不会深入其它的函数式语言或这是Lambda算子。 你可以点击所有的例子然后你所看到的代码就会被执行,这样就可以令指南变得具有交互性。你也可以使用这个沙箱来尝试。 第一课 —— 匿名函数 我们将首先介绍匿名函数。一个匿名函数就是一个没有名字的函数。你可以认为他们是一次性函数。当你只需要用一次某个函数式,他们就特别有用。通过使用匿名函数,没有必要把函数一直放在内存中,所以使用匿名函数更加有效率。 例Example: 下面两个函数处理同样的事情,而average在给z赋值结束之后一直保留——但匿名函数则不会。 function average(x,y) { return (x+y)/2; } var z = average(1,3); alert(z); var z = function(x,y) { return (x+y)/2; } (1,3); alert(z); 这很自然得引出了我们下面的一节课函数作为值。 第二课 – 函数作为值 事实上,我们一般在JavaScript中声明函数的方式可以看作是一个简化了的语法(也就是语法糖,syntactic sugar)。 例: 下面两个表达式其实完全一样。所以左边的表达式仅仅是右边的简写。 function average(x,y) { return (x+y)/2; } alert( average(1,3) ); var average [...]

TCMalloc:线程缓存的Malloc

作者:Sanjay Ghemawat, Paul Menage 原文 翻译:ShiningRay 动机 TCMalloc要比glibc 2.3的malloc(可以从一个叫作ptmalloc2的独立库获得)和其他我测试过的malloc都快。ptmalloc在一台2.8GHz的P4机器上(对于小对象)执行一次malloc及free大约需要300纳秒。而TCMalloc的版本同样的操作大约只需要50纳秒。malloc版本的速度是至关重要的,因为如果malloc不够快,应用程序的作者就很有可能在malloc之上写一个自己的自由列表。这就可能导致额外的代码复杂度,以及更多的内存占用――除非作者本身非常仔细地划分自由列表的大小并经常从自由列表中清除空闲的对象。 TCMalloc也减少了多线程程序中的锁争用情况。对于小对象,几乎已经达到了零争用。对于大对象,TCMalloc尝试使用粒度较好和有效的自旋锁。ptmalloc同样是通过使用每线程各自的场地来减少锁争用,但是ptmalloc2使用每线程场地有一个很大的问题。在ptmalloc2中,内存可能会从一个场地移动到另一个。这有可能导致大量空间被浪费。例如,在一个Google的应用中,第一阶段可能会为其URL标准化的数据结构分配大约300MB内存。当第一阶段结束后,第二阶段将从同样的地址空间开始。如果第二个阶段被安排到了一个与第一阶段什?用的场地不同的场地,这个阶段不会复用任何第一阶段留下的的内存,并会给地址空间添加另外一个300MB。类似的内存爆炸问题也可以在其他的应用中看到。 TCMalloc的另一个好处是小对象的空间最优表现形式。例如,分配N个8字节对象可能要使用大约8N * 1.01字节的空间。即,多用百分之一的空间。而ptmalloc2中每个对象都使用了一个四字节的头,(我认为)并将最终的尺寸规整为8字节的倍数,最后使用了16N字节。 使用 要使用TCMalloc,只要将tcmalloc通过“-ltcmalloc”链接器标志接入你的应用即可。 你也可以通过使用LD_PRELOAD在不是你自己编译的应用中使用tcmalloc: $ LD_PRELOAD=”/usr/lib/libtcmalloc.so” LD_PRELOAD比较讨巧,我们也不十分推荐这种用法。 TCMalloc还包含了一个堆检查器以及一个堆测量器。 如果你更想链接不包含堆测量器和检查器的TCMalloc版本(比如可能为了减少静态二进制文件的大小),你可以接入libtcmalloc_minimal。 概览 TCMalloc给每个线程分配了一个线程局部缓存。小分配可以直接由线程局部缓存来满足。需要的话,会将对象从中央数据结构移动到线程局部缓存中,同时定期的垃圾收集将用于把内存从线程局部缓存迁移回中央数据结构中。 TCMalloc将尺寸小于<= 32K的对象(“小”对象)和大对象区分开来。大对象直接使用页级分配器(一个页是一个4K的对齐内存区域)从中央堆直接分配。即,一个大对象总是页对齐的并占据了整数个数的页。 连续的一些页面可以被分割为一系列小对象,而他们的大小都相同。例如,一个连续的页面(4K)可以被划分为32个128字节的对象。 小对象的分配 每个小对象的大小都会被映射到170个可分配的尺寸类别中的一个。例如,在分配961到1024字节时,都会归整为1024字节。尺寸类别这样隔开:较小的尺寸相差8字节,较大的尺寸相差16字节,再大一点的尺寸差32字节,如此类推。最大的间隔(对于尺寸 >= ~2K的)是256字节。 一个线程缓存对每个尺寸类都包含了一个自由对象的单向链表。 当分配一个小对象时: 我们将其大小映射到对应的尺寸类中。 查找当前线程的线程缓存中相应的自由列表。 如果自由列表不空,那么从移除列表的第一个对象并返回它。当按照这个快速通道时,TCMalloc不会获取任何锁。这就可以极大提高分配的速度,因为锁/解锁操作在一个2.8GHz Xeon上大约需要100纳秒的时间。 如果自由列表为空: 从该尺寸类别的中央自由列表(中央自由列表是被所有线程共享的)取得一连串对象。 将他们放入线程局部的自由列表。 将新获取的对象中的一个返回给应用程序。 如果中央自由列表也为空:(1) 我们从中央页分配器分配了一连串页面。(2) 将他们分割成该尺寸类的一系列对象。(4) 像前面一样,将部分对象移入线程局部的自由列表中。 大对象的分配 一个大对象的尺寸(> 32K)会被除以一个页面尺寸(4K)并取整(大于结果的最小整数),同时是由中央页面堆来处理的。中央页面堆又是一个自由列表的阵列。对于i < 256而言,第k个条目是一个由k个页面组成的自由列表。第256个条目则是一个包含了长度>= 256个页面的自由列表: k个页面的一次分配通过在第k个自由列表中查找来完成。如果该自由列表为空,那么我们则在下一个自由列表中查找,如此继续。最终,如果必要的话,我们将在最后一个自由列表中查找。如果这个动作也失败了,我们将向系统获取内存(使用sbrk、mmap或者通过在/dev/mem中进行映射)。 如果k个页面的一次分配行为由连续的长度> k的页面满足了,剩下的连续页面将被重新插回到页面堆的对应的自由列表中。 跨度(Span) TCMalloc管理的堆由一系列页面组成。连续的页面由一个“跨度”(Span)对象来表示。一个跨度可以是已被分配或者是自由的。如果是自由的,跨度则会是一个页面堆链表中的一个条目。如果已被分配,它会是一个已经被传递给应用程序的大对象,或者是一个已经被分割成一系列小对象的一个页面。如果是被分割成小对象的,对象的尺寸类别会被记录在跨度中。 [...]