2009年5月12日星期二

在Linux下统计你的Erlang程序的行数(SLOC)

统计代码行数(SLOC, soure line of code)的几种选择:
  1. 使用命令wc -l filename可以统计文件filename的行数,但是不能除去空行和注释。
  2. Linux下有个程序叫sloccount,可以统计各种语言的代码行数,但是不支持Erlang -_-!
  3. 我的最终解决方案是使用grep。
使用下面的命令即可统计当前目录下Erlang源代码的行数:
grep -cv '\(^%\)\|\(^\s*$\)' *.erl *.hrl
或者
egrep -cv '(^%)|(^\s*$)' *.erl *.hrl
返回的结果类似于:
module1.erl: 120
module2.erl: 38
module2.hrl: 45

参数c表示让grep统计行数
参数v, 也就是--invert-match,表示选取不符合正则表达式的行

正则表达式(^%)|(^\s*$)由两个正则表达式的并组成。正则表达式^%表示注释(Erlang的注释都以%开始),而正则表达式^\s*$表示开头(^)与结尾($)之间只有任意多个空白符(\s)的行,也就是空行。这样整个正则表达式(^%)|(^\s*$)即表示注释行或者空白行。

GNU的grep和egrep功能相当,区别在于前者使用GNU Basic Regular Expression(BRE),这是目前还在使用的最古老的正则表达式语法,而后者使用的是GNU Extended Regular Expression(ERE)。

两种正则表达式语法的主要区别是前者要求特殊符号前必须有转移字符\, 而后者不要求有\,但是当想表示特殊字符的原意的时候必须加\作为前缀。当正则表达式中有很多特殊符号的时候,ERE的表达就比BRE简洁不少。

关于BRE和ERE可以查看http://www.regular-expressions.info/gnu.html
关于grep的正则表达式的语法可以查看http://opengroup.org/onlinepubs/007908775/xsh/regexp.html

2009年5月7日星期四

Summary on Eleutian's vim tutorial

Eleutian gave a series of vim screencast tutorials , which I think it's good for beginners.

Here's summaries on the key points in his tutorials:

Tutorial 1

