2011年8月31日星期三

我有几台电脑

    废话贴,数一下。
    家里能正常工作的电脑四台,一台台式机,11年7月买的,一台笔记本,07年买的,一台上网本,09年买的,一台低功耗服务器,11年初买的。
    两台租用设备,一个是空间,一个是vps。
    公司一台电脑,10年换的。
    两台嵌入设备,wince和android各一,还打算明年入个平板。
    虚拟设备七到八个,常用的两个,一个xp一个debian。
    差不多就这些。

2011年8月29日星期一

汽车、苹果、人类的历史

    Jobs辞职了。
    好吧,这篇文章早在年初就想写了,不过经过漫长时间的沉淀,最终还是被忘记了。最后帮主的退出帮我想起了这个事情。
    本文论述的其实很简单,是一个人类使用东西上再简单不过的常识。不过很可惜,几乎所有的程序员都会忘记这个事实——直到有一个正视事实的家伙赚了大钱——然后现在辞职了。
    人在使用东西的时候,都会从简单的角度去理解,而不是从复杂的角度。而人在研究东西的时候,都会从复杂的角度去研究,而不是简单的角度。我们可以回想机械大爆炸的年代,今天能看到很多上世纪的笔记,里面记载了奇奇怪怪的机器——传说达芬奇还研究过直升机。不过今天能留下来的,都是最简单和基本的了。这并不是说这些机器不好,而是创意从研究者到使用者之间巨大的专业鸿沟所致。
    举例来说,我们日常最常见的机械之一——汽车。汽车上有数千计的组件,随着我们对不同组件的定制和组合,我们能够组装出不同的车。越野的,城市行驶,大脚怪,等等。从设计角度说,车的操控界面其实过度简化了。理论上说,即使四个轮子的车,也可以考虑对每个轮子施加不同方向和大小的力矩。加上轮子的内弯和外弯角度参数。一个轮子上就有两个有向标量在控制,四个轮子组合起来,足足可以形成一个八维量——只比张量差一个维。然而我们在开车的时候,只会控制四件事情——方向盘角度,档位,油门,刹车。近些年的无级变速车还逐步合并了油门和档位,使得控制量还少了一个,只有一个有向标量,一个标量,一个布尔。
    这些控制系统能够产生的控制精细程度,是远远比不上八维的控制的。例如,如果我们能精细控制每个轮胎,车可以做到原地旋转——两个前轮同向向前,两个后轮反向向后。或者可以保持方向的状态下斜侧移位,乃至于如果前轮内外弯角度比较大,还可以直接侧方移位——不用前后倒车进车。然而,一方面是复杂的控制系统会造成非常高的成本。另一方面,人类没有昆虫那样的复眼去同时盯着路面、后镜、还有诸多仪表,更没有那么多手去操纵那么多控制件——比这个更直观的,是人类根本不会想要把自己的神经训练成这种怪物的信号处理系统。
    人类能够大规模使用的,都是自己简单能够理解的东西——这个简单的标准随着这个东西能做到的事情而不同。如果只是要帮自己晃动孩子的摇篮,那么通常而言,只要控制开关就好。如果晃动摇篮的机械需要你指定晃动输出是基于正弦波还是基于锯齿波,你一定会觉得不可思议,然后摇头走开。而如果这个"东西",能够帮助诊断很多重症病人,并且让你获得一份高的离谱的合约。我想你不会介意花三到五年时间学习整套系统的使用方法。当然,即使在这种情况下,简化的系统仍然是一件让人开心的事情。
    计算机发展到后期,已经远远超出了最聪明的人所能理解的范畴。app store上有十万多个程序,即使每个花5分钟浏览一下也需要6天。如果要一一玩过,基本会花去一个人的一生。windows下的各种程序更是数都不要数。在这种情况下,如果我们还是持续的曝露各种底层细节给用户——你的数据要存放到哪个文件夹?你的文件类型是什么?无疑,用户不会跑开,但是肯定会很恼怒——为什么我需要知道文件路径?我写下一个名字,下次你帮我找出来,不就好了?
    类似的问题正是ipod, mac, ipad, 加上现在的android试图解决的。app的安装删除并不需要用户理解细节,android上调节参数比较多,最多也不过是指名安装到sd卡上还是内存中。数据保存也基本无须关心——其实这点上做的还并不足够。整个系统,就像一个封装在琥珀里面的,神奇的魔盒。你说出你的愿望,他就帮你实现,一切都是那么美好——除了这个魔盒可以买到,而且必须经常充电。
    将来?将来的系统可能会重现工业时代的老路,有经验的程序员会逐渐变成工人,而不是城市里孤独的游侠。华而不实的设计被淘汰,有效的设计成为生活中的常识。电脑将变得越来越贴近生活——前所未有的近。而我们的历史,也会进入新的一页。

2011年8月26日星期五

debian打包的一些细节补充

    如果前面有人接手了,你最好和前任联系一下,看看是否可以获得他的帮助,或者跟着他的思路继续做下去。
    debian有一个比较变态的规定,你的打包内容,必须遵循FHS。有些程序写的数据放到了程序路径下面,你需要进行人工分离(这个花了我整整两天)。
    求RFS比ITP难多了...



....




.......



求RFS。

2011年8月24日星期三

其实英文基本没必要学的

    找个maillist实际跟老外一起交流干活。历经数次抓耳挠腮依旧词不达意,然后看到老外的标准回复后,有用的东西基本都留在脑子里了。
    当然,坏处就是,很多非英系老外的错误(包括国人的错误)也会复制过来。

2011年8月23日星期二

