编译语言 vs 解释语言

阅读:  评论:  作者:Rybby  日期:  来源:rybby.com

一直以为,编译语言的性能绝对比解释语言快,因为就理论而言,解释语言要一边解释(将脚本语言翻译成计算机能识别的语言)一边执行,就工作量来说就比编译语言多一倍。以下是自己心目中长久以来的各种编程语言的性能排行榜:

1)01语言(计算机语言)

2)汇编语言(半计算机语言,低级语言)

3)编译语言(高级语言,如C,C++,C#,JAVA等等)

4)解释语言(脚本语言,如Javascript,VBscript,Node等等)

直到最近,在锐某开发TTD(Thick Text Database/胖文本数据库)的过程中,因为自己是用 Node.js 进行开发的,后来觉得也许用编译语言能获得更高的性能,于是花了几天时间来翻阅C语言的资料,我的电脑磁盘里都保存有各种编程语言的电子书(PDF,CHM,TXT等等),由于自己只用脚本语言开发些网络程序,对软件程序开发没兴趣,所以一直没学这些语言,如果我要设计软件程序,唯一考虑的是汇编语言,很多高级语言都是程序猿为了偷懒而将许多东西封装起来,性能当然大打折扣!本来就打算用汇编来写TTD的,但因为汇编太难学了,只好先学C了。看了几天C的资料,简单入门之后写了个测试程序,结果太坑人啦!编译语言 C 完全输给了解释语言 Node!以下是锐某的测试程序源码:

C语言

程序名:test1.c
#include
#include
void main()
{
unsigned long a = 0, b, *c, d = 1000000000;
time_t t1, t2;
c = &a;
t1 = time(NULL);
for(; a < 1000000000;) a++;
t2 = time(NULL);
b = (t2-t1)*1000;/*以毫秒计算耗时*/
printf("t1 = %lu s\nt2 = %lu s\ntimeDiffer = %lu ms", t1, t2, b);
}

程序名:test2.c
#include
#include
void main()
{
unsigned long a = 0, b, *c, d = 1000000000;
time_t t1, t2;
c = &a;
t1 = time(NULL);
for(; a < d;) a++;
t2 = time(NULL);
b = (t2-t1)*1000;/*以毫秒计算耗时*/
printf("t1 = %lu s\nt2 = %lu s\ntimeDiffer = %lu ms", t1, t2, b);
}

程序名:test3.c
#include
#include
void main()
{
unsigned long a = 0, b, *c, d = 1000000000;
time_t t1, t2;
c = &a;
t1 = time(NULL);
for(; *c < 1000000000;) ++*c;
t2 = time(NULL);
b = (t2-t1)*1000;/*以毫秒计算耗时*/
printf("t1 = %lu s\nt2 = %lu s\ntimeDiffer = %lu ms", t1, t2, b);
}

Node.js

程序名:test1.js
(function test() {
var a = 0, b = 1000000000;
console.time('time');
for(; a < 1000000000;) a++;
console.timeEnd('time');
})()

程序名:test2.js
(function test() {
var a = 0, b = 1000000000;
console.time('time');
for(; a < b;) a++;
console.timeEnd('time');
})()

程序名:test3.js
(function test() {
var a = 0, b = 1000000000, c = Array(1000000000);
console.time('time');
for(; a < c.length;) a++;
console.timeEnd('time');
})()

下面我们来比较结果,所有的例子都反复执行几次,通过目测取平均值,如果要更精确的统计结果至少要执行100次以上,然后取平均值,有兴趣的网友可以自行测试。C程序我是用TC2编译的,至于js程序,大家可以将源码保存为相应的程序名,然后放到Node目录,在Node终端输入如下命令即可:node test1.js

本程序用于计算10亿次加法运算所耗的时间,test1.c 总耗时:35000 ms,每次加法运算耗时 35000*1000*1000/1000000000=35 纳秒(1秒=1*1000毫秒*1000微秒*1000纳秒*1000皮秒*1000飞秒*1000渺秒);test1.js 总耗时:6500 ms,每次加法运算耗时 6.5 纳秒。test2.c 总耗时:60000 ms,每次加法运算耗时 60 纳秒;test2.js 总耗时:5300 ms,每次加法运算耗时 5.3 纳秒,同样的操作,C语言所耗的时间是Node的10多倍!!!这里还仅仅测试了加法的运算而已,如果for循环里还有其它一些表达式语句...
PS:测试PC为神州笔记本优雅Q,CPU:N270,1.60GHZ,内存:1G,很老的机器了。

