这篇文章真的不错,转载于此,盖因这里支持直接Copy网页,省去了排版的麻烦,^_^ 本文适合初学编程的程序员阅读,它对比了几种编程语言在解决同一问题的时候的运效率。并通过具体的例子进行了量化分析。主要目的是帮助初学者认识各种编程语言的特质,并且能够理性的选择适合的编程语言来进行工作。 准备 #!/usr/bin/perl $filename="d:\access.log_"; $count = 0; open(FILE , "<$filename"); while(<FILE>) { @match_list = ($_ =~ /HIT/g); $count=$count+@match_list; } close(FILE); print "Count = $count "; exit
#include <stdio.h> #include <string.h> void main() { int len=2048; char filename[20];//文件名 char buff[10000];//文件缓冲区 char hit[5]; FILE *fd; int i,j,flag=0,over=0; int max,readed; int count=0;//最后的结果 strcpy(&filename[0] , "d:\access.log_"); strcpy(&hit[0] , "HIT"); buff[0]=0x0; buff[1]=0x0; //打开文件: if((fd = fopen(&filename[0] , "rb"))==NULL) { printf("Error : Can not open file %s ",&filename[0]); } //读取文件内容 while(over != 1) { readed = fread(&buff[2] , 1 , len , fd); if(readed < len) { over=1; max=readed; } else { max=len; } for(i=0;i<max;i++) { for(j=0;j<3;j++) { if(hit[j] != buff[i+j]) { flag=0;//一旦有一个不相同就退出并且标志为0 break; } else { flag=1;//一个相同为1,如果连续都相同最后结果定是1 } } if(flag==1) { count++; i+=j-1; } else { if(j==0) { i+=(j); } else { i+=(j-1); } } } //把最后两个字符转移到前面两个字节以防止切断搜索串. buff[0]=buff[max]; buff[1]=buff[max+1]; } fclose(fd); printf("count:%d ",count); }
#include <stdio.h> #include <string.h> #include <fstream.h> void main() { int len=2048; char filename[20];//文件名 char buff[10000];//文件缓冲区 char hit[5]; int i,j,flag=0; int max; int count=0;//最后的结果 strcpy(&filename[0] , "d:\access.log_"); strcpy(&hit[0] , "HIT"); buff[0]=0x0; buff[1]=0x0; //用输入流打开文件: ifstream input(&filename[0]); //读取文件内容 while(input) { input.getline(&buff[2] , len); max = strlen(&buff[2]); for(i=0;i<max;i++) { for(j=0;j<3;j++) { if(hit[j] != buff[i+j]) { flag=0;//一旦有一个不相同就退出并且标志为0 break; } else { flag=1;//一个相同为1,如果连续都相同最后结果定是1 } } if(flag==1) { count++; i+=j-1; } else { if(j==0) { i+=(j); } else { i+=(j-1); } } } } printf("count:%d ",count); }
第四个选手:汇编 STSG SEGMENT STACK 'S' DW 64 DUP(?) STSG ENDS ;数据段 DATA SEGMENT rlength EQU 2048 fname DB 'access.log_',0 hit DB 'HIT$' fd DW ? ;文件句柄 resault DB 'count : $' ;结果提示 count DD 0 ;存放结果 disflag DB 0 ;显示标志 buff DB 5000 dup(0) ;缓冲区 DATA ENDS ;代码段 CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE,DS:DATA,SS:STSG,ES:NOTHING MOV AX,DATA MOV DS,AX ;我的代码开始: mov ah,3dh ;打开文件 lea dx,fname mov al,00h ;文件打开方式 int 21h ;开始操作 ;这里就不作错误处理了,偷懒喽! ;CF=0表示正确,CF=1表示错误,AX是文件句柄或者是错误代码 mov fd,ax ;保存文件句柄 READ: mov ah,3fh ;读文件 mov bx,fd ;文件句柄 mov cx,rlength ;要读length字节 lea dx,buff ;给出读缓冲区指针 add dx,2 ;缓冲区指针向后错两个(目的是解决边界问题:有一个HIT正好横跨rlength界限) int 21h ;开始读 ;AX里面是实际读出的字节数 ;读完了以后,扫描缓冲区 push ax ;保存AX字节数 cmp ax,0 jz ALLEND ;文件读完了就退出 sub dx,2 ;指针向前错2个, mov si,dx add dx,2 ;把指针回到原来的位置 add dx,ax ;计算结尾 LOD3: cmp si,dx ;到头了就重新读一次文件 jz OVR lods buff lea bx,HIT cmp al,[bx] jnz LOD3 ;读第一个字节不相等就重新读一个 cmp si,dx jz OVR lods buff cmp al,[bx+1] jnz LOD3 ;如果第一个字节相等,就读第2个字节,不行等就从第一个字节再重比较。 cmp si,dx ;如果第二个字节也相等的话,就比较第三个字节。 jz OVR lods buff cmp al,[bx+2] jnz LOD3 ;第三个字节不相等再从头开始 ;有一个HIT匹配 push bx lea bx,count add WORD ptr [bx],1 ;计数器增加一个 adc WORD ptr [bx+2],0 ;进位 pop bx jmp LOD3 OVR: mov ah,[si-1] mov BYTE ptr buff+1 , ah mov ah,[si-2] mov BYTE ptr buff , ah pop ax ;恢复这次总共读出的字节数 cmp ax,rlength ;看看是不是最后一次(剩余的零头) jz READ ;如果是最后一次读文件, ALLEND: mov ah,3eh ;关闭文件 mov bx,fd ;文句柄 int 21h ;关闭文件 mov ah,9 ;显示结果字符串 lea dx,resault int 21h ;转换2进制结果到10进制ACSII形式 mov bx, WORD ptr count call TERN mov ax,4c00h ;返回DOS int 21h ;结束代码,最大的数字已经排到了最前面 MAIN ENDP TERN PROC ;这个子程序是转换并显示2进制数字的 mov cx,10000 call DEC_DIV mov cx,1000 call DEC_DIV mov cx,100 call DEC_DIV mov cx,10 call DEC_DIV mov cx,1 call DEC_DIV ret TERN ENDP DEC_DIV PROC mov ax,bx mov dx,0 div cx mov bx,dx mov dl,al add dl,30H mov ah,disflag ;read flag cmp ah,0 jnz DISP ;已经显示过有效数字了 cmp dl,30H jz NODISP mov disflag,1 ;作用是第一个有效数字出现前不显示0 DISP: mov ah,2 int 21H NODISP: ret DEC_DIV ENDP CODE ENDS END MAIN 上面这段代码我猜你也懒得仔细阅读。其实他不能"显示结果"。因为最后这段负责把最终结果转换成可显示ASCII码的程序实际上只能转换二进制十六位的数据,而最终的结果高达1000万挂零,显示会出错。由于这最终结果的显示已经和程序的运行没有大关系了,因此,我也就懒得去写一个32位的ASCII转换程序了。就这样吧。 第五个选手:JAVA JAVA是一个不能不参加比赛的选手。有如此多的人热爱他,他们中的一半人是因为JAVA的面向对象特性以及良好的跨平台特性。而另一半人纯粹就是因为JAVA不姓"微(软)",这就是意识形态在程序员头脑中对某种语言的注释。单纯从语言元素上来说,我还是比较喜欢JAVA的。因为他的语法干净、简洁。环境也好。虽然用虚拟机系统(JVM)的做法来实现跨平台特性并非什么了不得的创意(像不像30年前的BASIC解释器?别跟我说什么中间代码?几乎所有的解释器都是把语言因素翻译成中间代码的,JVM不过是分成2步来实现罢了,但从运行机制上应该是差不多的。),但JVM仍然将JAVA的跨平台特性做到了前所未有的地步。而且JVM是一个很干净的系统,让人用起来赏心悦目。说到这里我忍不住想提一下J2EE企业应用框架了。不知道有多少人能够看懂SUN出的J2EE的"理论著作"?满纸充斥着各种生造的概念,洋溢着溢美之词。JAVA的企业应用框架实在是比较复杂的东西,虽然赶不上后来的.NET框架,但足以让大多数初学者望而却步。一句话,东西太多了。事实上JAVA的企业级应用并没有想象的成功,iPlanet就随着电子商务概念的全面垮台而渐渐淡出。现在换了个名叫“SUNONE”――SUN公司员工原话。 我们回到JAVA的语言元素上来说,实际上JAVA可以被理解为被纯化的C++。JAVA去除了C++为了兼容C而增加的一些"非面向对象特质",用其他的一些变通办法实现C++直接实现的功能,比如:多继承。在实现机制上,JAVA的程序会先编译成.CLASS文件,然后这种跨平台的中间代码就可以"一次编译,到处运行"了。当然必须运行在有JVM虚拟机的环境中,连图形什么的都可以照搬。换句话说,你用JAVA程序在PC屏幕上画一个圆,在JAVA-PDA上它还是圆的。 我在本次测试中,写了下面的代码,用JAVA做了同样的测试,测试中实际上用到了:JAVA的文件流类,运行了循环、条件判断、数组操作等基本的语言因素。环境是J2SE1.3.1-06。JAVA程序做1500万行的文本扫描用了8分21秒18。应该说是几种语言中最慢的,基本上和纯解释的PERL是在同一水准。J2EE的JVM环境还是经过优化的所谓HOTSPOT。 import java.io.*; public class langtest { public static void main(String[] args) { String filename = "d:\access.log_"; try { count(filename); } catch (IOException e) { System.err.println(e.getMessage()); }; } public static void count(String filename) throws IOException { long count=0; long len; String strline = ""; char hit[] = {'H','I','T'};//要搜索的字符串 char buff[] = new char[2100]; Reader in = new FileReader(filename);//用FileReader类构造产生一个Reader类对象 LineNumberReader line = null;//生成一个空指针 try { line = new LineNumberReader(in);//建立LineNumberReader类对象 while((strline = line.readLine()) != null) { //到这里已经读出一行了,用下面的代码分析这行有几个HIT int i=0,j=0,max=0,flag=0; buff = strline.toCharArray();//转换成字符数组 max = strline.length(); for(i=0;i<max;i++) { for(j=0;j<3;j++) { if(hit[j] != buff[i+j]) { flag=0;//一旦有一个不相同就退出并且标志为0 break; } else { flag=1;//一个相同为1,如果连续都相同最后结果定是1 } } if(flag==1) { count++; i+=j-1; } else { if(j==0) { i+=(j); } else { i+=(j-1); } } } } System.out.println("Count : "+count); } catch (IOException e) { System.err.println(e.getMessage()); } finally { try { if(in != null) in.close(); } catch (IOException e) { } } } } 候捷先生翻译的宏篇巨著《JAVA编程思想》一书中第67页说到:"使用最原始的JAVA解释器,JAVA大概比C慢上20到50倍"之说法我在阅读的时候就心存疑虑,心想要是这样,JAVA完全没有存或与世间的必要了。在亲自动手试验过后,我觉得说JAVA在J2EE环境下,比C慢上2-3倍还是比较可靠的说法的。况且,目前越来越多的硬件JVM的诞生,也给JAVA越来越多的机会。不过我担心的正是这点,JVM的多厂家多样化很可能会造成某些兼容性方面的问题。例如我见过一篇文章就是讨论某种JAVA程序在IBM-JVM可用而在SUN-JVM上不可用之事例。但愿的,JAVA能健康成长。 总结 事实上,本文有两个基本的意义传递给初做程序员的读者: 一、 抛开你的意识形态好恶,选择最合适的编程语言来完成你的工作。每种流行的语言都有自己存在的意义。 二、 在编程中,有想法就自己做一做,你会得出自己的结论。 至此,你应该明白,前面的所有测试结果其实并不重要,重要的是你了解了这些语言的特质,也许在今后的编程生涯中会因此增加一点点"经验"呢。
后记 2003-05-17■作者:阿谭■出处: yesky 【作者: 覃健祥】【访问统计:1245】【2004年09月7日 星期二 12:01】【注册】【打印】 回复
4 你好,现在通过下面链接可以备份您的博客: http://home./blogmove.aspx 快去看看^_^ bokee.com 18
只能说明文件的I/O操作是最费时的,其实应该说java和C的效率是有数量级的区别的,C代码中80%以上的时间都花费在I/O上了,C++除了I/O之外在流的处理上也发费了交多的时间,这是本次测试中C++比C慢就慢在这儿,很显然java的运行期消耗已经和I/O处于相当的数量级,因此实际消耗时间是C的3到4倍.perl的运行期原理不是很清楚. 我觉得java中也有正则表达式应该快的一点吧! C++, Java 都提供块数据的方式, Perl 也可以多行一并读入 这样才能有可比性 怎么没有发完呢,是不是故事结局要 汇编语言比效率比不过c语言: 青蛙的发情期到了吗?~ 我觉得写得非常好,对了解各语言的特点很有帮助。
|
|