第一个debian官方包请求出来

    贝壳的第一个为debian官方贡献的包出炉了,地址在这里。之前也发过一个ITP,结果发现莫名其妙有人在做了。不知道为什么没有在wnpp中发现,结果弄的好不尴尬。
    大概说一下,为debian官方贡献打包,你需要了解这个包的基本情况。例如用哪种语言写的,有什么依赖关系,是什么授权,等等。尤其是授权,debian有所谓的dsfg方针(不知道的看这里这里这里)。如果你打出来的包包含dsfg不许可的内容,你的包会被紧急移除,直到修复这个问题。尤其值得注意的是,debian要求文件级的授权,就是说,即使有一个文件不符合授权要求,整个包也会不通过,哪怕包本身声明为开源授权。之前ibus还是fctix,因为用了拼音加加的词库,就享受了一把这个待遇。另外,如果可以的话,最好征求一下上游维护者的意见(一般就是作者)。因为debian的bug系统中的问题是你需要解决的,而这些问题通常没有上游维护者是很难搞定的。当然,如果你觉得自己搞的定,或者可以出了问题再联系,那也可以。
    当你搞明白这些问题后,通常需要先发一个ITP(Intent To Adoption)出来,表示你要打包,别人不要抢。通常是用reportbug来进行提交,汇报wnpp(Work-Needing and Prospective Packages)这个包的bug。然后程序会问你确定?确定的话,会要求你选择是哪种报告,其中就有ITP。当你的ITP通过后,你会收到一个bugnumber,这个bugnumber会在changelog中用到。
    另外说明一下bts(bug tracking system)的基本用法。你需要给control@bugs.debian.org发送一封邮件,内容是bts的控制指令,每行一条。碰到无法识别的指令时,bts停止解析。通常习惯在最后写一个thanks来停止解析,也表示礼貌。指令系统可以参考[3]。
    然后开始干活。干活的方法参考Debian 新维护人员手册。其中注意在changelog中填入你刚刚申请到的ITP,这样当包通过后,会自动关闭你的ITP。提交的包需要是lintian clean的,即自动检查程序没有发现错误。通常你可以在本地系统安装lintian进行检查。
    当你完成打包工作(没法详述,太复杂了,自己看文档吧),你需要上传到mentors系统,然后让DD审查你的包。你首先要在http://mentors.debian.net拥有一个账户,这个账户的email将来会用于给你发送bug通知之类的东西。当你完成账户创建,你会在页面上看到要求上传一个gpgkey。gpg创建key都会吧?记得做4096位密钥。另外填写姓名的时候,用最好真实姓名作为名称,网名进nickname,尤其是大部分中国人都有一个拼音姓名和一个英文姓名的时候。。。
    然后,你的主页上有一个说明,会让你复制一些数据到你的~/.dput.cf中。dput是用来上传源码包的工具。如果你按照说明去复制,那么你就可以用dput debexpo ..changes来上传你的包。其中有几点需要注意的,一个是debexpo不能丢,否则会默认传到ftp.debian.org上去,然后失败。另外changes和dsc必须经过你上传那个公钥对应的私钥的签署,否则签名验证失败,你的包上传行为就会失败。如果你的系统中有多个private key,那么dpkg-buildpackage会不知道如何打包。用-k参数加上你的私钥id,就可以指定使用哪个私钥进行签署。
    当你的包完成上传后,你可以在my packages下面看到。注意服务器检查结果,本地通过lintian的包在远程还是可能爆出错误,所以再检查一下。
    如果一切都没有问题。你可以将package中的Needs a sponsor改为Yes,然后等DD注意到你的包。当然,还可以向debian-mentors@lists.debian.org发送一封RFS(Request For Sponsor)的邮件,提醒DD的关注。具体的内容模板在成功上传的邮件中会提示你,一般是http://mentors.debian.net/package/rfs/[package name]这种格式。打开url,里面就是你的RFS邮件规范的目标地址,标题,还有内容。
    OK,最后总结一下,整个过程中我们用到了三个系统。第一个是debian bts,通过提起bug来表示你准备打包。第二个是mentors.debian.net,通过注册来上传包。第三个是debian-mentors@lists.debian.org,通过maillist来提醒DD检查你的包。过程有一点小繁琐,不过熟悉之后还不算繁琐。如果真的觉得繁琐,debian在包检测和打包过程中的一堆事情更是会烦死人的。

Reference:
[3]. Introduction to the bug control and manipulation mailserver http://www.debian.org/Bugs/server-control

2011年8月18日星期四