1. Vim is a modal editor. There are a lot of modes:
  • Normal mode: Press ESC or CRTL+[
  • Insert mode: Press i in normal mode
  • Command mode: Press : in normal mode
  • Visual mode: Press v in normal mode
  • Append mode: Press a in normal mode
2. In command mode, "e" means opening a file and "w" means saving a file.
  • :e filename : open a file whose name is "filename"
  • :e! : reopen the current file; all changes are lost
  • :w : save the current file
  • :w filename : save the current file as filename; primarily used when a file is to be saved for the first time
3. Stay in normal mode, unless you're actively typing text.
4. To move around in a most efficient way use "h", "j", "k", "l" as left, down, up, right respectively.
5. Move more quickly:
  • ^: Home; move to the head of the current line
  • $: End; move to the end of the current line
  • CRTL + D: Pagedown
  • CRTL + U: Pageup
  • w: Move to the next word
  • b: Move to the previous word
Tutorial 2
1. Move the beginning or the end of a document:
  • gg: Move to the beginning of the document
  • GG: Move to the end of the document
  • XGG: Move the Xth line of the document, like 10G(move to the 10th line)
2. Copy(yank), Cut(delete) and Paste
  • yy: Copy the whole line
  • yw: Copy the next word
  • y$: Copy till the end of line
  • x: cut the current letter
  • dd: Delete the whole line
  • dw: Delete the next word
  • p: Paste the text that just deleted or yanked
3. Change
  • cw: Change the next word
  • cb: Change the previous word
  • c$: Change till the end of line
  • ct: Change till , like ctD(change till the first occurence of letter D)
4. Swap two consecutive letter: xp

Tutorial 3
1. Search
  • :/<Pattern> : Search forward according to the <Pattern>
  • :?<Pattern> : Search backward
  • n: Go to the next occurence <Pattern>
  • p or N: Go to the previous occurence <Pattern>
2. Find
  • f<Symbol> : Find the first occurence of <Symbol>
  • ; : Go to the next occurence of the <Symbol>
  • , : Go to the previous occurence of the <Symbol>
3. Replace
  • %s/<TargetString>/<SubstituteBy>/g : % means the range is the whole text, % means substitution, is what we are looking for, is the substitution for . Don't forget the /g. For example, %s/Good/Bad/g will substitute all ocurrences of "Good" by "Bad" in the whole document.
4. Find occurences of the word under the cursor
  • # : Go to the previous occurence of the word under cursor
  • * : Go to the next occurence of the word under cursor

2009年4月26日星期日

Erlang的Mailbox或者MQ的性能问题

最近看了几篇帖子

erlang-questions mailing list上的讨论Low disk logging performane in SMP
Caoyuan's Blog: A Case Study of Scalability Related "Out of memory" Crash in Erlang
Caoyuan's Blog: Async or Sync Log in Erlang - Limit the Load of Singleton Process

它们都是关于Erlang的mailbox性能问题的。所谓mailbox,就是Erlang的process用于存储其他进程发来的尚未处理的消息的容器。

根据这些讨论我有下面几点总结:
  1. 不要把mailbox“撑爆”:当mailbox太大的时候,selective receive的性能就会大打折扣。在第二篇帖子中,作者的甚至把error_logger的mailbox塞到机器out of memory!
  2. 如何避免:这几篇讨论这中“撑爆”的mailbox都是日志process:一个是error_logger,另一个是file_logger。日志进程的io操作都是比较耗时间的,而发送来的消息又太多太快,以至于写日志的进程根本来不及处理,消息只能在mailbox中积累。所以这在种consumer速度跟不上producer的情况,要尽量减轻consumer(这里是logger)的负担,让操作尽量在producer处完成(比如日志的格式化操作在发送者处做好,而不是在logger处)。另外还可以考虑把logger从singleton变成分布式的。
  3. SMP:多核的使用会加剧这种多producer单consumer情形的速度差距,导致性能下降,甚至内存溢出。
  4. 根据第一篇中的讨论,file:write似乎也是把write的请求发给一个file server,所以过多的请求也会导致write请求的处理效率低下。把几个write请求大包成一个write请求再发送过去或许是一个提高性能的办法。

2009年4月21日星期二

Ubuntu下录制桌面

为了项目演示,我需要在Ubuntu下把我操作的软件的过程录制下来。我使用了RecordMyDesktop这款开源软件,使用下面的命令来安装它:

sudo apt-get install recordmydesktop gtk-recordmydesktop

这个软件的GUI很简洁,非常容易上手。录制出的结果是ogg格式的,在Windows下可能无法播放。我使用了mencoder把ogg转换成avi格式。安装mencoder使用下面的命令:

sudo apt-get install mencoder

使用命令就可以把ogg格式的文件转换成avi:

mencoder -idx input.ogg -ovc lavc -oac mp3lame -o output.avi

我参阅了这个关于Ubuntu下录制桌面的英文blog:http://ubuntuchocolate.wordpress.com/2007/09/01/howto-screen-capture-in-ubuntu-feisty-fawn/

2009年4月7日星期二

美化Ubuntu桌面:Wallpaper Clock





Wallpaper Clock集漂亮的桌布和方便的时钟于一身,将美观和实用完美的结合在了一起。而且在Ubuntu下你可以完全免费地使用Wallpaper Clock来美化你的桌面。

安装过程我参考了这篇国外的blog

使用Wallpaper Clock需要完成三个方面的准备:
  1. 下载Wallpaper Clock:你可以从它的官方网站http://www.vladstudio.com/zh/wallpaperclock/上下载,现在已经有200+的壁纸了,每张都很精美,其中至少有一半是可以免费下载的。壁纸的文件扩展名是wcz。
  2. Wallpaper Clock screenlet:你下载的这些wcz文件不像图片文件可以直接作为桌面的,必须使用专门的软件才能够作为动态桌面呈现出来(每分钟刷新一次以更新壁纸上的时间)。在Windows,Mac,Linux下都有软件可以显示wcz文件,其中Linux下的是一个叫Wallpaper Clock screenlet的screenlet,你可以到http://gnome-look.org/content/show.php?content=66717下载它。这个东东也不能独立运行,它需要利用screenlets manager安装并使用它。
  3. 安装screenlets包:在ubuntu下使用命令"sudo apt-get install screenlets"来安装,这样你就得到了Screenlets Manager以及自带的一些screenlets。注意,在我的Ubuntu 8.04下从源上安装的Screenlets Manager不能使Wallpaper Clock screenlet正确工作。如果你也遇到了同样的问题,根据前面提到的那篇blog,你可以从https://launchpad.net/screenlets/trunk/0.0.12/下载并安装了0.0.12版本的screenlets。在我的Ubuntu 8.04下0.0.12版的screenlets包可以使Wallpaper Clock screenlet正确工作。
至于如何通过Screenlets Manager安装Wallpaper Clock screenlet,以及如何安装wcz为扩展名的壁纸,这里就省略了(也可以参看前面提到的blog),因为都只需要简单的GUI操作就可以完成。

Enjoy!

2009年3月3日星期二

ubuntu下安装Acrobat Reader并显示中文

Adobe的Acrobat Reader还是比Ubuntu自带的Evince要好一些。

在Ubuntu下安装Acrobat Reader的方法如下:
Step1. 设置mediabuntu源,参考官方的指南https://help.ubuntu.com/community/Medibuntu
Step2. sudo apt-get install acroread

此时Acrobat Reader就可以用了,但是还不能显示中文。为了能显示中文还需要做下面几步
Step3. 到这个http://www.adobe.com/tw/products/acrobat/acrrasianfontpack.html网址上下载中文语言包
Step4. 解压后,运行里面的安装脚本(用命令./INSTALL.sh)。当安装脚本要求“
Enter the location where you installed the Adobe Reader [/opt]” ,你输入“/usr/lib”。

这样就可以在Ubuntu下使用Acrobat Reader查看中文文档了。
上述方法在Ubuntu 8.04下实验通过,其他版本应该也可以。

2009年2月26日星期四

判断三点共线问题的最佳程序

此问题与解答源于《Beautiful Code》,这里只是精炼地表达书上的解答。

问题:如何判断平面上三个点(x1,y1),(x2,y2),(x3,y3)是否在一条直线上。
思路:
这个问题的难度不在于如何解决它,而在于如何“完美”地解决它。“完美”,可以理解为代码必须正确,美观,简洁,高效而且不容易受到计算误差的影响。

判断三点共线的方法有很多。如果采用与斜率有关的方法(比如使用直线的截斜式),那么必然要对斜率无穷大或者说没有斜率的情况做特殊处理。也可以考虑计算第三点到另外两点所确立的直线的距离,如果用这种方法,那么会涉及到求直线方程Ax+By+C=0和开平方,这样做运算效率较底。

最终的解决方案是求三点所确立的三角形的面积,三点共线当且仅当三角形的面积为0。而计算面积最简单高效的方法是使用矢量法,即三角形面积的行列式公式,面积等于
| x1-x3 y1-y3|
| x2-x3 y2-y3| / 2

[ (x1-x3)*(y2-y3) -(X2-X3)*(y1-y3)] / 2
利用这个公式可以保证在无论三点是否互不相同都可以判断共线。

Lisp代码:
(defun area-collinear (x1 y1 x2 y2 x3 y3)
(= (* (- x1 x3) (- y2 y3))
(* (- x2 x3) (- y1 y3))))