在测试的过程中发现个有趣的现象,test2.c 所耗的时间是 test1.c 60000/35000=1.7倍,主要原因是 test2.c 用变量“d”来代替实数“1000000000”,使用变量内容的过程是先找到变量的地址才能找到内容,时间就花在这上面了。而Node则刚好相反,test2.js 所耗的时间是 test1.js 5300/6500=0.8倍,Node使用变量反而比实数快!锐某不明白她的变量内容是如何取的,于是又写了 test3.js测试了使用对象属性的耗时,通过实例我们可以看到for循环的耗时按快到慢的排序是:for(;z<变量;) < for(;z<对象的属性(str.length|arr.lenth);) < for(;z<整数;),结果很令人郁闷!因为锐某想象中的排序应该是:for(;z<整数;) < for(;z<变量;) < for(;z<对象的属性(str.length|arr.lenth);),似乎 javascript 中for循环的耗时排序就是按后者排的,这个我没测试过,不过测试了其它一些表达式,如:字符串连接,在 javascript 与 php 中,用 arr.push(str) 比 str += str 要快得多,在不同的浏览器中二者的差别更是明显,比如在 IE 这个臭家伙中,两者的差别简直是一个在天一个在地!但是这些表达式在Node里几乎没有太大的差别。

另外锐某还发现个很惊人的东西,那就是大多数人都以为程序语言自带的函数肯定比程序猿自定义的函数快,因为程序语言自带的函数都经过编译好了,而程序猿自定义的在运行过程中一边解释一边执行,事实是否真如此呢,让我们来一探究竟。我们要将一段字符串转对象,大家常用的都是建立一串json格式的字串,然后用程序自带的函数实现对象化,比如Node里就有这么一个 JSON.parse(),但是锐某自己写的方法却能比这个快至少6倍,原理很简单,我们不需要用json这样垃圾的东西,至少我觉得她很垃圾,不但占空间、耗时间!还很麻烦!因为她用了很多符号,而我们要用这些符号必须经过转义。我们可以用另一种格式:
name^value^name^value^name^value^name^value...
str to obj
var arr, obj, l, z;
arr = str.split('^');
obj = {};
l = arr.length;
for(z = 0; z < l; z+=2) obj[arr[z]] = arr[z+1];

锐某觉得 JSON.parse 之所以慢,应该是她要对每个属性的值都要判断是否还有子对象或属性,时间就是这样被浪费掉了!很多封装的东西都要考虑针对各种各样的情况进行处理,如果我们对自己的数据格式或结构很清晰,根本不需要考虑其它的情况,这样就省下了很多的时间。很多网友一开始学一种语言就库呀、类呀、模块呀什么的,别人写的东西都不一定适合自己用,还是按自己喜欢的方法从底层开始写,那样可以对自己的程序为所欲为的操作。如果对别人的程序不是很了解,在使用过程中出现问题就不知道从哪里开始处理。锐某还是那句话,多走弯路多犯错!这会为你积累非常宝贵的经验!

最后说一下关于C语言的东西,锐某对C不是很了解,呀!应该说完全不了解!鉴于上面的性能测试例子,test2.c 使用 for(; a < d;) 竟然比 test1.c 使用 for(; a < 1000000000;) 慢了1.7倍,仅仅使用了一个变量,就有如此大的差距,如果程序中还用了很多变量呢?出于好奇,我又写了 test3.c 进行测试,这个例子用了指针,但性能跟变量也没有多大差别,或许指针不是这样用的吧?如果不是这样用那应该怎样用?一直很不解,C语言为什么要引入指针这种概念?有种脱裤子放屁的嫌疑,用变量就能取到内容为什么还要绕个圈圈通过指针来取进而增加内存空间。当然如果增加内存空间能带来性能的提升还是可以理解的,因为这个时代是以空间换时间的时代。指针究竟能带来多大的性能?我不知道,我唯一知道的是指针存放变量的地址,通过地址能够快速找到变量的内容,如果用变量就多了找地址这一步。指针到底有哪些优点,希望有大牛写些实例来测试一下,锐某感激不尽!

最新文章

  1. 【练习】移动数据---解决null值
  2. sublime Text 2 制表符
  3. 踩到一个Emit的坑,留个纪念
  4. [iOS微博项目 - 2.0] - OAuth授权3步
  5. 2326: [HNOI2011]数学作业 - BZOJ
  6. 利用Php ssh2扩展实现svn自动提交到测试服务器
  7. akka actor 的request-response简单实现
  8. require include php5中最新区别,百度上好多错的。
  9. JavaEE开发之SpringMVC中的自定义消息转换器与文件上传
  10. linux统计cdn日志慢请求
  11. zookeeper 入门系列-理论基础 – zab 协议
  12. 用JavaScript写一个简单的计算器
  13. poj1442 Black Box
  14. 个人作业Week3
  15. noi2017 day2t2
  16. PowerShell发送邮件(587)
  17. C/C++函数调用方式
  18. 【bzoj1044】木棍分割
  19. vmstat工具
  20. 【Web Shell】- 技术剖析中国菜刀 – Part I

热门文章

  1. 【详解】Linux的文件描述符fd与文件指针FILE*互相转换
  2. Java 字符串 String
  3. JVM体系结构之七:持久代、元空间(Metaspace) 常量池==了解String类的intern()方法、常量池介绍、常量池从Perm--&gt;Heap
  4. 面试总结之JAVA
  5. 1021 docker prometheus监控体系
  6. linux记录每个用户执行的命令
  7. 蚂蚁社招Java-第四轮电话面试【技术终面】
  8. C语言指针的一些题目
  9. mybatis 学习五 二级缓存不推荐使用
  10. c# 类间关系