一次系统和数据迁移

    在文件系统选型后,贝壳骤然发现用ext3保存媒体文件是一件很傻的事情。耗费空间多,性能差,安全性低。根据文章结论,其实最好的文件系统是xfs。同时,贝壳的mini-itx空间基本满了(/home分区75-80%)。所以,贝壳准备买一块新的硬盘,然后将数据迁移过去。
    硬件选择上,贝壳询问了熟悉的硬件商。他说日立没货,WD的盘问题比较多,推荐希捷的。而且只有绿盘,具体型号是ST2000DL003-9VT166,SataIII,常规转速5900。ST的2T盘入手后,贝壳做了一下基础测试,hdparm分数是,原本的WD硬盘90M/s,新的ST硬盘70M/s,公司的硬盘99M/s。看来硬盘性能还是WD的比较好一点,当然,也可能是因为新硬盘本身就是低档硬盘。
    贝壳的第一选择,是按照原本的U盘安装设置,安装debian系统。不过前后两次都可耻的失败了,主要原因是mini-itx对U盘启动的支持并不是很好。被迫,用新买的大型电脑安装,又失败。原因是6.0的安装镜像对boot.img.gz方式的U盘启动支持不良。算了,先装5.0升级。没想到,这个原因直接导致了贝壳两次系统安装完毕后无法引导升级。为什么?因为硬盘的尺寸刚刚好比2T大了点。gurb升级到grub2的时候,为了让你支持全部空间,很好心的帮你升级到了gpt。然而gpt需要一个分区来保存一些信息,新多出来的空间又刚好不足以保存这个数据。因此,grub-pc就升级失败,而且救都没法救——因为没空间了。
    两次折腾下来,贝壳基本搞明白了为什么。然而要解决这个问题,就要手工分区,计算大小,产生lvm,设定,然后debootstrap,再设定。或者就直接使用debian 6.0的安装镜像。这个时候,悲崔的事情来了——U盘安装那篇文章的上一节,就说明了如何直接使用usb启动iso,直接cat iso > /dev/sdX就可以了。早知道这么简单,何必折腾那么一大套呢,哎。
    debian 6.0的安装系统比5.0的好了很多,磁盘分区支持gpt,直接就生成了bios_grub分区。lvm2的支持增加了vg级别的控制,而不仅仅只能控制lv的生成和删除。同时增加了软raid的支持。这就很好的解决了贝壳当前的问题。
    贝壳的分区方案是,gpt分区表,一个bios_grub分区,一个ext2的boot分区,一个lvm分区。lvm上面分8G的root,ext4格式。4G的swap,可以适应当前内存和升级到4G的内存(linux swap推荐是,4G以下两倍于内存,4G以上和内存一致)。1.7T的home,xfs格式。剩余268G。为什么要剩余?因为xfs只能扩展不能缩小,如果我需要扩展root和swap,或者需要产生新的lv来做虚拟机,不留下一定空间会出问题的。如果home不足,我再扩展150G基本可以解决问题。
    分区和安装都很顺利,然而approx对新的系统基本没有缓冲作用。我略微想了一下,大概明白了为什么——原有系统是用i386架构和amd64内核,而新系统则是架构内核都是amd64。或者通俗来说,原系统是64位内核下的32位混合系统,而新系统是彻底的64位系统。32位的包对64位的系统一点用都没有,所以approx原有的包都白缓存了。
    好吧,瑕不掩瑜,这次升级基本还是成功的。安装对应软件包,复制数据(推荐首次cp -a,速度快,后面用rsync保证同步),修改属主(否则很多程序无法启动)。尤其需要注意,mldonkey在downloads.ini中,不但保存了以哪个用户启动,同时也保存了用户id。新系统中用户名和id对应关系会发生变化,因此要修改正确。基本——事情就完了。
    一个小细节是,uwsgi由于amd64升级,所以无法使用。贝壳解决了一下问题,重新编译这个包。另外,debian官方的包出来了,目前处于sid状态,大家可以等着什么时候进入testing状态了。

2011年8月17日星期三

除虫故事(三)

    第三个bug是刚出的,贝壳刚刚从现场回来,提交了bug系统关闭申请。
    问题是这样的,我们有一套系统,为客户提供从web访问某台windows的能力,作为管理系统使用。这个系统的后台使用了三四个不同的程序,通过管道通讯。目标设备上有一个组件,要适应2000/2003/2008的32位和64位环境,非常复杂。最近,贝壳将这套系统的目标设备的组件进行了重编译,提供了64位版本。然后测试发现,32位系统不工作了,64位系统正常。
    第一反应是什么?一定是组件有问题?贝壳在服务器上,直接使用连接程序去连接,结果是成功的。这个表明组件应当是正常的,或者部分正常。问题就在web页面到连接程序的过程中某处。
    负责web界面到连接程序的工程师同事接手了下一步排查,他也是一头雾水。系统看来一切正常,连接程序明明可以工作,为什么从web页面调用就会失败呢?而且只有32位会失败。web页面对CPU字长(而且是目标设备的CPU字长)并不敏感阿,这个听起来不合理。
    测试过程中,测试部门的同事偶然的看了一下日志系统,发现了问题。我们的连接程序会写出日志,默认情况下这个日志的属主应当是web.web的,而当时的日志是root.root的,而且权限是644。所以当连接程序被直接调用,当前id是root,就可以连接成功。而连接程序被web调用,当前id是apache,日志写出就会失败,程序就挂了,目标设备会失去反应。
    出现这个错误的原因也很直观,在某次调试后,有人删除了原始的日志,并且直接执行了连接程序。但奇怪的是,同样是连接程序挂掉,为什么64位就可以继续执行呢?我们讨论不出为什么,只有基本猜测,64位设备是2008,rdp服务版本比较高,所以相对健壮。
    所以,实际的错误是两个。一个是日志权限导致的连接程序不工作。另一个是64位下不正常的连接程序依旧可以工作。
    好吧,总结一下这个奇怪的问题中的教训。
1.隔离最小差异。要验证是否是组件升级导致问题,一定要进行旧组件测试,然后再测试新组件。万不可假定旧组件可以正常运行,直接测试新组件,从而将非组件问题带入排查。
2.单元测试隔离。每个部分都要做单元测试,如果测试通过却无法连接,那就是环境问题。再查不出,再检查通讯/调用记录。
3.通讯系统关联错误。当两个程序通过通讯工作,其中一个程序死亡时。另一个程序应当能够检测并且报错退出,而不是出现各种异常反应。
4.日志底线设计。程序一定要写日志,如果日志写不出,就写系统日志,再写不出,设法报全局错误。

2011年8月15日星期一

ACC lead to no core temp reading?

    I bought a Phenom II X4 955 CPU month ago, recently I find that HWMonitor can't read core temp, just motherboard temp. I googled it and find this article. This article said that ACC is a tech will make AMD X3 work like X4 by unlock cores in BIOS. But CPU core temp sensors will not work, even use a real four cores CPU.
    贝壳一个月前买了一块羿龙II X4 955(黑盒),但是最近发现HWMonitor读不出核心温度,只有主板温度。放狗搜了一下,找到这篇文章。根据这篇文章说,ACC是一种能够让AMD三核CPU像四核一样工作的技术,只要在BIOS中打开unlock cores选项就好。但是这个会使得CPU的核心温度传感器不工作,即使你真的有四个核,而不是仿冒四核。

2011年8月14日星期日

linux下的文件系统选型

    贝壳原来一直认为文件系统可以随便选,结果最近吃了两次苦头。一个是btrfs对虚拟机支持不良,另一个是特定情况下xfs性能比ext3高20倍。痛定思痛,打算列一下文件系统选型的方法和依据,欢迎拍砖。
    下面我列一下纳入参考的文件系统,当然,ntfs就不要出来搞基了,玩嵌入式/光盘live之类的朋友也不要来凑热闹了阿。btrfs(简介), ext3ext4(简介), jfs(简介), reiserfsxfs,基本涵盖常用文件系统。最下面加入ntfs和zfs对比,实际上不参与选型。以下进制换算为1024,大小依次为KB,MB,GB,TB,PB,EB,ZB。
文件系统 btrfs ext3 ext4 jfs reiserfs reiser4 xfs ntfs zfs
最大卷容量 16 EB 32 TB 1 EB (16TB) 32 PB 16 TB ?? 16 EB 256 TB 16 EB
最大文件容量 16 EB 2 TB 16 TB 4 PB 8TB 8TB 8 EB 16 TB 16 EB
目录结构 B tree list/tree list/Htree B tree B+ tree dancing B* tree B+ tree B+ tree hash table
文件分配 extents bitmap/table bitmap/extents bitmap/extents bitmap ?? extents bitmap ??
ACLS Yes Yes Yes Yes No No Yes ACLS only Yes
checksum Yes No journal No No No No No Yes
透明压缩 Yes No No No No Plugin No Yes Yes
透明加密 No No No No No Plugin No Yes Yes
online defrag Yes No Yes Yes No Yes Yes Yes Yes
shrink Yes Yes Yes No Offline resize Offline No Yes No
特性 SSD





Stream
    首先,文件系统选择上要考虑现实性和支持情况。如果你希望得到广泛的支持,在移动硬盘上被多个系统挂载,应用于老内核,或者不使用/boot分区,那么可选项目基本只有ext3。作为老牌文件系统,ext3的支持是最广泛的,工具组也相对全面。无论其他文件系统拥有多大的优势,在现实情况考虑下往往会败给ext3,基本就是因为广泛的使用和支持。另外,btrfs我所知还没有fsck工具,出了问题全看RP,而且在上面使用虚拟机速度特别慢。reiser4作者目前在监狱中,出了问题能否获得支持全靠RP。jfs用的人相对xfs少一些,也比较不活跃。这些虽然并不出现在数据上,但是最好特别注意。
    其次,文件系统的选择要考虑必要特性。例如如果你希望使用SSD支持,你可选的项目就只有btrfs。如果需要透明加密,那只有reiser4。当然,在决定必要特性前,请仔细考虑,自己是否真的必须使用这些特性。为了一个不必须的特性选用一个不合适的文件系统会付出极大代价。linux下文件系统还是比较单调和弱小了点,基本不支持透明压缩,全部不支持透明加密,ext两兄弟更是没有完全实现Btree目录结构(ext4其实有用Htree,一种改过的Btree,不过为了兼容ext3,好像升级来的目录不使用)。不过好佳在,大部分都支持online defrag/growing,否则不如一头撞死算了。ext3/4, btrfs是支持shrink的,但是jfs, xfs只支持growing,reiser4必须offline shrink。xfs的growing在1T(一说2T)以上有点问题,非64位内核在1T以上可能无法创建inode。本来是会在1T内创建inode,使用高位空间。但是growing的时候可能地位空间已经满了,会报没有空间的错误。解决方案是将老文件移出再移回,或者看看用inode64参数是否解决。如果你确定需要shrink,最佳选项是使用ext4。另外补充一点,ntfs的online shrink也不是完美无缺,他只能shrink到未被使用的地方。也就是说,如果有不可移动文件,有可能就无法shrink到以下内容。
   第三个要确定的问题,是你的系统服务的数据大小。即使是表里面最小的ext3,一次也可以使用2T的卷。贝壳全部数据加起来大概2T多一点,家用绝对不成问题。然而作为商业用途,动辄数百T的数据正常到不能再正常,ext3就可以直接出局了,同理reiser4也直接出局。jfs是唯一没有达到EB级别的文件系统,不过32PB也可堪一用,大部分商业系统都到不了这个量级。在管理大型卷的时候,bitmap比extents会消耗更大的空间进行管理。因此不支持bitmap的文件系统可以少考虑,ext3/4虽说支持extents,但是ext3中默认不开启,必须手工指定挂载参数。ext4中一旦启用extents,就无法兼容于ext3。
    最后是性能考量。在贝壳在公司的测试中,xfs会性能高于ext3达20倍。因为根据这篇文章,xfs的随机写性能比ext兄弟差很多,但是顺序写的性能比ext要强上无数倍。我们的业务大部分情况下是顺序写,因此差异非常明显。所以,当你的特性要求差不多的时候,性能和稳定性是另一个考量因素。
文件系统 btrfs ext3 ext4 jfs reiserfs xfs
全填充速率 1m22.083s 1m34.821s 1m15.495s 1m5.819s 1m34.310s 1m38.953s
全填充利用率 0.8945 0.9065 0.9047 0.9959 0.9927 0.9918
大文件效率 14.676 17.435 10.7255 13.7493 14.319 12.7093
大文件删除 2.693 5.262 2.422 0.037 1.802 0.296
小文件效率 9.949 5.131 2.7866 40.949 13.605 8.978
小文件删除 6.737 10.7227 1.39 16.116 2.756 5.653
循环列文件 0.124 0.089 0.002 0.094 0.19 0.099
大文件read 2046206 1931451 1946598 2003912 1537752 1970242
大文件write 1279625 565960 926461 962617 446841 812466
大文件rndread 2012771 1926287 1934420 1985273 1490199 1976056
大文件rndwrite 1380404 1187010 1294689 1446011 1308210 1384804
小文件read 2375893 2934815 3019732 2708437 2559371 2236197
小文件write 926602 526469 681710 844237 395810 939536
小文件rndread 3324647 3544566 2702282 3737551 4045575 2666753
小文件rndwrite 910277 1525970 1244240 1910756 1790393 1311261
    以上数据,在公司的debian testing上测定。机器型号Dell Inspiron 560s,CPU Dual-Core E5700,4G内存,硬盘WDC WD3200AAKS-75L9A0。系统是debian testing,内核2.6.39-2-amd64。全填充是用time dd if=/dev/zero of=abc来测试填满一个分区的速度和容量。大文件是四个ISO文件,共1.3G,从tmpfs上复制到目标设备上的时间平均值,三次平均。小文件是pypy/python2.7/linux kernel2.6.39所有源码,总计49242个文件,629M。从tmpfs上复制到目标设备的时间平均值,三次平均。循环列文件是通过time find .测试效率。下面测试单位为bytes/sec,是iozone测试结果。
    首先是文件利用率,btrfs/ext3/ext4会消耗10%左右的空间作为系统消耗。如果你需要比较高的磁盘利用率,请不要考虑这三种系统。也许你会认为,放文件又不会放满,必须空出部分来才能减少文件碎片。实际上,被消耗掉的空间也并不是白白消耗,你的所有数据,都会增加10%的系统消耗空间。因此ntfs的防碎片阀值(为了防止碎片化,磁盘使用率不应当高于)大约是85%,而ext3就只有75%-80%。
    其次是大文件效率,除了ext3不予考虑外,其余系统都过的去。btrfs/ext4在删除大文件的时候耗时略多,大概是和管理特性有关。
    第三是小文件效率。如果你需要用小文件,千万不要考虑jfs,慢到我无法相信。ext4比btrfs和xfs快了四倍左右,非常适合操作大量小文件。例如源码编译,有blog说ext4比xfs快数倍。
    最后是循环列文件效率,同样,ext4一枝独秀,其余水准相去不远。

    综合以上几个考量,linux中比较推荐的文件系统是ext4, xfs两种。大量文件存储用xfs,小规模文件密集使用用ext4。在特定情况下,可以使用btrfs(它的特性非常全)或者jfs(小文件操作慢,但是随机读写快)。兼容考量下,可以用ext3。不推荐使用reiser4。

参考:
  1. Linux filesystems benchmarked: EXT3 vs EXT4 vs XFS vs BTRFS - Bonnie++ random seeks and file handling
  2. Ext4 ReiserFS Btrfs 等7种文件系统性能比拼
  3. Filesystems (ext3, reiser, xfs, jfs) comparison on Debian Etch
  4. XFS, Reiser, JFS & ext3 performance on Suse 9 Enterprise
  5. Filesystems (jfs, xfs, ext3) comparison on Debian

2011年8月10日星期三

硬盘底座入手

    贝壳买的新硬盘底座入手了,质感不错,很沉,只是在插入硬盘的时候对准不是很方便,总是要对一下才能对准。而且硬盘插上去有点摇晃,如果长时间使用还是会伤硬盘的。不过针对短时间使用,底座正是一个好解决方案。
    硬盘底座,就是将硬盘插上去,然后接入电脑的器件。现在大部分硬盘底座都是sata接口的,以前有IDE接口的,贝壳试过,不稳。IDE本身就不支持热插拔,硬做上去当然好不到哪里去。通常而言,硬盘底座/移动硬盘/sata热插拔是三种相关又各有特点的解决方案。底座的目标是使得硬盘可以更换,使用底座的人,多数希望在一台电脑上更换使用一个接一个的硬盘,对硬盘没有特殊要求。移动硬盘,基本就是把底座的硬件和硬盘捆绑到一起。使用移动硬盘的人,是希望一个硬盘在一台台的电脑上使用,对电脑没有特殊要求。而sata热插拔是强调热,即可以不关机接入设备,对台式机用处不大。通常是现场空间不足了,不能关机增加存储设备造成的需求,对插拔次数支持并不好。有资料说,普通sata接口大概能承受50次的插拔。普通硬盘安装而言,50次是一个非常足够的数目了,但是移动硬盘使用的话,几天就用光了。
    底座支持两种接口,usb2.0和esata。前者的速率是480bps,后者速率是3.0Gbps,合前者最高60M/s,后者最高375M/s。一块民用硬盘的突发速率往往高达150M/s,usb对于普通台式机而言显然是远远不足了。而且esata直接挂入硬盘控制设备下面,而USB则是挂入USB控制器链,效率上说差了一点不说,而且esata是作为普通硬盘对等管理的。
    贝壳本次的方案,是通过一根sata 2 esata接线,将mini-itx主板上的一路未使用的sata引出机箱,连接到底座上。但是linux下要支持esata,必须在BIOS中将SATA设备模式改为AHCI,而后重启进入系统,可以看到设备变了。当然,这个改变对于windows系统来说是个灾难,但是linux系统完全不在乎这个事情。
debox:~# lspci | grep -i sata
00:1f.2 SATA controller: Intel Corporation N10/ICH7 Family SATA AHCI Controller (rev 01)
debox:~# lsmod | grep ahci
ahci                   25089  2 
libahci                22767  1 ahci
libata                149043  2 ahci,libahci
    这次更改造成的一个额外效果就是,机器上的普通sata硬盘速度也上升了。从原来的71M/s到了115M/s,提升相当惊人。

2011年8月9日星期二

读一读我的blog用户

    好吧,应该是viewer,姑且称为user。谢谢你们的关注,这个blog才撑的下去。坚持写blog,尤其是技术blog,是个很辛苦的事情。查证技术很花时间,也没什么回报,一不留神还会成了各大互联网公司的免费写手。不过看看每个月的ip和pv,好吧,还是值得的。
    说是读一读,当然,我不会有你们的名单。我做的是审计,可不代表我会审查来的每个人。但是我的blog里面安装了统计系统,google还有个webmaster。我们来看看数据报表。
    首先是,大概1/3的我的读者是geek,或者足够geek,其余是麻瓜。各种windows系统占了2/3,我觉得普通blog不会出现这个比例...
    然后,firefox家族占了一半不到一点的流量,chrome占1/4,一点的safari,其余的IE。感谢党,感谢国家,感谢CCAV,这样的比例让我在抛弃IE的时候决定不会太艰难。
    来源,google不计,第一是baidu,其次twitter,然后豆瓣。google不计是因为通过google过来的人都算不出来....
    爬虫上说,google占了一半,其次是sogou(这个混帐爬虫占了1/3的流量却没带来几个ip/pv)。然后是Yahoo和baidu,两个没差多少。
    google reader订阅数是180,平均每周更新3.3篇,我还算努力吧?
    最后是很丢脸的ip/pv,上个月ip2700/pv8900,本月预期ip3300/pv8600。

linux下多种文件系统在小规模追加写下的性能

    因为公司需要,所以贝壳最近做了一个比较。多种文件系统,在小规模写下的性能。
    首先要说明的一点是,贝壳的blog为了保持便于传播,因此惯例是不贴图。这次的图,全部在blog同空间的相册上,通过引用方式放原始连接,可以保持原味查看。我知道中国不少站长复制粘帖大法厉害,不过大家手下留情,可以的话自己找个图床,贝壳可以提供所有原始图片。万一相册过载,blog也会跟着挂掉,谢谢谢谢。
    这次的内容,对于有些类型的应用很有价值,具体哪些——懂行的自然了解,就不多嘴了。测试的目标,是测试在同样的环境下,不同文件系统对于散碎的写文件的支撑能力。测试方法如下。
    首先,贝壳写了一个程序,可以开N个子进程。每个进程打开4个文件,分别写出16, 32, 64, 256字节大小的块。间隔m秒写一次。当磁盘吞吐耗尽的时候,大量的线程会排队在iowait上,因此造成iowait和loadavg快速上升。当loadavg明显超过CPU数时,宣告文件系统压力达到极限。具体测试方法,使用自己设计的压力系统对磁盘造成压力,然后通过压力读取系统读取系统参数,输出到文件。通过一个filter重新组织文件,计算移动平均数等。最后通过gnuplot输出图像。由于具体有些涉及公司业务,贝壳避嫌,就不贴出源码了。draw.plot的代码在最后。
    这个业务情况的核心问题是,对同一个文件,在一段时间内会写多次。正常情况下,这些数据会堆积在系统的Dirty区域,直到dirty_ratio的限制到了,或者dirty_expire_centisecs的限制到了,系统才会开始强制写出。否则每隔dirty_writeback_centisecs的时间,系统会写出部分数据。虽然理论上说,一个磁盘的IOPS应当在每秒600-700次上下,但是实际上并不是只能支撑150个并发的。然而设计的好的文件系统,支撑并发数会比设计的差的文件系统明显高。
    这个测试环境和实际的另一个差异,在于读写平衡上。这个业务和大部分的日志系统是很类似的(其实我们系统的业务就是日志)。但是商业用日志系统的特点是在高散碎文件写的情况下还有高随机读。这点在测试中并没有涉及,测试是单纯的大量文件追加写,请读者自行注意。
    首先是400进程,间隔1秒写出,测试对象是ext3, ext4, ntfs, jfs, xfs, btrfs,基本涵盖常见的linux文件系统。ntfs不属于常见的linux文件系统,本轮只做对比测试。首先可以看到的是ext3糟糕到吐血的表现,磁盘写io只有500上下,400个进程最多有280多个在排队。这货不是坑爹呢么。ext4的结果就正常很多,io在100上下,开始的高开是因为前一个测试的静默时间不足。jfs的结果很搞笑,队列load倒是不高,可是Dirty缓存一路上涨,让人不禁怀疑到底有没有写出。xfs的表现中规中矩,半分钟一次写出,和贝壳机器上的dirty_expire_centisecs相吻合,Dirty也不高。btrfs和jfs的情况类似。
    上一轮中,筛掉ntfs和ext3,其余进行1000进程,间隔1秒写出测试。测试对象是,ext4, jfs, xfs, btrfs。这次ext4也表现出了坑爹的一面,Dirty最高250M多,load也明显超过了2,写io大约在700上下,就此出局。btrfs这次的Dirty控制还不错,在25-40M徘徊,写出也不多。看似情况略好,实际上暴露出btrfs一个非常大的弱点,突发响应能力差,服务不稳定。一次集中写出,就能让排队数飞速上涨。jfs虽然曲线类似,但是队列可从没有超过1。综合考虑,后期平均load也明显超过了2,一样出局。xfs还是一样中规中矩的写出,非常低的io和Dirty。jfs依然是高速上涨的Dirty和超级低的io。
    测试到这里,只剩下了jfs和xfs。jfs的特点是大量使用Dirty,平均io很低。xfs的特点是Dirty使用比较低,io输出比较平均。不过我们的服务器内核对xfs的支持比jfs要好一点,所以使用xfs已成定局,下面就是测试两者的极限性能而已。
    第三轮的参数是2000个进程,0.75秒间隔。jfsxfs表现非常相似,让贝壳差点怀疑自己是测试错了东西。核查之后,确实没有。所以就下狠手,测试了一把高压力的。
    第四轮的参数是3200个进程,0.5秒间隔。从绝对量上,大概是基础测试的16倍。在jfs测试开始后的三分钟内,load上升到了60,宣告出局,因此贝壳这里没有jfs的图像。但是xfs还是完美的顶住了压力。Dirty已经上涨到了80-120M,平均io也到了300。然而平均load只有1左右,最高load也只有1.4。
    最终测试的参数是4000个进程,0.5秒间隔,基础测试的20倍。xfs的表现万分惊艳,平均io300-400,Dirty100-160M,平均load大约是1,最高也只有2。也就是说,到最后贝壳还是没有测试出xfs的最高压力。
    另外,贝壳也通过iozone对两者进行了测试,结论是,xfs在读写性能上比ext3高一些,但是在随机读写上大幅低于ext3。无论哪个数据,都无法出现这种20倍以上差距的现象。因此贝壳又对文件系统选择发生了兴趣,具体写在下一篇blog上。
    从最终结论上说,我们确定了xfs比ext3的巨大提升(20倍以上),并准备对xfs进行可用性测试。如果您有什么经验,欢迎和我联系。
-------------draw.plot-------------
set terminal png size 1920,1080
set output "out.png"
set xdata time
set timefmt "%H:%M:%S"
set y2tics
set origin 0,0
set size 1,1
set multiplot
set origin 0,0.5
set size 1,0.5
plot 'out.dat' using 1:2 with lines title 'Buffer',\
     'out.dat' using 1:3 with lines title 'Cached',\
     'out.dat' using 1:4 with points title 'Dirty' axes x1y2
set origin 0,0
set size 1,0.5
plot 'out.dat' using 1:5 with points title 'wio',\
     'out.dat' using 1:6 with lines title 'sma_wio',\
     'out.dat' using 1:7 with lines title 'loadavg' axes x1y2
unset multiplot
-------------draw.plot-------------

2011年8月7日星期日

从C++的一个特性到设计原则再到哲学

    最近在看C++的设计和演化,里面讲到算符重载。关于这个,Effactive C++里面明确说明,不要试图重载&&和||算符。因为这个重载造成的结果和默认不符(Not same with the default)。
    &&和||有什么特殊?熟悉C的朋友考虑这么一个问题。if(i && ++i)的作用是什么?基本来说,这个语句是判断i是否为0或者-1的,并且有个额外效果就是对i进行自增。但是,如果i == 0,则不进行自增,这就是&&的短路求值原则。这个原则产生了一系列写法,例如sh中常见的 [ -z "$ABC" ] && { ... }。
    不过当重载了&&或者||后,就破坏了短路求值原则。因为C系列语言是应用序语言,参数先求值。所以后参数*一定*会被求值,无论前参数的值是多少。
    更加悲崔的是,这个破坏了最小惊讶原则,或者叫做知识内隐原则。当你使用一个知识的时候,你会根据自己的经验对这个知识做内隐的预期。例如,虽然螺丝有左螺纹也有右螺纹,然而你在拧螺丝的时候,多数预期是顺时针拧紧。不论其理由,这个已经成为常态。同样,有下压把手的门是扇页门,画着杯子的店家是咖啡店和茶馆,画着裙子的厕所是女厕,这些都是你对知识内隐的预期。破坏这个预期,相当于把螺丝改为反向,下压把手的门改成移门,画着杯子的店家是古董店,男厕画裙子一样,会让人感到不知所措。大家会莫名其妙的绕出去,确认门上画的确实是裙子,走进去再看到男厕,感到世界莫名其妙。
    同样的道理,如果一个对象使用了&&重载,程序员唯一能够快速发现的机会就是在调试时单步了&&的语句。如果他运气不好,可能在数个小时内都找不到理由,直到反汇编目标代码为止。
    那C++为什么设计算符重载?那是设计给需要的算符用的。其实C++一直是一个矛盾的设计,一方面他认为,程序员是不可信的,所以C++里面有隔离保护系统,例如私有成员函数和变量。另一方面,他又认为程序员应当对自己的行为负责,因此他设计了复杂的算符重载,复杂的继承系统,并期待程序员能够按照正确的方法使用。这是一个奇妙的,矛盾的设计思路,反映设计者自身的冲突(例如多人设计),或者C++设计者的实用主义倾向(选择最实用的设计)。python语言的思路相对统一,他认为程序员应当为自己的行为负责,所以python的隔离系统都是伪系统。而java的思路也相对统一,他认为程序员是不可信的,所以java才会搞出复杂的架构哲学。

2011年8月4日星期四

估算(一)

    出租车价又涨了,贝壳好奇出租车上面水到底多深,就找几个师傅了解了一下行情,大家看看吧。
    首先是油价,目前是7块多,不到8块,按照7.5算。出租车都不太新,每百公里油耗不小,按照8-10算不过分。一般出租,只要在市区跑着,平均速度大约是40公里/小时。司机都是24小时轮班制的,做一休一。平均做一天,大概上缴330-380不等的出租车管理费。以上就是大致的原始数据。
    一天24小时,大约要跑960公里。乘上油耗,大约是86.4升的油。折合价格,大概是650上下。这是工作一天的油价。
    师傅做一休一,一个月只能做15天。按照税前4500的工资算,一天要赚300才能做平。对于老驾驶员,还做一休一来说,这个价格不算太高。去掉三金和税,还剩下3650。
    一天管理费350,一个月师傅这里能缴5250的管理费。但是三金就要缴掉2000,还剩下大概2000是真正的管理费。
    我们综合来算,一天的成本是1300。
    平均里程费用的问题,其实有点复杂。不考虑夜程,大概可以用3.5算。大概原理是这样的。
    3公里以内,14元。就算正好3公里,费用还是4元多。不足3公里平均费用更高。
    3-10公里,一公里2.4。最低值平均费用4.6,最高值平均费用3.1,最终得到的平均费用都介于两者之间,里程越长,平均费用越低。
    10公里以上,一公里3.6元。总平均费用会从3.1逐步上升到3.5左右的样子。
    从区间函数变化可以发现,出租车费用最低的区段大约在9-11公里之间。6公里以内的费用最高,12公里以上的费用就平均了。注意,以上计算都是时间-距离折算计算,即时间延误被乘以系数加到距离上了。实际出租车计价表也是采用的这种算法。
    中途插播一句,如果是多人短途,例如三四个人2公里多。或者8-10公里的地理距离,价格在28-35上下,都是比较合算的坐法。出租替代公交的成本不高。
    1300的成本,除以3.5的公里费用,得到371公里。加上各种余量考虑,出租车司机一天最高驾驶1000公里,实际400公里有客就可以收回成本,即空载率不应低于40%,否则就亏本了。
    我们观察成本,发现一半多的大头多来自油价。难怪每次油价变化出租车师傅都一脸郁闷。
    对抗油价变化的方法也很简单,就是等车,减少空乘移动。从上面数据可以看出,每公里载客可以赚入2.8元,一天的除油费成本650。如果每次载客结束都是当场熄火等待乘客,只要232公里就可以收回成本。所以我们经常可以看到机场或者各个地方的司机师傅,排长队等车。而且油价越高,师傅移动拉客的成本越高,越趋向于等车。
    一个师傅每个月缴2000的管理费,上海大约是5万到10万辆出租,一辆出租两位师傅轮流开。一个月给各个出租公司上缴的管理费大约是2亿到4亿。
    出租公司要负责车辆管理,叫车电话服务,人力资源,还有无线电调度,是有一定开销的。车辆管理的费用浮动,不大好算,然而普通人的车辆,一次养护成本大约是1200,一年一次。我们假定出租公司成本翻倍,一辆一个月200,全上海的车辆维护大约是1000-2000万。叫车电话,调度管理按照1:100的管理比例,需要500人持续管理。按照合三金工资4000(对于无技术的接线员来说,会比需要技术,连班转的出租师傅工资低)计算,大约是200W一个月。无线电调度不是很清楚,应该没有特别高的成本——除了牌照一类的问题外。
    满打满算,各家公司的总开销,加上正常盈利,一个月5000万已经足够。那么2-4亿中的其余部分到哪里去了呢?是成为了出租公司盈余,还是成为政府管理拍照费用,这就不得而知了。
    以上数据,都是2011年5-7月间,和各个出租师傅聊天时提到的。大部分数据都是经过一位以上师傅的口中说出,有一定准确性。然而由于仅听取了同一利益倾向的所有当事人,所以数据可能有一定误差。

2011年8月2日星期二

如果你的python项目一定要源码保密,你一定用错语言了

    python的特征在于快速编写代码,快速运行得到结果。通常而言,就是高开发速度。
    如果你的项目需要源码保密,那通常不会是高速开发的项目。因为能够高速开发的,就能够高速复制。别人在看到你的概念和基本逻辑后,可以非常快的抄一份出来。代码什么的根本是浮云。

除虫故事(二)

    第二个故事,是一次oracle数据库的紧急损坏抢修问题。
    当时客户紧急保修,系统无法继续工作,重启后无效。我们就找了DBA赶快飞去客户那里。客户有两台应用服务器和两台数据库,应用服务器组成热备的态势,数据库组成RAC。数据保存在一个SAN盘阵上,LogFile放本地,ArchivedLog使用备份脚本复制到备份服务器后删除。听起来是挺靠谱的方案,没想到就坏了。
    去了后,客户说暂时恢复了运作。然而我们还是要出具详细的报告,因此赶快去了机房。贝壳第一眼看的东西,就是/var/log。里面的报告是err9,也就是文件读写错误。oracle一切正常,应用发布服务器一切正常。
    这下有点抓瞎了,难不成要出具一份报告说SAN盘阵损坏?可是损坏也得有厂商来维修,说坏得有真凭实据阿。现在SAN一切正常,这个报告怎么写呢?
    说来算巧合,贝壳检查磁盘的时候,顺手打了一句df -h进去,看到磁盘空间已经用掉了80%以上,顺口问了句DBA,如果空间耗尽会如何。DBA说会挂起,和目前状况一致。贝壳顿觉狐疑,是不是空间耗尽呢?是的话,为什么会神秘的恢复呢?
    Oralce的运作非常精巧,也非常复杂。当一条SQL语句执行的时候,先写LOG,然后操作数据,最后再将结果写入LOG。当出现问题需要复原的时候,根据某个时间点的数据备份,和整个运作过程中的所有Log,就可以复原。但是LOG写出的时候量非常大,没有无限的空间给他写阿。所以LogFile的设计是文件循环,当写满一个文件,切换下一个文件。一个文件写满后,就会有一个服务,趁着磁盘空闲,将Log压缩备份为ArchivedLog,然后再将这个文件的状态变为Empty。
    我们的设计,是通过脚本备份ArchivedLog,除去最后一个文件外,复制到备份服务器上,然后删除。但是我们对ArchivedLog的量估计不足,一天清理一次,分配空间只有20G出头。系统开始的时候压力不高,因此绰绰有余。后来压力逐渐升高,这天的操作比较多,ArchivedLog量大了点,导致空间写满。当ArchivedLog空间满之后,备份进程就会报告错误,这就是/var/log下面err9的来历,因此LogFile无法备份出来。当所有的LogFile被循环写满后,SQL执行前试图写入LogFile失败,执行就会失败,然后挂起在那里。这导致了所有应用发布服务器的失效。
    备份脚本的设计是定时和开机结合的,在客户第一次重启设备的时候,已经执行了备份脚本。然而备份动作需要执行相当久,中间客户又重启了几次,导致备份工作进展缓慢。直到半个小时后,第一份ArchivedLog才备份出去。然后清理文件,开始LogFile的备份,大约执行了一个小时多。此时服务就突然恢复了,因为空间问题已经暂时解决。而后是不断的ArchivedLog备份和LogFile的备份的平衡,直到我们到的时候,LogFile已经全部空了,ArchivedLog还没有完成备份。因此我们才能抓到最后的尾巴。
    反过去检查备份脚本的执行记录,基本验证了这个想法,客户也接受了我们的报告,不过还是要责令修改系统——这是后话不提了。
    这个故事里面,至少有几个教训。
  1.     对于所有编程时无关紧要的假定值,在开发时可以胡给一个差不多就行,但是上线的时候必须重新分配合理的值。因此必须将这些假定值记录出来,否则从程序中找出假定值来本身就是一个非常困难的事情。
  2.     确实运作一下,搞清楚运作方方面面的问题,不要想当然,觉得没问题。就算运作了没问题,在时间的考验前都没人敢保证没事。
  3.     一套系统,尤其是大型复杂系统,必须有懂得运维的人员接手管理。检查磁盘IO,CPU压力,内存和磁盘用量,数据量,网络响应速度等等问题。
  4.     废物Log不要乱出,太多的Log和没有无异。如果早关注备份脚本的执行记录,就能早找到问题。可是由于量太大,我都是过滤掉了看的。